


                  DrWimp

	Version 5.00 (29th November 2008) 


        Andrew Ayre 1995, 1996, 1997, 1999

        Ray Favre 1999-2008

         Manual laid out by Eddie Lord


               Freeware


Conditions of Use

The Dr Wimp package is distributed on an As Is basis, without warranty. No liability can be accepted for any consequential loss or damage, however caused, arising from the use of this package..


The Dr Wimp package (apart from the 3rd party utilities as detailed in the !!ReadMe!! file) may only be distributed as a whole. For conditions of use of these 3rd party applications see their own !Help files.


Distribution of the Dr Wimp package (and programs constructed using the DrWimp library) by third parties:


Freeware. The DrWimp library may be distributed for free and without the documentation, examples, utilities, etc. if it is being used as part of a freeware product. (It would be nice if your documentation acknowledged Dr Wimp - and dont forget that my web-site has a page for links to your Dr Wimp applications, if you let me know .....)

Shareware. Those using Dr Wimp to produce Shareware products must donate 10% of the received income from these products to a charity of their choice within 6 months of receiving the income. The Shareware user-documentation must state prominently that this charity donation is being made and also that Dr Wimp was used to produce the product. The applications name and author should be notified to the Dr Wimp copyright holder but no prior permission or further contact is needed.

Commercial. If you wish to distribute the Dr Wimp package with a commercial product (or distribute commercially a program that uses Dr Wimp) then a specific licence is needed from the Dr Wimp copyright holder.


Public Domain libraries may make a reasonable charge for materials, handling, etc. as long as this does not exceed 2.00 (UK) net for the Dr Wimp package.



The author retains copyright of Dr Wimp, documentation and examples at all times.



Contact addresses



The latest version of DrWimp can be obtained from the web page below or direct from:


Email:		drwimp@rayfavre.me.uk

World Wide Web:	http://www.rayfavre.me.uk/


Alternatively try your local PD library or send a HD disc and return postage to:


Snail mail:	Ray Favre

		26 West Drayton Park Avenue

		West Drayton

		Middlesex

		UB7 7QA

		U.K.



Feedback such as suggestions for future additions, bugs and help requests for how to achieve various things are always welcome, either by E-mail or post.



From 1st May 1999 the support and distribution of the Dr Wimp package is carried out by RayFavre






Section 1. Introduction

1. Prologue

Ever wanted to write high quality multitasking programs?

Cant quite get the hang of manipulating words, bytes, menu structures and message systems?

Have you looked in despair at the amount of programming needed to get a single window on the desktop?


Forget all your worries and write superb applications with great ease; Doctor Wimp is here!


DrWimp - solves all your multitasking worries!



	The DrWimp system consists of:


 The DrWimp library.

 A skeleton blank application.

 This Manual in Impression Publisher and text format.

 Text files with the history, upgrading and security information.

 Template files for standard windows.

 !Fabricate for quick starter application construction.

 Support files for the tutorials.

 !FuncnProc quick browser.

 !Linker BASIC library linker.

 !CodeTemps for converting windows to code.

 Various PD utilities.

 Example applications written using DrWimp, with fully commented code.





This Manual is aimed at getting you up and running with Dr Wimp.

It assumes that you are reasonably familiar with Basic.


If you find you need more detail and a wider scope,

then the charity book Dr Wimps Surgery (over 300 pages, A5 ring-bound)

is available from Ray Favre, whose address appears earlier.


Similarly, if your Basic is a bit rusty,

then another charity book Starting Basic (over 300 pages, A5 ring-bound)

is also available from Ray Favre.



2. An overview

In this Manual all functions (FN) and procedures (PROC) will be referred to as just functions.


The heart of Dr Wimp programming focusses on two provided Basic files: the skeleton !RunImage and the DrWimp library file. These two files are an integrated pair and work in harmony.


The DrWimp library does all the detailed, clever work (and you should leave it strictly alone to do that!) - and the skeleton !RunImage file is where you add Basic coding to build your own application.


The DrWimp library is a collection of Basic function definitions, most of which are intended for you to call from the !RunImage file - just as with a normal Library. All the user-available function names in DrWimp are in lower case and preceded by wimp_ . For example:


PROCwimp_dosomethingamazing(curtain$)


and so this Manual refers to these functions as wimp-functions. (There are also a number of internal functions in the DrWimp library. They have lower case names starting with wint_ and you should ignore these.)


Some of the functions in the DrWimp library need help from you, the programmer. To get your help, the DrWimp library calls a number of functions which have their DEFs in the skeleton !RunImage file. All these functions in the !RunImage also have lower case names, but they are preceded by user_ . For example:


FNuser_givemesomehelp(tomato$)


and so this Manual refers to these as user-functions,


So, the DrWimp Library holds wimp-function definitions (and some internal functions) and the !RunImage holds user-function definitions - and the two files are inextricably linked by the fact that the user-functions are automatically called by functions in the DrWimp library when needed. (The set of user-functions belonging to one version of the Dr Wimp package will normally only work with the set of wimp-functions in the DrWimp library of the same Dr Wimp version.)


Note also that only the DrWimp library can call the user-functions - you must not make calls to the user-functions yourself.


All the user-functions have to be in your !RunImage at all times, regardless of whether they do anything or not, otherwise your application might complain that one of them cant be found.


To save you having to type in the complete set of user-function definitions every time you start the !RunImage of a new application, the Dr Wimp package always comes with a skeleton application called !MyApp. !MyApp is a fully working Wimp application that does nothing - it awaits your added code. Inside !MyApp is the skeleton !RunImage file with all the correct user-function definitions for that version plus its matching DrWimp library file - plus a !Run file and a !Sprites file.


It is strongly recommended that you always start a new application from a copy of  the supplied !MyApp - preserving the original !MyApp as a master.


(There is also the utility !Fabricate which will be introduced later. This enables you to build a rather more useful skeleton application automatically.)


At the start, for a blank application which does nothing (e.g. the supplied !MyApp) all the user-function definitions will be empty i.e. they will look like this:


DEF PROCuser_something

ENDPROC

or:

DEF FNuser_something

=0 :REM** Or some other default return value. **


where the default return value (here, 0) signifies do nothing.


Examination of the skeleton !RunImage listing in the supplied !MyApp application will show the different default return values used. For example, you will find that -1, 1 or a null string are also used. Whatever default return value is shown, it still signifies do nothing as far as the DrWimp library is concerned and it is vital that you do not change these default values in the supplied master !MyApp application.


To develop an application, you therefore gradually add Basic coding to one or more of the user-function definitions in the !RunImage - often calling the wimp-functions, as we will shortly see in Section 2 of this Manual. Also, you will need to arrange for the return values from user-functions of the DEF FNuser_xxxxx type to change from their default return values in specific circumstances i.e. so that Dr Wimp does not do nothing in those circumstances. These actions are fully described in Section2.


As with any Basic program, it is often convenient and structurally better to put specific routines into PROC/FNs and Dr Wimp offers no restrictions here - you can add as many custom DEF PROC/FNs as you like to the !RunImage or in separate libraries. (But dont touch the DrWimp library!)


Section 3 of this Manual - and the utility !FncnPrc, and its StrongHelp equivalent FuncProc (both supplied in the Utils folder) - contains a catalogue of all the user- and wimp-functions available to you, giving details what the parameters mean and, where appropriate, what is returned. (!FncnPrc was written using DrWimp, of course!) The Manual and the above-mentioned utilities are changed for each new release of the Dr Wimp package and will therefore only be valid for their stated version.



The main difference that you will probably notice when developing multitasking Wimp programs is that the program doesnt start at the top and work its way to the bottom. Instead, multi-tasking programs proceed in small loops centred on the wimp poll and which loop happens to be used at any one time depends on whether an icon has been clicked on, or a window dragged, or a menu item chosen, etc. Your coding of your application therefore is mainly to respond to these different events - and you will be pleasantly surprised how easy it is with Dr Wimp.



(The charity book Dr Wimps Surgery mentioned in Section 1.1 gives a detailed introduction to the multitasking Wimp environment.)


3. Handles

In the Wimp environment there is a frequent need to store detailed information in blocks of memory and subsequently to be able to access these blocks quickly and conveniently. For instance, definitions of windows, icons, menus, etc. all need to be stored in memory blocks and access to the blocks is necessary for displaying these items etc.


The most common way of managing this is to store the starting address of a particular memory block in an integer variable and to give that variable a meaningful name i.e. a name related to what is stored in the memory block. Thereafter, we can simply refer to this variable in order to access the memory block. For example, if the definition of the iconbar menu is stored in a memory block whose start address is assigned to the variable iconbarmenu%, then we can simply refer to iconbarmenu% whenever we need to do something with the iconbar menu.


Conventionally, the Wimp calls such identifiers handles. Thus, in our above example, iconbarmenu% holds the handle of the iconbar menu definition - or, for all practical programming purposes, iconbarmenu% is the handle of the iconbar menu.


The Wimp uses the same concept for many other items. For example, to use an outline font at a certain size you need a font handle - which tells the Wimp where to look when it needs the detailed font information. Similarly, when you open a file, an access channel is supplied and it is common to call this the file handle.


Just in case you are starting to get worried that you will need to get involved in a lot of memory details, please rest assured that the whole point of Dr Wimp is to hide all that from you.


You will also be relieved to know that the Wimp allocates memory blocks automatically and that Dr Wimp wimp-functions are specifically designed so that you can choose the handle names yourself and need know nothing about the actual memory locations - nor what they hold.


For instance, the wimp-function to define a simple menu is DEFFNwimp_createmenu(), whose parameters allow you to specify the menu item (and title) text. This wimp-function constructs the menu definition for you behind the scenes, asks the Wimp for a memory block to store it, and then returns the menu handle to you (i.e. returns the start address of the memory block which the Wimp automatically allocated). Typically, you would assign this returned handle directly to a meaningfully named integer variable, with a call similar to:


iconbarmenu%=FNwimp_createmenu()


and you dont need to know what the actual memory address is, nor what it contains.



Similarly, a window called save held in a Templates file can be loaded into your program using FNwimp_loadwindow() - which, again, returns a handle for the loaded window. You might well assign this returned handle to an integer variable called save%. Thereafter, you can simply use save% whenever a reference to the save window is needed.



You will find that most wimp- and user-functions involve a handle to a window, icon, menu, etc. - so you will need to use handles very frequently.



To drive the message home, here is a typical practical sequence:


find% = FNwimp_loadwindow(Templates,find,0)

PROCwimp_openwindow(find%,1,-1)


The first line loads into our program the definition of a window called find which is held in a templates file called Templates. We can assume that it is a window for entering something to find. So, here, we have chosen find% for the handle name and the function duly returns the start address of the memory block (allocated automatically by the Wimp) into find%.


The second line gives an example of how we use the handle. Here, a wimp-function is being called that opens a window. Passed to it in the first parameter is the window handle from the first line - telling it which window to open. The details of the memory block are invisible to us and we need know nothing more about it - the handle is all we need. (The meaning of the other parameters need not concern us here and will be covered later in this Manual.)


Dont forget - it is up to you to choose the name for a handle. It could be anything, eg:


coffee% = FNwimp_loadwindow(Templates,find,0)


Or changed later on, eg:


find% = FNwimp_loadwindow(Templates,find,0)

coffee% = find%


i.e. a handle is an ordinary Basic integer variable.



4. Variables & Strings


As was stressed in Section 1.2, the two files (DrWimp and !RunImage) work as a pair.


One of the implications of this is that any variables that are created in one of the files will be available to both files, unless the variables are made local.


This can be both an advantage and a disadvantage. For instance, it would be a problem if you created a variable in the !RunImage which - unknown to you - is also used in the DrWimp library and might therefore change the variables value unexpectedly.


This potential problem has been largely overcome by localising most of the variables used in DrWimp. However, there are some variables in the DrWimp library that cannot be localised for one reason or another (i.e. they are global variables). In all but two of these cases the global variables in the DrWimp library have been given names that start with a lower case w.


So the simple rule is: when you create variable names yourself, dont start them with a w. (It also makes sense to localise them wherever feasible.)


The exceptions are two global variables which have been specifically designed to be changed by the programmer and do not follow the naming rule above. They are NULL% and UNUSED% and are both set to their default value of FALSE within FNwimp_initialise. The use of these variables by the programmer is covered later - in Section 2.26 and 2.30 respectively.



5. On/Off bits

Throughout Wimp programming, the presence or otherwise of some feature e.g. an icon border, a menu-tick, etc. is often signified simply by the state of a specified single data bit somewhere in the depths of a definition held in memory. If the bit is 1 (set) then the feature is present: if the bit is 0 (unset) then it isnt.


Dr Wimp hides the tricky detail, but it is still essential to give you, the programmer, the power to control such features yourself, via the various wimp-functions.


You will therefore find many instances where Dr Wimp uses the same philosophy of 0/1 for off/on, disabled/enabled, etc. For instance, if you want to put a menu-tick against a menu item you would use:


PROCwimp_menutick(menuhandle%,itemnumber%,1)


and if you wanted to remove the menu-tick you would use:


PROCwimp_menutick(menuhandle%,itemnumber%,0)


i.e. the same wimp-function but with a different third parameter controlling the effect.



Similarly, if you want to check whether or not an icon is already selected you would use:


selected%=FNwimp_geticonselect(window%,icon%)


which will return 1 if the icon is selected, or 0 if not.



You will find that you will rapidly assimilate this simple practice.



(Note that TRUE/FALSE is used instead of 1/0 in a few places in Dr Wimp, but there are special reasons for these exceptions and they should not cause confusion.)


6. System variables

System variables are another important feature of RISCOS and their concept is simple. They are variables which, once created, are available for use by any application running on the computer (i.e. they are super-global). It is also important to note that, unlike ordinary variables created within your application, system variables do not disappear automatically when you quit your application. They remain until the computer is shut down - unless you take specific steps to delete them.


The most common way to create system variables is by using one of two star commands  (*Set or *SetEval)  in a Command or Obey file. Typically, nearly every application creates at least one system variable in its !Run and/or !Boot file. In addition, Dr Wimp provides a pair of wimp-functions to create/delete system variables from within your program. (Star commands can, of course, also be issued from the command line or Task Window.)


The most important use of system variables takes place largely out of sight. It is the system variable called Obey$Dir which is used in the very important job of making sure that an application can run from anywhere, eg: floppy disc, hard drive, CD, etc, whilst still giving the application the essential access to files in the application directory, eg: templates, sprites, message files, etc.


Whenever the !Run file of any application is run (e.g. by double clicking on the application icon) the Wimp automatically puts the full directory path of that !Run file into Obey$Dir - and this system variable retains that value until another applications !Run file is run (likely to be very soon) or the computer is shut down.


It is standard Wimp practice - usually in the very first line of a !Run file - for an applications !Run file immediately to copy this value of Obey$Dir into a new system variable uniquely named for the application e.g. MyApp$Dir for the application !MyApp. This is done immediately, before there is any opportunity for another application to be run. The programmer can then use MyApp$Dir in the application coding as part of file references to application resources e.g when loading window templates, with full confidence that it points to the right place irrespective of where the application is located or what other applications are started subsequently.



System variables can also be useful for other things. For example, if you wrote an application to process user-supplied data you might have to set the maximum size of the data allowed, but you might also wish to gve the user the option to change this maximum size. The limit could be put in the !Run file as the value of a uniquely named system variable - which will be simple for the user to change.


Please note that all system variable values are strings. Further, although there are few restrictions on naming system variables, there are certain conventions detailed in the Style Guide and PRMs. A look inside various application !Run files will soon indicate what is normal.


Dr Wimp provides a small suite of wimp functions to allow you to create, delete, read value of and check existence of system variables from within your application coding - see Section 3.1.

7. Security and post-programming actions

If you are going to distribute your application for others to use you will probably want to maximise the running speed and reduce the memory needs of the finished package. You might also want some security for the listing.


Utilities to help with this are included with the DrWimp package.


As an example, the total size of the !RunImage + DrWimp, for a particular application was 55611 bytes (54.3k). After using the supplied utilities, the resulting !RunImage was 8732 bytes (8.6k) only.


The procedure (as reproduced in the Security file) is:


1. Store your original !RunImage and DrWimp library (the source files) somewhere safe.


2. Link a copy of your !RunImage with the DrWimp library using !Linker. (This eliminates all unused wimp-functions and merges the !RunImage with the remaining wimp-functions to produce a new linked !RunImage. A very useful reduction in disc storage space and some run-time memory needs results.)


3. Compress the linked !RunImage using !StrongBS (or another Basic compression utility). (This can eliminate REMs, abbreviate variable names, concatenate lines, etc. Apart from usually producing a large reduction in the linked !RunImage size and a good run-time speed increase, this process makes it very difficult to read and alter the !RunImage.)


4. (Optional) Turn the linked and compressed !RunImage into an absolute file by dropping it onto !MakeApp3. This renders the !RunImage unreadable.


[Note that !StrongBS has options to allow you effectively to carry out Steps 2, 3 & 4 in a single operation, if you wish]


If/when you want to modify/upgrade your application, you will need to modify (a copy of!) the source version and then repeat steps 1-4.


Step 3 can also help to reduce red herring chasing if you are releasing your application for others to use and you are offering a support and bug-fix service. Human nature being what it is, making the listing difficult to read helps to ensure that you have a known baseline when bugs are reported.



Finally, if you are contemplating using a Basic compiler to convert your Dr Wimp application into machine-code then please see the note on this in Section 2.33.


8. The RISC OS Packaging Project


The Dr Wimp package is now also available within the Risc OS Packaging project managed by Graham Shaw. Details can be found at http://www.riscpkg.org/





Section 2. Tutorials/Guide

Notes

This Section is a mixture of Tutorial and User Guide. It starts off predominantly tutorial and tapers off into user guide as (hopefully) your understanding increases. Sub-sections which include hands on tutorial activities have a ** in their heading line - and are also shown in the Contents list in the same way.


The tutorials use some support files and pre-made templates files. They can be found inside the Tutorials folder. The tutorial template files contain standard windows like Info and Save windows. Feel free to use these in your programs. There are no conditions attached to them.


The Tutorials folder contains copies of the tutorial !RunImage listings as they should appear at various stages. These listings, referenced in the text, are called RI_01 to RI_11 and, for convenience, they are split among three sub-directories Tutor1, Tutor2 and Tutor3 to reflect the fact that - over the whole tutorial - there are three fresh starts from the blank !MyApp listing.

There are also several window templates files and other items and, where appropriate, these too are split among the three sub-directories so that they appear where they are used.


If you are a newcomer to Dr Wimp (even if you are very familiar with Basic) it is highly recommended that you start by working through the tutorial step by step at the keyboard - at least as far as Section 2.5. Before you start, make a copy of the blank master application !MyApp to work on. Put it in a new hard disc directory.


We would highly recommend using !WinEd for editing/creating template files. It is easy to use and it is included with DrWimp. Full instructions can be found in Manual inside the !WinEd directory. However you can use any template editor you wish.



If you get stuck or come across a problem then please dont hesitate to get in touch. Your information could benefit other users.


Most learning is done through experimenting. In most of the tutorials, you will be invited to fiddle and generally muck about with the !RunImage code (not the DrWimp library code!). The worst that can happen through doing this is that your application crashes and is quitted by the Task Manager.


To help you to understand further how to use DrWimp, some example applications are supplied with the DrWimp package, in the Examples directory. They have fully commented !RunImage files so you can study them. A short list of what each demonstrates is given in the !!ReadMe!! file of each. 


(Note that these Example applications will nearly always be using the latest version of Dr Wimp. But, if not, this does not detract from their usefulness as learning aids.)1. Getting going **

With your freshly-copied version of !MyApp visible in a filer window, double-click on it. Nothing should happen. But if you now open the Task Manager display and look at the list of tasks, you should see MyApp at the bottom. i.e. something did happen: the skeleton application really works and is properly loaded into the Wimp - although it currently does nothing and you can only quit from this Task display.


The skeleton !MyApp application

Now open the !MyApp application directory - using <shift-double-click> - and you will see something like this (although there may be minor differences and certainly the window title will not be the same:



You will probably recognise the contents as similar to any simple Wimp application i.e. there are !Boot, !Run, !Sprites, !Sprites22 and Templates files plus a !RunImage file where the main application program resides. Here the !RunImage is a Basic file because that is the programming language the Dr Wimp package uses.


The only unfamiliar file is the DrWimp Basic file. This is the DrWimp Library, already briefly introduced in Section 1.2


The short main program

Now load the !RunImage into !Edit (or your other favourite text editor) and take a look at what is happening. The first ten lines of the listing are:


10 REM>!RunImage - for DrWimp Library Version x.xx **

20 LIBRARY <MyApp$Dir>.DrWimp

30 :

40 appname$=MyApp

50 ver$=1.00 (01-Nov-01)

60 

70 ON ERROR PROCwimp_error(appname$,REPORT$+ at line + STR$(ERL),1,,0,0,Quit +appname$):PROCuser_error: PROCwimp_closedown:END

80 task%=FNwimp_initialise(appname$,7000,360,0)

90 PROCwimp_poll

100 END

(Note: the REM line and date may not be the same as shown here.)


Have a look inside the !Run file as well - and note that its first line of the !Run file effectively copies the system variable Obey$Dir into a new system variable MyApp$Dir, exactly as was described in Section 1.6.


Thus the LIBRARY command in the first working line of the above !RunImage listing uses this system variable and tells the computer that the DrWimp library is also located within the !MyApp application directory - and that it is to be loaded from there into your applications memory space.



The next two working lines puts an application name and version number/date into the string variables appname$ and ver$. These variables are used later on in the listing.



The next line is a global error trap in case an error occurs in your coding. What it does is firstly call a wimp-function PROCwimp_error which displays the error and where it has happened - and then it calls PROCuser_error and PROCwimp_closedown, in turn, to make an orderly exit ending the application. These functions can be safely ignored for now and will be looked at in more detail later on (Section 2.8).


Note: don't add any lines between this error line and the following FNwimp_initialise line, as this could cause problems with the error handling.


The next line is very important:


task%=FNwimp_initialise(appname$,7000,360,0)


Your application cant do anything until it has been called. It registers your application with the Task Manager and it returns a handle for your task (another example of using a handle). Here the handle has been put into task%.


Having said it is important, at this stage of your learning curve it is sufficient to ignore the detail of this wimp-function for the moment - but we need to explain it somewhere and this is the logical place. So you could safely skip the descriptions of each parameter in the following indented paragraphs and come back to them later, if you wish. But dont forget to come back sometime soon!


The first parameter of this wimp-function is self-explanatory. Note that this is the text that will appear in the Task Display window when the application is run, and can be anything. Try it and see - but not all of it will be displayed if it is too long. The Wimp automatically truncates it if it is too long.

The second parameter - which you will see has the variable name wimpmem% in Section 3 of this Manual - specifies how much memory is to be reserved for window definitions (including all the icons in the windows). For the moment it is just set to a largish value. When the application is finished you can reduce it to as low as possible consistent with the application still working fully. (It is unnecessary to go into greater detail about memory needs at this point but Section 2.34 revisits wimpmem% and also covers the important WimpSlot.)


The third parameter is the minimum version number of RISC OS that the application is allowed to run on, multiplied by 100. The default is 360, so the skeleton !MyApp will run on RISC OS 3.60 or better. It is up to you to decide this in the light of what you include in the !RunImage. Most Dr Wimp wimp-functions will operate successfully with RISC OS 3.00 or higher, but a few need higher versions. To use all Dr Wimps facilities RISCOS 3.60 or higher is needed and this is why the default value here is set at 360.


The fourth and final  parameter tells Dr Wimp whether or not you want your application to respond to the desktop save protocol - 1 if you do, 0 if you dont. This is explained in more detail later and, for now, it is left set at 0.


One of the many things that FNwimp_initialise does is to call PROCuser_initialise, whose DEF is a little lower down in the !RunImage listing and currently empty. PROCuser_initialise is specifically intended for you to use for the wide range of application-specific initialistion tasks that are necessary or sensible before wimp-polling starts. For instance, loading window definitions, creating menus, DIMming arrays, declaring  global variables, etc.



The final line of the earlier !RunImage extract (the line before END) calls PROCwimp_poll. This deceptively simple call is the driving engine of most Dr Wimp applications - which makes them multitasking. Effectively, this call sets up a continuous wimp-poll loop controlling all user activities. It is only exited when your application quits for some reason, such as Quit being chosen from the iconbar menu .


These first ten lines are, in fact, the complete main program for many applications.


You may have been expecting more, but you will find that most of your applications will follow this same very short and simple pattern - needing no more than these few lines of main program.



The rest of the skeleton !RunImage file contains all the DEFs of the user-functions. They are all empty at the moment as described in Section 1.2 i.e. they do nothing or return default values. It is the filling of these which makes up the bulk of the programming effort for any application.


As was said above, !MyApp doesnt do much at the moment and there is nowhere for the user to get access to it. So how and where do we start?


Adding an iconbar icon

The best thing to do first is to add an icon to the iconbar.


So, find the (currently empty) DEF PROCuser_initialise, and add the following new line to it:


iconbar%=FNwimp_iconbar(!myapp,,0,1)


i.e. between the DEF PROC line and the ENDPROC line.


(If you use clipboarding to export this line to your !RunImage listing, remember the warning on the cover page about smart quotes!)




This wimp-function creates an iconbar icon and returns a handle for the window that contains it i.e. a handle for the iconbar itself, which is just a special window. So we have assigned the return to a variable with the name iconbar%. (We are not normally interested in the icon number/handle of an applications iconbar icon, because there is only one iconbar icon per application.) You might wish to note in passing that the iconbar window always has the handle value of -2 - so you will find that the return from this particular wimp-function - and thus the value held in iconbar% - is always 2.


The first parameter of our new wimp-function (!myapp, here) is the name of the sprite to use for the iconbar icon. This sprite must already be known to the Wimp - either because it is a standard one automatically loaded on computer start-up, or because it is included in the !Sprites/!Sprites22 spritefiles in the application directory. In this case it is the latter. (Have a look to check!).


The second parameter is the text to place under the iconbar icon, if you want some. If it is an empty string (a null string, as here) then no text is printed. 


We can leave the third parameter for now: just ensure that it is set at a small value - and 0 is a good idea. We will look in more detail at the use of this third parameter later - in Section 2.15.


The final parameter decides which side of the iconbar the icon appears, 0 for left and 1 for right.


Now save the amended !RunImage and double-click on the application icon as usual to run it. You will see that !MyApp now loads to the iconbar in the usual way, with the iconbar icon showing the sprite called !myapp without any text beneath it.



Now do some playing: try changing the sprite name to !draw in the above call and see what happens after saving and re-running it. (!draw is a sprite which will already exist on all RISC OS computers.) Also, try entering some text in the second parameter.  Do you see the difference on the iconbar?


After playing, restore the wimp-function call to that shown earlier.


You will note that you are still only be able to quit the application from the Task Window at the moment.2. First menus **

An iconbar menu

The next thing needed is a menu for the iconbar.


Menus can be created by DrWimp in several ways, but the simplest is by using a shorthand form which is passed as a string. DrWimp translates it into the correct layout in a block of memory for the Wimp to understand.


So, after the previous addition of FNwimp_iconbar, add the following line to PROCuser_initialise:


iconbarmenu%=FNwimp_createmenu(MyApp/Info/Quit,0)


This wimp-function creates a menu definition and returns a handle for it, which here is put into iconbarmenu%.


This is the first time we have added a wimp-function call to the skeleton !RunImage. See how straightforward it is.


The string in the first parameter is the key part and you can see that the string comprises three items of text separated by a /. Each item of text corresponds to an item in the menu-to-be. The first item (MyApp, here) is the menu title, and the following items are the actual menu items, in order. Thus, the top menu item is Info and the second (bottom) one is Quit. In the same manner you can use as many items as you wish - except that the total string length of the first parameter must not exceed 255 characters (or even less if you include the string directly in the Basic line as in the example above). (Other means are provided to get round this limitation and are introduced later.)


The second parameter is the maximum number of menu items allowed to be used in this menu - to allow for a later increase perhaps. It is set to 0 here and this has a special meaning: it just means that the maximum number of items in this menu is to be limited to the number used in the previous string i.e. two menu items, here.


At the moment MyApp doesnt know about the menu, all we have done is set up its definition in memory.


Pressing the <menu> button

Here is where we first introduce a user-function with parameters - one of the most powerful features of Dr Wimp and what sets it apart from being just another library. 


Using an application produced with Dr Wimp, whenever <menu> (the middle button) is pressed over a window belonging to the application (including the iconbar, which is a special window) the DrWimp library automatically calls the user-function:


FNuser_menu(window%,icon%,screenx%,screeny%)


whose definition is in the !RunImage i.e. DEF FNuser_menu().


Moreover, whenever this call is made, the parameters in the user-function (window%, icon%, screenx% and screeny%) are automatically filled, by Dr Wimp, with the current appropriate values. Thus, in our !MyApp example, if you press <menu> over the iconbar icon, FNuser_menu will be called with the iconbar window handle in the parameter window%.


Similarly, if we pressed <menu> over a particular icon in an ordinary window, then FNuser_menu would be called with the window handle in window% and the icon handle (the icon number) in icon%.  (If <menu> is pressed over a window but not over an icon i.e. over the window background, the parameter icon% would be set to 1.).


And, in all cases, the parameters screenx% and screeny% will contain the x/y position of the mouse pointer when the mouse-click took place - in screen coordinates (see later).


In order to display a menu when <menu> is pressed over a particular window/icon combination, we simply have to change DEF FNuser_menu to return the handle of the menu that we want to open, otherwise return a 0.


It is easier done than explained! So, move down to DEF FNuser_menu in the !RunImage and change it to:


DEF FNuser_menu(window%,icon%,screenx%,screeny%)

return%=0

CASE window% OF

	WHEN iconbar% : return%=iconbarmenu%

ENDCASE

=return%


To ensure you understand the sequence of events properly in this first look at this type of userfunction, lets detail what will now happen, step-by-step:


i) The user presses <menu> over the iconbar icon;

ii) DrWimp automatically calls FNuser_menu with the parameters window%, icon%, screenx% and screeny% set, respectively, to the window and icon handles over which the <menu> mouse-click took place, plus the mouse x/y values. Thus, here, window% will contain the iconbar window handle (-2).

iii) DEF FNuser_menu has been altered by you to return the menu handle iconbarmenu% (whose definition you have already created) when window%=iconbar%, so DrWimp will receive this returned handle and duly display the particular menu you want.

Note that in all other circumstances the default return value of 0 is returned and Dr Wimp will do nothing.


In this iconbar case the values in icon%, screenx% and screeny% are irrelevant  - because there is only one icon-per-application on the iconbar and therefore its window handle is sufficient identity within the application. But in general, as we will see, other CASE statements (and/or IF constructs) could be added to pinpoint precise window/icon/mouse position combinations. In other words, we use the CASE statements as a filter.


Using Dr Wimp, the user-functions with parameters are the main focus of the programmer and they all operate in a similar way to the one described above - so it is very important for you to understand their role. 


Try running the !MyApp application now. The iconbar menu will duly appear if <menu> is pressed over the iconbar icon.



Selecting a menu item

OK, the menu is displayed, but selecting any of its items does nothing yet.


When a menu item is selected, DrWimp automatically calls another user-function:


PROCuser_menuselection(menu%,item%,font$)


As before, the parameters menu% and item% tell you which menu and which item from it has been selected. (Ignore font$ for now. We return to it later - in Section 2.18.) This time, the user-function is a PROC, so nothing is returned. Instead you only have to act on the selection made by the user.


Therefore, if the Quit item is chosen from our iconbar menu, PROCuser_menuselection will be automatically called with menu% containing the iconbar menu handle (iconbarmenu%) and item% containing 2. (The top-most item is number 1.)


So, to respond to this selection, change PROCuser_menuselection to look like:


DEF PROCuser_menuselection(menu%,item%,font$)

CASE menu% OF

	WHEN iconbarmenu%

  	CASE item% OF

  		WHEN 2 : PROCwimp_quit(0)

  	ENDCASE

ENDCASE

ENDPROC


Thus, when we select Quit from our iconbar menu - and only in that case - we call PROCwimp_quit with an argument of 0. This wimp-function call quits the application.


If you now resave and run the application you will be able to confirm that it does indeed quit when you select Quit.



Try adding some more items when creating the menu. Dont forget to increase the 2 (the Quit item) in PROCwimp_menuselection accordingly though! For instance, try getting the computer to make a beep when you select one of the items. VDU7 would be ideal for this. Note that there is no need to change the last parameter (0) in FNwimp_createmenu (and we will return to this later). Menus may also be created automatically from arrays and message files. See Section 2.18 for details.


Before moving on, note that displaying the menu and making a selection from it were handled by two independent programming actions. We were able to check that the menu was displayed OK before tackling what to do with it. This is typical of wimp programming: features are added by smallish self-contained routines. This has considerable advantages for the programmer, who can (largely) thoroughly check one step before proceeding to the next - and go back and change one step with clear interfaces to the preceding and following steps.


3. First windows **

Windows are, of course, the main visual tool of Wimp programs, so lets have a look at how Dr Wimp handles them. We will start with the very common info window.


Adding an Info window

An info window is usually accessed from the Info item on the iconbar menu. In the Tutorials folder (Tutor1 sub-directory) you will find the file Template1. Copy this into the !MyApp application directory and rename it as Templates. You can examine it if you want by loading it into !WinEd. (At the moment, we will only be using windows which have been designed in a window template editor - such as !WinEd, which is included in the package. A template editor puts its results into a templates file - and one file can hold several window definitions.)


In !MyApps !RunImage listing add the following line below FNwimp_iconbar (above FNwimp_createmenu):


info%=FNwimp_loadwindow(<MyApp$Dir>.Templates,info,0)


This wimp-function loads into the applications memory the definition of a window from the templates file, whose full pathname is given in the first parameter. The second parameter is the name of the particular window as named in the templates file.



The last parameter tells DrWimp where to find any sprites that you may have used in designing the window. A 0 means look in the Wimp sprite pool, and this is the most common option. Alternatively, a handle to a sprite area could be used instead and would mean look in this sprite area as well. Our Info window uses just one sprite (the Dr Wimp logo) and it is included in the !MyApp !Sprites/!Sprite22 files - which means that it will be loaded automatically into the sprite pool on application start-up. Thus setting the final parameter to 0 is appropriate here.



The function FNwimp_loadwindow returns a handle for the window which we have assigned to the variable info% - whose name, again, tells us what it is.



Attaching a sub-menu/window

Now we need to modify the iconbar menu to take into account the info window. We want Item 1 of the iconbar menu to lead to this window, just like a sub-menu.


This is very simple to do and, in fact, RISC OS (and Dr Wimp) allows submenus to be either normal submenus or windows. Using Dr Wimp, all you have to do is attach a submenu/window to the required menu item using the following wimp-function in a line such as:


PROCwimp_attachsubmenu(iconbarmenu%,1,info%)


So, add that line after the line with FNwimp_createmenu in it - as the menu and the attachment need to exist before you can attach anything.


The first parameter of PROCwimp_attachsubmenu is the handle of the menu to which the submenu is to be attached: the second parameter is the particular item on that menu to which the submenu is to be attached (in this case 1 which is the top item) and the third parameter is the handle of the sub-menu to attach (or the handle of the window to attach). In this case it is the handle to the info window.


And thats it!


Re-load !MyApp and you will now see that the first (Info) menu item now has the familiar arrow-head against it, indicating that a submenu/window is attached. If you move across this arrow-head the info window will appear.



Adding/changing icon text

You will see in the info window that the Author and Version fields have default information in them. It is very simple to change this, and the technique that we are about to describe can be used for any icon that has text, whether it is a Radio button, a default action button, or just a label icon - provided the icon text is defined as indirected, (see !WinEd). You only need to know the window handle and the icon number/handle.  We will be changing the text in icon numbers 1, 2 and 4 below. (You can find the icon number by loading the Templates file into !WinEd, opening the info window and moving the pointer over the icons. The !WinEd  Monitor window at the top right of the screen will give you the number of each icon.)



First of all we will look at the Author field. This is icon number two. Add the following line just before ENDPROC in PROCuser_initialise:


PROCwimp_puticontext(info%,2, Joe Bloggs 1996)


Replace Joe Bloggs with your own name (there is a limit on the length of the string though). This is fixed by the indirected size and the physical size of the box. These can easily be changed using !WinEd.



Now for the Version field, which is icon number 4. It is common practice to display the version number and date in the form X.XX (Dt-Mth-Yr), eg:


	1.42 (16-Oct-99)


So add the following line just before ENDPROC in PROCuser_initialise (changing the date to whatever you wish):


PROCwimp_puticontext(info%,4,1.00 (29-Mar-98))


By now, you will see that the parameters to the function are quite simple. From left to right they are: the window handle, the icon number/handle, and the text to put into the icon.


Check that the application works as it is supposed to and then try using the same method to change the Purpose field (icon number 1) to something more interesting.



By the way, as long as the window has been loaded, you can change icon text in the above fashion at any time. If the window is open when you do it, the change will be displayed straightaway. If not, the change will show when you next display the window.


Note that, in icons, the Wimp only allows text to be displayed. So any numbers need to be converted to strings before putting into an icon - and often need to be converted back to numbers after reading from an icon.



[Your !RunImage listing should now look like listing RI_01 in Tutor1 (apart from the REM lines, perhaps). Do not destroy it as the following sections continue the tutorial from this stage.]



4. Window & icon control **

Most applications have a main window that appears when the user clicks on the iconbar icon. This is easy to implement with Dr Wimp.


Pressing the <select> or <adjust> button

Copy Template2 from the Tutorials folder (Tutor1 sub-directory) into the !MyApp application directory, and rename as Templates thus overwriting the previous one.


Add the following line below FNwimp_loadwindow to load in a second window:


main%=FNwimp_loadwindow(<MyApp$Dir>.Templates,main,0)



Whenever the <select> or <adjust> mouse button is pressed over one of !MyApps icons, the user-function PROCuser_mouseclick is automatically called, passing to it the window handle, the icon number, a number relating to the mouse button pressed and the work area coordinates the pointer was at. These are in window%, icon%, button%, workx% and worky% respectively. (It is useful to remember that PROCuser_mouseclick is used to respond to <select> or <adjust>, whereas FNuser_menu is used for <menu> presses)


Therefore, in !RunImage, change PROCuser_mouseclick so that it looks like:


DEF PROCuser_mouseclick(window%,icon%,button%,workx%,worky%)

CASE window% OF

	WHEN iconbar% : PROCwimp_openwindow(main%,1,-1)

ENDCASE

ENDPROC


As you can see, when a mouse button is pressed over the iconbar icon (i.e. in the window whose handle is iconbar%) then PROCwimp_openwindow is called , which here is used to open the window whose handle is main%.


The first parameter of PROCwimp_openwindow is the handle of the window to open. The second means open the window in the centre of the screen, and the third parameter means open it on top of all other windows.


If the second parameter was 0 then the window would open where you last left it (ie. before it was closed), or if it was being opened for the first time then it would open as it was positioned in the templates file. If the second parameter was 2 then the window would open centred on the mouse pointer. (Useful if you want to open save windows below the pointer so the user doesn't have to move the pointer very much to start dragging the file icon.)


If the third parameter was -2 then the window would open behind all the others. If the third parameter was -3 then the window would at the current stack position. If this third parameter was another window handle then the opening window would open behind that window - very useful when panes are involved (see Section 2.6). Finally, if the third parameter was -4 the window would open behind the backdrop i.e. the window would be open but hidden - a rather special usage which need not concern us here.


Run !MyApp and check that it works, then try changing the values of parameters of PROCwimp_openwindow and see what happens.


Note:  PROCuser_mouseclick will also respond to mouse-clicks over a window's background, if the latter is given a button type of Click in a template editor - see !WinEd. In such cases, the icon number passed in  PROCuser_mouseclick will be -1.



Our new window main% is divided up into three sections. We will now use each section to demonstrate one or more aspects of icon control using DrWimp. The icon number for each icon can be found by loading the templates file into !WinEd as described before.


The first section contains a writable icon (icon number 1) which can take up to 19 characters (+1 terminator character, making a total of 20 - the value set here). This value is set by using !WinEd and changing the Max text length for this writable icon.


Reading icon text and writable icons

Entering text into writable icons is fully automated by the Wimp. Click in the writable icon and the caret will appear so you can enter some text. Note also that this action automatically gives the window the input focus (if it hasnt already got it)  - signified by the title bar changing to a cream colour. There is more on this a little later.


What we want to do is enter some text from the keyboard into the writable icon (Icon 1) and when OK is clicked on (icon number 2), the text is read from the icon and copied into the icon below (icon number 11). As an alternative action, we want to achieve the same copying result by pressing <return> when the caret is in the writable icon.



The wimp-function FNwimp_geticontext reads text from icons i.e. it is the complement of PROCwimp_puticontext. The parameters passed are the window handle and the icon number. The function returns the text in a string. All that we need to do then is use PROCwimp_puticontext to put the text into the other icon.


So, alter PROCuser_mouseclick to look like:


DEF PROCuser_mouseclick(window%,icon%,button%,workx%,worky%)

CASE window% OF

WHEN iconbar% : PROCwimp_openwindow(main%,1,-1)

WHEN main%

	CASE icon% OF

  	WHEN 2

  	text$=FNwimp_geticontext(main%,1)

  	PROCwimp_puticontext(main%,11,text$)

  	ENDCASE

ENDCASE

ENDPROC


Re-load !MyApp and check that this first step works. Read this part of the above routine as When the window is main% and the clicked icon is 2, read the text in icon number 1 and write it into icon number 11. The OK button (icon number 2) has the yellow trough/border around it and is called the Default Action icon.


Indirected icons

Note that, although you can read text from any icon, you can only put new text into icons if they are what is called indirected. You can make an icon indirected by turning that option on when editing the icon in a template editor. At the same time, you need to decide the maximum number of characters you want to use - then add 1 to it (because the Wimp always automatically adds a string terminator). This is value is entered in the appropriate place in the template editor.


So, making an icon indirected with a maximum value of 11 allows a user to put up to 10 text characters into the icon.


If you have an icon whose text you are never going to change during the program run (e.g. a label) then you can make it non-indirected to save memory - but note that the maximum size of non-indirected text is 12 (11 characters plus terminator).



Keyboard keys

The above deals with clicking the OK button, and now we are going to make the action of pressing the keyboards <return> key (when the caret is in the writable icon) do the same as clicking on the OK button.


The <return> key is just one of the keys on the keyboard, so before looking at our immediate issue we need to divert for a moment to look more generally at what happens when any keyboard key is pressed whilst the caret is in a writable icon.



The detailed result(s) of a keypress are programmer-definable via the validation string  (see Section 2.28 later) which is set in the definition of the writable icon.


Briefly, the validation string can, among other things, control which characters (typed at the keyboard rather than entered by PROCwimp_puticontext) are allowed to appear in the writable icon, how the caret moves between writable icons (when there are more than one in a window) and which keypresses will be notified to our task by the Wimp if/when they occur. These issues can be controlled separately by the validation string but there are sensible default arrangements if you opt to do nothing.


The main points to note for this stage of our tutorial are that, by default (and with only one writable icon in the window), all printable characters entered at the keyboard will be displayed in the writable icon but only the pressing of the <return> key will be notified to our task by the Wimp (so that we can respond to that, if we wish).



Whenever a keypress is notified to a Dr Wimp task, FNuser_keypress is automatically called -and passed to it is the window handle and the icon number holding the caret. Also passed to it is the ASCII number of the letter/number/symbol pressed, which for <return> is 13 (&0D).


In itsempty state FNuser_keypress returns 0. If we use the keypress to do something (other than simply appearing in a writable icon) then we must return a 1. This is to stop the keypress being notified to other tasks by the Wimp.


So alter FNuser_keypress to:


DEF FNuser_keypress(window%,icon%,key%)

return%=0

CASE window% OF

WHEN main% :

  CASE icon% OF

  WHEN 1 :

    IF key%=13 THEN

      text$=FNwimp_geticontext(main%,1)

      PROCwimp_puticontext(main%,11,text$)

      return%=1

    ENDIF

  ENDCASE

ENDCASE

=return%


Note that the writable icon is icon number 1, which is the location of the caret when <return> is pressed.


This added code is very similar to what we added in the mouse-click case - which is what you might expect as we want the same action.


It may look to be a lot of code for what it actually does, but it has been written so that it is easy to add more pieces of code for lots of windows/icons (or many different key press codes) with the minimum amount of effort and minimum risk of problems. Also it encourages putting the code onto several lines, making easier to read.



Selecting/De-selecting icons

There is just one thing missing now. When you click on the OK icon it presses in briefly. When you press <return> it doesnt. It is much more reassuring for the user to see the OK button press in in both cases, because then they know exactly what has happened. Pressing in is simply a behind-the-scenes trick whereby one icon is used for the deselected state and another for the selected state.



DrWimp provides a wimp-function, PROCwimp_iconselect, to select/deselect an icon. So, to achieve our required effect all we have to do is select the OK icon, copy the text, then deselect the OK icon.


In DEF FNuser_keypress(), alter the part between IF key%=13 THEN and ENDIF so that it looks like:


IF key%=13 THEN

	PROCwimp_iconselect(main%,2,1):REM** Selects the icon. **

  	text$=FNwimp_geticontext(main%,1)

  	PROCwimp_puticontext(main%,11,text$)

  	return%=1

  	PROCwimp_iconselect(main%,2,0):REM** De-selects the icon. **

ENDIF


Re-run !MyApp and check it works. 



PROCwimp_iconselect uses a format which is common to several wimp-functions in DrWimp. It has three parameters window%, icon% and state%. The first is the window handle, the second is the icon number and the third chooses the desired action: here, the selection state (0 to deselect: 1 to select and 2 to toggle from one to the other). In this case, icon% is 2 for the OK icon.


If you removed the PROCwimp_iconselect(main%,2,0) call then the OK button would stay pressed in. Try it and see.



On fast machines this simulated short press in may be too quick and just produce a flicker. You may therefore like to add the following line, maybe temporarily, just above PROCwimp_iconselect(main%,2,0):


PROCwimp_pause(1)


This wimp-function is described in Section 3. The above call will introduce a pause of 1 second into the <return> action.



Keypress character codes

Although we dont need any more detail about keypresses for the tutorial, this is a useful point to delve a little further into the general handling of keyboard presses.


As seen above, the default arrangements for a writable icon i.e. assuming that no validation string is added by the programmer, is that all key presses will appear in the writable icon (if they are printable) but only a press of the <return> key is specifically notified to our task by the Wimp - via FNuser_keypress(window%,icon%,key%).


If we want to be notified of more keypresses than this then the validation string - and, in particular, its K-command - needs to be used.


The most important K-command in this respect is the Kn command. If this is entered into the validation string of a writable icon then all keyboard presses will be notified via FNuser_keypress(), with the value of its parameter key% being set to the appropriate keycode used by the Wimp - which is the normal ASCII code for alphanumeric keys and the codes as shown in the table below for the non-alphanumeric keys.


If using Kn it is then a matter of coding the contents of FNuser_keypress() carefully to respond to whichever key presses you wish and to signal these uses (and only these uses) with the correct return value of 1 for the user-function. If you are not responding to some keypresses - and that will be the normal case - it is important that unused keypresses return the value 0 from the user-function.


As an important example, if you examine the following table you will see that the key F12 is a perfectly valid keypress and it will appear as the value &1FC in the parameter key% (if Kn is used). In virtually all cases it will be important that your application does nothing in response to this key - because it traditionally gives access to the Command Line. And there are other keys with common special uses.


The safest type of coding when using Kn is to try to give priority to filtering the key% value before anything else. For instance, using the CASE structure with key% first:


DEF FNuser_keypress(window%,icon%,key%)

return%=0

CASE key% OF

WHEN <wanted codes>

  CASE window% OF

  WHEN <wanted window handles>  

    CASE icon% OF

    WHEN <wanted icon handles>


      <action>

      return%=1


    ENDCASE

  ENDCASE

ENDCASE

=return%


Non-alphanumeric key press codes


Key		Alone		+Shift		+Ctrl		+Ctrl & Shift


Escape	  	 &1B		&1B		&1B		&1B

Print (F0)	&180		&190		&1A0		&1B0

F1-F9	      &181-189	      &191-199		&1A1-1A9	&1B1-1B9

Tab		&18A		&19A		&1AA		&1BA

Copy	  	&18B		&19B		&1AB		&1BB

Left arrow	&18C		&19C		&1AC		&1BC

Right arrow	&18D		&19D		&1AD		&1BD

Down arrow	&18E		&19E		&1AE		&1BE

Up arrow	&18F		&19F		&1AF		&1BF

Page Down	&19E		&18E		&1BE		&1AE

Page Up	        &19F		&18F		&1BF		&1AF

F10-F12 	&1CA-1CC	&1DA-1DC	&1EA-1EC	&1FA-1FC

Insert  	&1CD		&1DD		&1ED		&1FD	


Radio icons

Returning now to our Tutorial, in our main% window, the second section contains two radio buttons labelled Choice1 and Choice2 and a button labelled Swap. Both the radio buttons have the same ESG group.  In one ESG group, only one radio button can be selected at any one time, so clicking <select> on one radio icon within the group de-selects any others in the same ESG group. 


Thus, here, when the user clicks <select> on Choice1 it becomes selected and Choice2 becomes deselected, and vice versa. Also, here, if you press Swap the selected and de-selected radio icons swap over, as if you had clicked on the de-selected one. The Swap button has an icon number of 6.


If you write an application with radio buttons, you may have to keep track of which ones are selected. For !MyApp we will use the integer variable choice% - which will be set to either 1 or 2 depending on which radio button is selected. When you first load !MyApp we will have it so Choice 1 is selected, so we will set choice% to 1 at the start.


Although you can set the radio icon to select when editing the templates it is always best to do this in your program so there is no chance of problems if a user fiddles with the templates file. In fact, this is good practice for all initial settings.


Then, when Swap is clicked, we look at choice% to decide which to select and which to de-select.


So, just before ENDPROC in PROCuser_initialise, add the following lines to make the initial settings:


choice%=1

PROCwimp_iconselect(main%,4,1)

PROCwimp_iconselect(main%,5,0)


Then, after PROCwimp_puticontext(main%,11,text$) in PROCuser_mouseclick, before the ENDCASE, add the following:


WHEN 6 :

IF choice%=1 THEN

  	PROCwimp_iconselect(main%,4,0)

  	PROCwimp_iconselect(main%,5,1)

ENDIF

IF choice%=2 THEN

  	PROCwimp_iconselect(main%,4,1)

  	PROCwimp_iconselect(main%,5,0)

ENDIF

choice%+=1

IF choice%>2 THEN choice%=1

WHEN 4 :

choice%=1

WHEN 5 :

choice%=2


It is mostly self-explanatory. The sequence choice%+=1:IF choice%>2 THEN choice%=1 toggles choice% between 1 and 2 to keep track of which one is selected.


This middle section of the main% window is a bit over-the-top (and the above coding is not elegant) but it is a clear demonstration of selecting and de-selecting radio icons.



There is a small problem with radio buttons. Try pressing <adjust> over a selected one. You will find that it becomes deselected. Having none of the radio buttons selected may be an undesirable situation. It is quite simple to solve this. If you have a look at PROCuser_mouseclick you will see that the third parameter is called button%. Basically, if button%=4 then <select> was pressed. If button%=1 then <adjust> was pressed. There are also numbers for combinations of mouse buttons, but we need not concern ourselves with that at the moment.


So alter the WHEN 4 and WHEN 5 parts so they look like:


WHEN 4 :

IF button%=1 PROCwimp_iconselect(main%,4,1)

choice%=1

WHEN 5 :

IF button%=1 PROCwimp_iconselect(main%,5,1)

choice%=2


Re-load !MyApp and make sure that you now always have a radio icon selected.


Note: the act of clicking on a radio icon with any mouse button will automatically deselect the others in the same ESG group, so thats why we only set the icon clicked on with <adjust> and not deselect the other here. However, note also from the above examples that using PROCwimp_iconselect() to select a radio icon does not, in itself, de-select others in the same ESG and you would need to carry out deselection separately - with further calls to the same wimp-function for the other icons with the same ESG.


Enabling/Disabling icons

The last section of the main% window has an option icon and two buttons. What we want to do with this section is control the option icon using the buttons, in much the same way as for the radio icons. There is a difference though, in that at any one time, we will want to disable (grey out) one of the buttons - because, for instance, if On is already chosen there is not much point in clicking on On . If the user clicks on a disabled icon, then the mouse click is ignored, and PROCuser_mouseclick is not called.


The function PROCwimp_iconenable(window%,icon%,state%) follows the common DrWimp practice: it allows you to enable an icon, or disable (grey out) it - or to change its current state from one to the other.


For example, in our tutorial program, just before ENDPROC in PROCuser_initialise, add the following to make the initial setting of the Off button:


option%=0

PROCwimp_iconenable(main%,10,option%)


option% is going to be used to record the state of the Off button option icon - which is icon number 10. So, placing option% (now 0) in the third parameter in the above call disables the Off button. If we had used 1 the icon would be enabled - and if we had used 2 the state of the icon would be changed i.e. if it was enabled it would be disabled - and vice versa i.e. toggled between the two states.


Now modify PROCuser_mouseclick to:


WHEN 5 :

IF button%=1 THEN PROCwimp_iconselect(main%,5,1)

choice%=2

WHEN 9 :

PROCwimp_iconenable(main%,9,0):REM** Disables icon. **

PROCwimp_iconenable(main%,10,1):REM** Enables icon. **

PROCwimp_iconselect(main%,8,1)

option%=1

WHEN 10 :

PROCwimp_iconenable(main%,9,1)

PROCwimp_iconenable(main%,10,0)

PROCwimp_iconselect(main%,8,0)

option%=0

WHEN 8 :

IF option%=0 THEN

  	PROCwimp_iconenable(main%,10,1)

  	PROCwimp_iconenable(main%,9,0)

ENDIF

IF option%=1 THEN

  	PROCwimp_iconenable(main%,10,0)

  	PROCwimp_iconenable(main%,9,1)

ENDIF

option%=ABS(1-option%)


You should be able to see how it works, and know exactly what will happen when you click on the icons. Run it and check.


(If you want to check if an icon is currently enabled/disabled, then FNwimp_geticonenable() returns 0 if the icon is disabled and 1 if the icon is enabled.)


As you can see, PROCuser_mouseclick is probably one of the most important userfunctions and will often contain most of the code to control your application.



Changing the window title

You must have noticed in many applications (eg. !Edit, !Draw) that as soon as you have some unsaved data, the title of the window has an asterisk added to its end. Using DrWimp this is quite easy to achieve, once you know that you have some unsaved data..........


 Note: In order to change the window title it must be indirected. This is set up using a template editor like !WinEd, similar to setting up indirected text for icons.


For !MyApp we will assume that we have some unsaved data when, in the main% window, OK or <return> is pressed.


FNwimp_getwindowtitle returns a string containing the window title and its complement is PROCwimp_putwindowtitle which changes the title to the supplied string. All we have to do therefore is read the title, add  * to the end and put it back.


So change the WHEN 2  section in PROCuser_mouseclick to become:


WHEN 2 :

text$=FNwimp_geticontext(main%,1)

PROCwimp_puticontext(main%,11,text$)

r%=1

title$=FNwimp_getwindowtitle(main%)

IF RIGHT$(title$,2)= * r%=0

IF r%=1 PROCwimp_putwindowtitle(main%,title$+ *)


The existing title is read into title$ and checked to see if * has already been added (we dont want to add  * each time OK is pressed!). If it hasnt then the asterisk is added. You should now be able to alter a part of FNuser_keypress so the title changes when <return> is pressed as well.


If your program has a save feature (details on how to do that coming up later) then when the data has been saved you can remove the asterisk from the title.


Dont forget to allow for the extra space-plus-asterisk (two characters) when setting the maximum allowable length of the indirected title text!



Banners

Just a quick thing for you to try while we are dealing with windows: quite a few programs have a temporary window that appears in the centre of the screen when it loads. It stays there for a bit before closing again. This is called a banner.


Using banners is a good way of announcing your program or reminding people to register it.


DrWimp has a function that handles banners for you. While the banner is on the screen, you can still use the desktop and your application.



This is how you use it: just before ENDPROC in PROCuser_initialise enter the following line:


PROCwimp_banner(info%,3)


When you load !MyApp, the info window will appear for three seconds in the middle of the screen. The info window isnt really suitable, so you can design your own window, load it in, and put things like version number and date, etc in using PROCwimp_puticontext.



The caret and input focus

As has been demonstrated, if you click on a writable icon it gains the caret, and the window it is in gets the input focus - signified by the title bar changing to a cream colour.


But there will be many occasions when you want, automatically, to give the input focus to a window you have just opened and place the caret in a specific writable icon. This is done by using PROCwimp_putcaret(window%,icon%,index%) to specify the window and icon in which the caret should be placed.


If you wish to place the caret in the icon text more precisely then the third parameter, index%, can be set to the number of characters from the start (left) of the text to the required caret position. That is, a value of 0 will place the caret in front of the text; the value 1 will place it between the first and second character from the lrft; and so on. The special value of -1 will place the caret after the last (right-most) character - and this will also happen if the index% value is longer than the text string.

It may be obvious, but it is worth noting that the window needs to be open before this particular wimp-function can be used.


There may also be occasions when one of your windows will not have a writable icon but you want to give the window the input focus anyway. This is effected by calling PROCwimp_putcaret using the appropriate window handle but with the icon parameter set to -1. This gives the window the input focus without placing the caret. (index% also needs to be given a value in this case, even though it will be ignored.)


[Your !RunImage listing should now look like listing RI_02 in Tutor1 (apart from the REM lines, perhaps). Do not destroy it as the following sections continue the tutorial from this stage.]



5. Doing more with menus **

So far we have only got a simple two-item menu with an info window leading, like a sub-menu, from Item 1. (Windows used as sub-menus are often called dialogue boxes.) There is a lot more you can do with menus. This part looks at submenus, ticks, greying out, dotted lines, changing menu text, writable menu items and showing keyboard shortcuts with menu items.


First of all, lets create a menu for our main window.


Just below the existing FNwimp_createmenu line, add the following lines:


menu$=MyApp/Info/Item 2/Item 3/Item 4/Save

mainmenu%=FNwimp_createmenu(menu$,0)

PROCwimp_attachsubmenu(mainmenu%,1,info%)


And cause this menu to open in the main window by altering FNuser_menu so it looks like:


DEF FNuser_menu(window%,icon%,screenx%,screeny%)

return%=0

CASE window% OF

	WHEN iconbar% : return%=iconbarmenu%

	WHEN main% : return%=mainmenu%

ENDCASE

=return%


When you press <menu> anywhere over the main window, you should get a menu with 5 items. The first item should have a small arrow-head to the right of it - showing that it leads to a submenu. ( In fact, as we have said, it can be a sub-menu or a window - just supply the appropriate handle.) In this case we have attached the info window.



Now create another menu by adding the following line above the menu$=... you have just entered:


i3menu%=FNwimp_createmenu(Item 3/Help/Tick me!,0)


You can see from the title of this menu that it is obviously a submenu for Item 3 on our main menu. So, we need to use PROCwimp_attachsubmenu again - but this time attaching a menu handle rather than a window handle.


Therefore, immediately below PROCwimp_attachsubmenu(mainmenu%,1,info%) add:


PROCwimp_attachsubmenu(mainmenu%,3,i3menu%)



Run !MyApp and take a look at the menu. And that is all there is to it!


Here is another example:


Before the i3menu%=... line add the following:


tickmenu%=FNwimp_createmenu(Tick me!/Bored/Dull/Waffle,0)


And after the i3menu%=... line add:


PROCwimp_attachsubmenu(i3menu%,2,tickmenu%)


which results in a sub-menu attached to a sub-menu item. Thus you can see that it is quite painless to build up long and/or complex menu structures.



Choosing items from a sub-menu is exactly the same as from a menu: in both cases Dr Wimp causes PROCuser_menuselection to be called. The only difference is that, for a sub-menu selection, the parameters placed in PROCuser_menuselection will be from the sub-menu where the actual selection is made. For example, if the Bored item from the tickmenu% sub-menu is selected, the values passed by Dr Wimp in the PROCuser_menuselection call will be the value of tickmenu% in the menu% parameter and 1 in the item% parameter. i.e. the selection is treated as if the tickmenu% menu stood alone. (Note: Selections from the sub-menu of a font menu are handled slightly differently - see Section 2.18)



When you first create a menu, it will have no ticks by the side of any items, no dotted lines separating items, and none of the items are greyed out. If you want any of these features they have to be set up after the menu has been created (and set up again after any menu re-creation, see later).


PROCwimp_menutick(menu%,item%,state%) is multi-functional and uses the now-familiar Dr Wimp format to put or remove a menu-tick or to toggle between these two states. If the third parameter is 0 any menu-tick against the item is removed: if it is 1 a tick is placed: and if it is 2 the existing menu-tick status is reversed.


So, add the following line to the end of PROCuser_menuselection and try it out:


IF menu%=tickmenu% AND item%=1 THEN PROCwimp_menutick(menu%,item%,2)


(In addition, FNwimp_getmenutick allows you to check whether or not a menu item is already ticked.)



PROCwimp_menuenable works in exactly the same way to allow you to enable/disable menu items - or to toggle between these two states. (And FNwimp_getmenuenable allows you to check whether or not a menu item is already enabled.)


At the end of PROCuser_menuselection, add the following lines and try it out:


IF menu%=mainmenu% AND item%=2 PROCwimp_menuenable(menu%,3,0)

IF menu%=mainmenu% AND item%=4 PROCwimp_menuenable(menu%,3,1)


Similarly, PROCwimp_menudottedline(menu%,item%,on%) puts/removes a dotted line on the menu below the item specified. If on% is 1 a dotted line is added: if on% is 0 a dotted line (in that position only) is removed. (No toggling option this time.) Try it out by adding the following after i3menu% is created:


PROCwimp_menudottedline(i3menu%,1,1)


(Also, FNwimp_getmenudottedline() allows you to check whether or not any menu item already has a dotted line below it.)



There are still a few more functions related to menus.


Look at:


PROCwimp_menupopup(menu%,pos%,x%,y%)


This wimp-function is designed to allow you to bring up a menu without the need to press <menu>. You can use it to bring up a menu from a <select>/<adjust> mouse-click, or at any time you wish. (You can also display a window in the same way by using a window handle instead of a menu handle in the first parameter.)


The parameter pos% controls the positioning of the menu:


If pos%=0, then the menu is displayed at the screen co-ordinates x%,y% . 

If pos%=1 then the menu is positioned as for an iconbar menu (as if the iconbar icon was at the screen coordinate x%).

If pos%=2 then the menu is centred on the screen.

If pos%=3 then the menu is placed at the mouse pointer position (slightly to the right, to line up with the use of the ptr_menu pointer shape).

If pos%=4 then the menu is placed with its left edge butting up against the right edge of the icon over which <select> was clicked. (This option is designed for use with pop-up menu button icons and is complementary to the previous option.)

These options can be useful for many purposes. (For instance, a menu icon is often used - usually to the right of a writable icon - to offer the user a choice of items/strings to enter into the writable icon. The use of pos%=4 would be ideal here.)


Note that, for some values of pos%, the values of x% and/or y% are ignored, but it is vital that dummy x%/y% values are still used in these cases.


The text of a menu item can be read by using FNwimp_getmenutext, passing the menu handle and the item number. The complement of this is PROCwimp_putmenutext. This allows you to change the text of an item. (In Dr Wimp, all menu text is created as indirected, including the menu title text - and there is no restriction on changing the text length subsequently.)


Now, delete the previously-entered PROCwimp_menuenable lines, and put the following lines in the same place:


IF menu%=mainmenu% AND item%=2 THEN

	PROCwimp_putmenutext(mainmenu%,3,ABCDEFGHIJKLMNOPQRS)

ENDIF


Try choosing the second menu item with <adjust> (to keep the menu displayed). The menu will automatically adjust its width to accommodate the longest line.



There is one more major menu function, which turns a menu item into a writable one. A block of memory is reserved automatically to put the text into.


After the main menu has been defined, add the following line:


PROCwimp_menuwrite(mainmenu%,4,20,1,)


The first parameter is the menu handle, the second is the item number. The third parameter is the maximum length of text allowed to be entered and the fourth parameter determines if the writable item has a border placed around it (0 means no border, 1 means a border). The fifth parameter is the validation string.


It doesnt matter if some text is already there: it will be reinserted into the writable icon (and, if necessary, the maximum length of text will be increased to allow all the existing text to be entered). To read the text, simply use FNwimp_getmenutext, as already mentioned.


When this wimp-function is used a validation string of Pptr_write;Knar; is automatically inserted by default - and the contents of the fifth parameter above are added to this default string as a suffix. So, if you are content with this default, the fifth parameter can be a null string - as above. But if you wish to add further validation string commands (and/or modify the defaults) simply include your required validation string as the fifth parameter. For example, a fifth parameter of A0-9;Kn would add an A-command restricting the allowable keyboard entries to the digits 0-9, modify the K-command to become Kn (and leave Pptr_write unaltered).


(Note that pressing the <return> key when the caret is in a writable menu item has the same effect as selecting that item with the mouse. Hence this action is captured with PROCuser_menuselection and not FNuser_keypress.)



The final handful of menu functions dont really need much description. For more details see !FncnPrc or Section 3 in this manual.


FNwimp_menusize			- Returns the current number of items in a menu.

FNwimp_menumaxsize		- Returns the maximum allowable size of a menu, as

					   specified at creation.

PROCwimp_menuclose		- Closes any open menu.

FNwimp_getmenutitle		- Returns the title of the menu.

PROCwimp_putmenutitle		- Changes the menu title.

PROCwimp_menuitemcolour		- Sets the colour of a menu item text.



Tip: If you are using a standard iconbar menu, with Quit as its last item, you can use:


WHEN FNwimp_menusize(iconbarmenu%) : PROCwimp_quit(0)


instead of (in the earlier coding):


WHEN 2 : PROCwimp_quit(0)


This will ensure that the quitting action will always be associated with the last item on the iconbar menu, however many items there are. This is very useful when you are developing a program and changing the number of menu items.



[Your !RunImage listing should now look like listing RI_03 in Tutor1 (apart from the REM lines, perhaps). Do not destroy it as the following sections continue the tutorial from this stage.]



Adding Keyboard shortcuts to menu items

You are probably already familiar with menus which look like the one below - taken from !Draw - where keyboard shortcuts are shown right-justified against the menu item (here, a sub-menu) to which they refer.

Their intention is to tell the user that the indicated action can be obtained in two ways: either click with <select> over the menu/sub-menu item, or just press the indicated keyboard key combination.

Thus, on the sub-menu below, if you wished to select !Draws Text tool on its toolbar you can either press <select> on the second sub-menu item (appropriately called Text) or just press the key combination <Ctrl-F7>.





Adding such shortcuts to your own applications menus is made very easy by the Wimp. All you have to do is add the shortcut text to your menu item text, separated by a space. The Wimp will then do the necessary alignment.


For example, to achieve the sub-menu appearance for the second item shown above you would simply make the menu text for that item:


Text ^F7


This works for all of the following shortcut symbols:


	^	- ASCII code 94, either one of the <ctrl> keys. (Any key symbol can follow)

	 	- ASCII code 139, either one of the <shift> keys. (Any key symbol can follow)

	Fn	- where n is any of the Function key numbers i.e. F1-F10


and also for the following text items, which are specifically named keys:


	Esc

	Print

	Delete

	Insert

	Enter	- the <return> key

	Up	- the Page Up key

	Down	- the Page Down key


(This list may not be complete, and it is also known that on some computers there are further named keys which give the same effect. The list available for a particular computer can always be found near the top of the file Resources:$:Resources.Wimp.Messages)


Note that at least the first letter of the shortcut must be in upper case if it is not preceded by the <ctrl> or <shift> symbol.


Also, be careful not to add any spaces at the end of the shortcut text - and you might need to ensure that your menu title or one of the menu items has text long enough to make the resulting menu wide enough to make the right justifications visually pleasing.


If you indicate keyboard shortcuts like this, dont forget to add the necessary coding to FNuser_keypress() to carry out the shortcut!


6. Panes **

A pane is a window which, when displayed, appears to be attached to another window - its parent window - and (usually) moves around with it if the parent window is moved. Toolbars are common examples of panes - the toolbar being a separately-defined window but attached to a parent window.


Single pane

DrWimp has easy arrangements to attach a pane to a window. From the Tutorials folder (Tutor1 sub-directory) copy Template3 into the !MyApp directory and rename as Templates.


Where the other windows are loaded in, load in the window pane with:


pane%=FNwimp_loadwindow(<MyApp$Dir>.Templates,pane,0)


We are going to attach this pane to the window main%. 


When a window is dragged about etc., it is actually being continually closed/re-opened all the time. This means that PROCuser_openwindow is also being called continually just before the window in question is opened. So, to effect a pane, every time the main window is opened we want to first open the pane in the window stack position that is supplied (which would be the stack position that the main window would take if there was no pane). Then we want to open the main window just behind this.


We achieve this by using FNuser_pane, which tells DrWimp which pane belongs to which window and causes the parent window to be opened behind its declared pane. To show this, first add the following lines in PROCuser_openwindow :


IF window%=main% THEN

	xoff%=x%-FNwimp_getwindowvisiblesize(pane%,0)

	PROCwimp_openwindowat(pane%,xoff%,y%,stack%)

ENDIF


This automatically causes the pane to be opened first with main% opened behind it. (The getwindowvisiblesize call is not part of the essential sequence: it is merely placing the pane accurately.)


The pane also needs to be closed when the main window is, so in PROCuser_closewindow add the following line:


IF window%=main% THEN PROCwimp_closewindow(pane%)


Then, most importantly, change FNuser_pane as follows, to tell DrWimp that the window has a pane:


DEF FNuser_pane(window%)

return%=-1

IF window%=main% THEN return%=pane%

=return%

Re-load !MyApp and check that it is working.



Just a quick explanation of a few other related things:


PROCwimp_openwindowat(window%,x%,y%,stack%) opens a specified window so that the top left corner is at the co-ordinates x%,y%. If you want the window to open on top, then stack% = -1, or at the bottom if stack%=2. If you want the window to open behind a certain one, then stack% = the handle of the window to open behind - and this latter is used in multiple panes, see below. Finally, stack% values of -3 and -4 have the same meaning as in PROCwimp_openwindow().

If you want a window to open with another one but not follow it around the screen, then in PROCuser_openwindow, use PROCwimp_openwindow. If you set the second parameter to 1 then it will continually re-centre, so it is best to set it to 0. Also, just pass stack% straight through.



Multiple panes

Multiple panes are straightforward, but you now have to decide the stacking order of the window/panes. Firstly, add the following line to load in a second pane:


pane2%=FNwimp_loadwindow(\"<MyApp$Dir>.Templates\",\"pane2\",0)


With two panes you have to decide which one is going to be at the top of the stack in the final display, with the second pane behind that, followed by the parent window behind the second pane. This can be extended to as many panes as you like. (By behind and top is meant only the stacking order: the panes and their parent window can be anywhere you choose on the screen i.e. they dont have to abut or overlap, although often you will wish them to.)


We are going to make pane% our topmost pane; pane2% behind that and then the parent window main% at the bottom of this stack of three windows (two panes and their common parent window) - and, dont forget, if we follow the steps correctly then DrWimp will automatically open the parent window in the right place.


So, change the section in PROCuser_openwindow to become:


IF window%=main% THEN

  	xoff%=x%-FNwimp_getwindowvisiblesize(pane%,0)

  	PROCwimp_openwindowat(pane%,xoff%,y%,stack%)

  	yoff%=y%-FNwimp_getwindowvisiblesize(main%,1)

  	PROCwimp_openwindowat(pane2%,x%,yoff%,pane%)

ENDIF


This will open the first pane in the passed stack position and then open the second pane behind the first pane.


Now, in order to get DrWimp to open the parent window behind the second pane, we have to change FNuser_pane to return the handle of the bottom-most pane (the last pane opened). Thus:


IF window%=main% THEN return%=pane2%


Change the relevant parts in PROCuser_closewindow so when the main window is closed both the panes close:


IF window%=main% THEN

	PROCwimp_closewindow(pane%)

	PROCwimp_closewindow(pane2%)

ENDIF


and now check that it all works.


Some overall points

Finally, some overall points on panes:


 It is best to avoid using panes having title bars. Only the parent window should control the on-screen movement. (But scroll-bars on panes work without difficulty.)


 Note that, however many panes you attach to one parent window, only one of these panes (the bottom-most) must be assigned to the parent in FNuser_pane. Do the stacking as shown, within PROCuser_openwindow. Do not try to attach panes to panes!


 If you have more than one window with panes, simply treat them as separate conditional coding items within PROCuser_openwindow, PROCuser_closewindow and PROCuser_pane.


 Be careful to follow the described procedure accurately. If your initial window opening looks fine but things go awry when you use the furniture on the parent window (e.g. scrolling, back icon, etc.) then you have probably forgotten something or got things out of order.


 The normal operations of a pane work whether or not you set the Pane option for a pane in its window definition. However, it is best to set this option if you are using writable icons in a pane. This will then ensure that the caret management and window focus are properly linked. 


 The Examples folder contains at least three applications using panes. Please examine these.


[Your !RunImage listing should now look like listing RI_04 in Tutor1 (apart from the REM lines, perhaps). Do not destroy it as the following sections continue the tutorial from this stage.]

7. Saving data with save windows **

Easy facilities are provided for adding and controlling save windows - which are traditionally used to save data to files on a hard or floppy disc etc. The following user-functions are all involved in a strict, but simple, procedure:


FNuser_savefiletype

FNuser_savedata

PROCuser_saveicon



Copy the file Template4 from the Tutorials folder (Tutor1 sub-directory) into !MyApp and rename as Templates. Load in the save window:


save%=FNwimp_loadwindow(<MyApp$Dir>.Templates,save,0)


and after PROCwimp_attachsubmenu(mainmenu%,3,i3menu%), add:


PROCwimp_attachsubmenu(mainmenu%,5,save%)


If you run !MyApp now, a standard save window will duly open when you move across item 5 of mainmenu%. But nothing else will happen because we havent yet given it any code to tell it what to do.


Things starts to work when you change FNuser_savefiletype as follows:


DEF FNuser_savefiletype(window%)

return$=

IF window%=save% THEN return$=FFF

=return$


This is the first step: DrWimp now knows that save% is a save window and that it saves text files. Don't try it just yet as DrWimp will try to filetype the saved file and it is not created, so will throw up an error.


For the next step we move to FNuser_savedata. Whenever the file icon in a save window (i.e. one that has been identified by FNuser_savefiletype in the above way) is dragged to a destination (or the OK button clicked after entering a full save path) FNuser_savedata is automatically called by Dr Wimp - with, as usual, all the parameters filled with the current live values. So, path$ will hold the full pathname of the file-plus-window that you are saving to (the destination file) and window% will hold the handle of the window that the icon was dragged from (the source file).


Thus, it is in FNuser_savedata that you add your required saving actions and an example of this follows.


Firstly, you will notice that FNuser_savedata contains the following unusual lines:


LOCAL ERROR

ON ERROR LOCAL =2


These lines allow DrWimp to respond if an attempt is made to save to a protected floppy disc or a locked hard drive. It is suggested that they be REMed out until your saving code works properly so that errors are reported to you. Any local variables should be declared before these lines, and the rest of your saving code after them.


So, enter the following into FNuser_savedata, after the local error lines:


return%=0

IF window%=save% THEN

  	file%=OPENOUT(path$)

  	BPUT#file%,This is a text file,

  	BPUT#file%,created by MyApp.

  	CLOSE#file%

  	PROCwimp_menuclose

return%=1

ENDIF


and replace the last line of the DEF FN with:


=return%


 Remember: the filetyping is taken care of by DrWimp as a result of the FNuser_savefiletype action earlier.


A vital point is to note that FNuser_savedata returns a number. This is 0 by default, but can be 1 (or a 2 if a local error occurs). In our tutorial listing above we have changed the return to 1 when we use the function. It is very important that you do this when you use this user-function in this way - and return the default value of 0 in other cases. This ensures that the Wimp knows you have taken saving action and it will complete the Wimp saving protocol correctly and do the file-typing.


You can now Run !MyApp, open the save window from the main menu and then drag the file icon to any filer window (or click the OK button, after typing a complete path in the writable icon) and a new textfile containing the above text will be created. The standard error messages like You must drag the icon to a filer window to save... etc. are taken care of by DrWimp.



We have not yet introduced PROCuser_saveicon. To make things work automatically behind the scenes - which includes handling both dragging the file icon or clicking the OK button - Dr Wimp needs to know the icon numbers of the three key icons in any save window. That is, the (draggable) file icon, the writable icon and the OK button. Dr Wimp calls these drag%, write% and ok% respectively.


If you examine the tutorials save window in a template editor (!WinEd, for instance) you will see that:

Icon 0 is the (draggable) file icon, called drag%

Icon 1 is the writable icon, where the filename or pathname goes, called write%

Icon 2 is the OK button, to click on to save to the pathname, called ok%


These are regarded as the default values - but you may want to use different numbers for these icons in your application. This is where PROCuser_saveicon comes into play.



If you are using a save window with different values (e.g. drag%=3, write%=15, ok%=1) then you must tell Dr Wimp by adding something like the following line to PROCuser_saveicon:


IF window%=save% THEN drag%=3:write%=15:ok%=1

Thus, you simply set these icon numbers to whatever you have used in your window template and this action overrides the default values.


Note that PROCuser_saveicon is a little different from most PROCs in that - by using the RETURN keyword (plus a space) in front of each of the three variables drag%, write% and ok% - it works rather like a FN, because it then returns to Dr Wimp the new values of these parameters. But whereas a FN can only return one value, RETURN allows a PROC to return as many values as you wish.


As you can see, the save window procedure is not difficult but must be followed strictly. (If the Save box file icon will not drag or nothing happens when the drag finishes, the chances are that you have not used all three of the above saving user-functions correctly.)



The parameter values in FNuser_savedata allow you to do some checking before deciding whether to save or not. For example, at the start of FNuser_savedata, you could check to see whether the file path$ exists. If it does then use FNwimp_errorchoice to allow the user to decide whether to overwrite the file or not.


You can have as many save windows as you wish. Simply load them in, add them to a menu (or provide some way the user can get to them), return their filetype from FNuser_savefiletype, and do the saving in FNuser_savedata.


If the data you wish to save is already in the form of a file loaded into a memory block then you can use in FNuser_savedata one of the file-saving wimp-functions introduced later - see Sections 2.12 and 2.13.


Remember also that you can open a window - including a 'save window' - from a menu. If you add the following to the bottom of PROCuser_menuselection:


IF menu%=mainmenu% AND item%=5 THEN

	PROCwimp_menupopup(save%,3,0,0)

ENDIF


Now select the save item from the save menu. You will see that the save window opens near the mouse pointer and stays open until you complete the save or click elsewhere i.e. the window behaves like a menu - as you might expect in this case.


[Your !RunImage listing should now look like listing RI_05 in Tutor1 (apart from the REM lines, perhaps). Do not destroy it as the tutorial picks up again in the Section 2.9 where it continues from this stage.]


Saving a directory/application

All the above procedures are aimed specifically at saving files rather than saving a directory or an application. However, it is not difficult to modify the file-saving arrangements to do this. Indeed the !Fabricate utility - authored with Dr Wimp - does this.

The important point to note is that you must always ensure that FNuser_savefiletype() returns a valid file-type string for the save window you are using - even though the file-type will only be used as a dummy and even though you will have probably changed the save window drag icon to show a directory/application sprite. (FFF is a good file-type string choice, but anything in the range 000 to FFF will do.) Without this precaution dragging will not start.

After this, the necessary coding can mainly be confined to DEF FNuser_savedata() where - early in your routine - you need to create the new directory directly, using PROCwimp_createdirectory(). You can then add coding to create/copy other files/directories into the new directory as required, making sure they are file-typed if you are creating any new files.

Finally, it is safest to ensure that DEF FNuser_savedata() returns 1 after this process.

Saving to an application rather than a directory uses the same procedure but some extra steps are normally required. There will be a need to create/copy appropriate !Boot and !Run files - and also to ensure that an application sprite is created, correctly named (with the usual lower-case version of the application name) and placed in the new application in the usual !Sprites/!Sprite22 files. It is far easier to create all these extra files outside the programme, ready to copy them into the new application.

If you need any assistance concerning saving to a directory/application please do not hesitate to contact the Dr Wimp author.



8. Errors & Warnings **

You will inevitably meet error messages when you are programming. But this section mainly concerns itself with the facilities Dr Wimp provides for you, the programmer, to include warning and error messages within your coding as a means to help make them more user-friendly. It also revisits the global error trap line in the skeleton !RunImage listing, which was first introduced in Section 2.1.


Standard error/warning windows

There are two wimp-functions for producing standard error/warning windows i.e. program action will stop and the error box will appear. A mouse-click by the user on an action button (or <return> key or <escape> key press) is needed for the program to proceed.

The first is a PROC which produces a simple error box with just one action button. The second is a FN which can have more than one action button and gives a return value corresponding to which button is pressed.


The first wimp-function (with only one action button) is:


PROCwimp_error(title$,error$,from%,spritename$,spritearea%, button%,altbutton$)


title$ 	- is the title to be displayed in the title bar of the error window. Usually, the application name is used and, to assist with this, if title$ is made a null string then the words appearing will be <appname>, where <appname> is the same as used in the first parameter of FNwimp_initialise() when the application starts

error$ 	- is your rquired error/warning message itself. The text is word-wrapped automatically.

from%	- allows you to prefix the title to suit the error message. If from% is 1 then the title is prefixed with Error from . And if it is 2 then the title is prefixed by Message from . If from% is 0 no prefix is used.

spritename$ - the sprite name of an additional custom sprite to be added to the error box.

spritearea% - the sprite area containing the above custom sprite name - 1 meaning the wimp-pool.

button%	- controls the default button. If it is 1 then you get a Continue button. If it is a 2 then you get a Cancel button instead

altbutton$ - allows a button with custom text to be used instead of one of the above default buttons. The string altbutton$ should contain the required button text. If it is not a null string then it will be the button provided and will override whatever value is in button%.

The second wimp-function (allowing multiple action buttons) is:


FNwimp_errorchoice(title$,error$,from%,type%,spritename$,sprite-area%,continue%,cancel%,extrabutton$)


title$ 	- as above.

error$ 	- as above.


from%	- as above.


type%	allows you to further tailor the appearance of the error window to suit the type of message. The following standard sprites will appear in the error window, corresponding with the value of type%.






spritename$ - as above.

spritearea% - as above

continue%  - if 1 then a Continue button will be provided.

cancel%      - if 1 then a Cancel button will be provided.

extrabutton$ - allows extra/alternative buttons to be provided. If a null string then no extra buttons will appear. Otherwise, extrabutton$ should be a comma-separated string of the required button texts.

The return from this function is simply a number corresponding with the button pressed by the user. The Continue button (if present) always returns 1; the Cancel button (if present) always returns 2; and other buttons (if present) return 3, 4, 5 etc. corresponding to the order of their text in extrabutton$.


Here is an example error box from this call (made within an application called Calibre):


errorchoice%=FNwimp_errorchoice(,The year needs to be in yyyy format,2,3,!calibre,1,0,0,Return to application,Quit program)




As the parameters continue% and cancel% are both 0, neither the default Continue nor Cancel button is present. - so the return values of 1 or 2 are not possible. Therefore, clicking Return to application will return 3, or clicking Quit application will return 4.

Note that the buttons appear from Right to Left in the order Continue (if present), Cancel (if present), then the items (if any) in order from extrabutton$. The width of the error bax will expand to accomodate all buttons.

If the <return> key is pressed it is the equivalent of pressing the highlighted button (here, Return to application, so the return will be 3) and if the <Esc> key is pressed it is the equivalent of pressing the button next to it (here, Quit application, so the return will be 4). If only one button is present then pressing <return> or <Esc> has the same effect and the return will be the same as the return from pressing that only button.



Finally, if your call to PROCwimp_error() or FNwimp_errorchoice() specifies no buttons at all then the error box will default to just a Continue button.



The Dr Wimp global error trap


In Section 2.1 we saw the line:


ON ERROR PROCwimp_error(appname$,REPORT$+ at line+STR$(ERL),1, ,0,0,Quit +appname$):PROCuser_error: PROCwimp_closedown:END


which is the global error trap included in the skeleton !RunImage file (which will also appear in the !RunImage of any application produced by the !Fabricate utility).


As indicated, the role of this line is to react to any errors which may occur during the application run and, having reported what the error is and where, it then takes steps to end the application in an orderly manner - by calling PROCuser_error and then PROCwimp_closedown.


Because this global error trap always leads to quitting the application its main use (hopefully!) is for you, the programmer, whilst developing the application.


PROCwimp_closedown is, in fact, an internal function not intended for other uses by the programmer, and it is not in the list of functions in Section 3. (Strictly, it should therefore have a wint- prefix - see Section 1.2 - but as it appears in the skeleton !RunImage it is felt that naming it wimp_ presents less confusion to the beginner.) It is a good housekeeping function which closes/removes certain items which may have been opened/created during the program run. For instance, font handles, dynamic areas, messages files, template files. (This internal function is also called by Dr Wimp when you quit the application by normal means.)


It is also worth introducing PROCuser_error at this point. This user-function is only called in the above global error trap line. Its purpose is to give you, the programmer, a convenient place to do your own application-specific good housekeeping when something goes wrong and the application needs to end. For instance, possibly the most frequent use might be for closing any files which may be left open because an error occurred during file-manipulation action. This user-function is therefore very useful when developing a program, but another use might be to bring up a message to encourage your users to report any errors to you. Just one word of warning: be very careful to get your coding right within DEFPROCuser_error, otherwise you risk a continuous loop of errors!



Error traps in DrWimp listing

It may assist you in your programming and debugging to know a little about the many errors/warnings which are deliberately trapped by the Dr Wimp library. An attempt has been made to distinguish these by the title text used in their error message display.


Here are the most important ones:


RISC OS Version - fatal error if OS Version is less than that specified in FNwimp_initialise. Error message title will be Error from WIMP

Window/icon indirection - non-fatal error if attempt is made to change window title or icon text when they are not defined as indirected. Error message title will be Error from <YourAppName> library

Icon colour - non-fatal error if attempt is made to change icon colour when the icon is not using the desktop font. Error message title will be Error from <YourAppName> library

Icon caret - non-fatal error if attempt is made to put caret into a non-writable icon. Error message title will be Error from <YourAppName> library

Menu from Message file - fatal error if attempt is made to create a menu with the cumulative item text too long. Error message title will be Error from <YourAppName> library

Font menus - there are non-fatal warnings if you try to apply to a font-menu any of the many wimp-functions designed to change a menu in some way. For example, you cannot use PROCwimp_putmenutext() to alter a font-menu.

Saving data - DrWimp passes on any Abort on data transfer type Wimp error (probably fatal). Error message title will be Message

WimpSlot increase - Non-fatal warning if whole of requested increase cannot be done. Error message title will be Message from <YourAppName> library

Printing - Printing abort Wimp error messages passed on (non-fatal).  Error message title will be Error from <YourAppName> library

Dynamic areas - Two fatal Wimp errors if you try to change a dynamic area that does not exist or if the change cannot happen for some reason.  Also, one non-fatal error if you try to delete a dynamic area which does not exist. Error message titles will be Error from <YourAppName> library

Message files - A non-fatal error if you try to initialise more message files than the maximum set. Error message title will be Message from <YourAppName> library


Iconiser - Non-fatal warning if your intended iconiser sprite has a name longer than 7 characters. Error message title will be Message from <YourAppName> library


In addition, there are many wimp-functions where you have the option for an error/warning message to be generated in specific circumstances e.g. if a named file cannot be found.



Inevitably, you will also get error messages which do not fall into the above categories - and these will be picked up by Line 70 of the skeleton !RunImage of !MyApp, which ensures that the error message title will be Error from <YourAppName> and that they will all be fatal. They may be the result of your own programming errors or, possibly, due to a bug in Dr Wimp (which you are urged to report if you feel this is the case).


You will, of course, get other error/warning messages arising from your own use of PROCwimp_error and FNwimp_errorchoice and you may feel it worthwhile to arrange for their error message titles to be suitably unique - to make them easily distinguished from the above.





9. Message files **

It is increasingly common for applications to have Message files (nothing to do with the Wimps Messaging system!). These files commonly hold much of the fixed text used by the application. So, for example, it might be used for the interactive help text (see Section 2.10) which can then be easily translated into another language by someone who doesnt need to know much about programming.


Copy the Messages file from the Tutorials folder into the !MyApp directory. Load it into !Edit and have a look at it to become familiar with the Message file format. You will see:


#Message file for tutorial 9.

#Prepared by Andrew Ayre

#version 1.00 (29-Mar-95)


LIB:Doctor Wimp

OS:RISC OS %0

UTIL:FuncnProc

VER:1.00 (%0-%1-99)


Note firstly that you can put comments into a Message file simply by starting the comments line with a hash #.


Lines which have text to be used in the application start with what is called a token. This is just a few letters (not necessarily upper-case) that the line can be identified by. The token is followed by the required text - separated by a colon. For example:


LIB:Doctor Wimp


We can then use the token in our program instructions, and its corresponding text will be substituted. Thus, if we wanted to use the line of text Doctor Wimp in our program, we would reference it by using the token LIB.


Note: The message file must be terminated by a <return>, otherwise the last message in the file will not work.


Further, by using parameters, the substituted text can also have other strings inserted into them at the time they are read into the application. For example:


OS:RISC OS %0


which includes the parameter %0 and:


VER:1.00 (%0-%1-99)


which includes the parameters %0 and %1


Taking the last one only, when you read in this line (by referring to the token VER) you would also supply two strings. These could be 29 and Mar for example. When the line is read in it ends up as 1.00 (29-Mar-99).



Dr Wimps provides several wimp-functions to manipulate messages files. They are:


FNwimp_initmessages(path$)


which needs to be called once for each Message file you are going to use. It sets up blocks of memory ready to read in the lines of text. path$ is the full pathname of the Message file. The function returns a handle for that particular messages file, which is used to access the file, with:


FNwimp_messlookup(messagefilehandle%,token$,a$,b$)


as will be demonstrated below.


You can use multiple messages files. By default the maximum number of such files is 16 (in any one application) but this can easily be changed - see later.



So, to use the above-mentioned Message file called Messages it must first be initialised using FNwimp_initmessages(path$)and it is best to do this early within PROCuser_initialise.


For the tutorial, we therefore need to make the initialisation call for the Message file which is now inside the !MyApp directory i.e.


messages%=FNwimp_initmessages(<MyApp$Dir>.Messages)



The handle returned to messages% can now be used anywhere in your program.


To fetch, from the Message file, a string which does not have any substitution parameters in it you would use, for example:


FNwimp_messlookup(messages%,UTIL,,)


This returns the line of text FuncnPrc.


To fetch a string which has just the parameter %0 in it you would use, for example:


FNwimp_messlookup(messages%,OS,4.02,)


This returns the line of text RISC OS 4.02.


And finally, to fetch a string which has both the parameters %0 & %1 in it you would use, for example:


FNwimp_messlookup(messages%,VER,1st,Jan)



This returns the line of text 1.00 (1st-Jan-99).


So, add the following lines to PROCuser_initialise after FNwimp_initmessages and run your application.


lib$=FNwimp_messlookup(messages%,LIB,,)

PROCwimp_error(appname$,LIB=+lib$,1,,0,2,)

os$=FNwimp_messlookup(messages%,OS,3.11,)

PROCwimp_error(appname$,OS=+os$,1,,0,2,)

ver$=FNwimp_messlookup(messages%,VER,29,Mar)

PROCwimp_error(appname$,VER=+ver$,1,,0,2,)


These will cause a series of three error boxes to show in turn, each carrying short (and probably bewildering!) text constructed from the Message file. (When you have checked that it works you should delete/REM the above 6 lines.)



[Your !RunImage listing should now look like listing RI_06 in Tutor1 (apart from the REM lines, perhaps). Do not destroy it as the tutorial picks up again in the next section - Section 2.10 - where it continues from this stage.]


Note that you can use %0 and/or %1 as many times as you like in a Message string. You can also put them in any order.



You can also substitute a different messages file for one that has already been initiated, by using:


FNwimp_reinitmessages(messagefilehandle%,path$)


where messagefilehandle% is the handle of the already-initiated messages file and path$ is the full path of the new messages file that you wish to substitute. Substituting a different file in this way does not increase the number of simultaneously active messages files - it simply discards one in favour of another. This process is very useful when producing up-to-the-minute menus from changing messages files e.g. message files constructed by reading a directorys current contents.


It would be usual to use this function in the following manner:


messages%=FNwimp_reinitmessages(messages%,path$)


That is, assign the new handle to the same variable.


There is no practical limit to the number of times you can re-initiated a file - except that your application WimpSlot needs to be large enough to cope with the largest messages file, but this is unlikely to be a problem.



There is also a wimp-function for finding out how many messages there are in an active messages file, for a given token. It is:


FNwimp_getnumberofmessages(messagefilehandle%,token$)


and its use should be self-explanatory.



Finally, Message files can also be used for creating/recreating menus - see Section 2.18 - and in that section there is also further important guidance on formatting messages files.



As indicated above, by default the maximum number of messages files you can use in an application is 16, which is probably more than adequate - but this is easily changed if it is not enough for a particular application. Inside the DrWimp library - approximately ten lines into FNwimp_initialise - is the global variable wMaxMessagefiles%. Simply change its assigned value here to the maximum number you want.



10. Interactive help **

There are two Help syatems available to Wimp applications. One is via the Filer menu and one is via the RISCOS !Help application. They are independent of each other and hence either or both can be provided by any application.


The first system does not need any special facilities: all it needs is a file called !Help to be placed in your application directory - and many applications make their !Help file their main Manual. (Dont confuse a !Help file with the !Help application!) If such a file exists then it will be detected by the Filer when the application is first seen and the corresponding Help item in the Filer menu tree will be enabled for selection. (This basic system can be very usefully enhanced by using a special set of system variables suggested by RISCOS/Castle. The latest version of Dr Wimps !Fabricate utility incorporates these features automatically.)


The second system provides interactive help. When activated, small windows containing focussed help text appear temporarily as the pointer is moved over the windows/icons/menus of an application. An application needs to take special steps to use this method. If it does then the help becomes active as soon as you start-up the RISCOS !Help application which comes with all RISCOS systems. (There are also enhancements available which make the appearing text windows more attractive e.g. like cartoon speech bubbles.)



DrWimp provides facilities to enable this second method to be used very simply. There are two facilities: one for windows and icons, and the other for menu items.


For windows/icons, all you have to do is return your own choice of help text for a given window handle and icon number in FNuser_help.


In the tutorial !RunImage listing, enter the following lines into FNuser_help:


DEF FNuser_help(window%,icon%)

h$=

CASE window% OF

	WHEN info% :

  	CASE icon% OF

    	WHEN 0 : h$=This application is called MyApp

    	WHEN 1 : h$=It tests the DrWimp library

    	WHEN 2 : h$=MyApp was written by Joe Bloggs

    	WHEN 4 : h$=This is the version number and date

    	OTHERWISE : h$=This is the MyApp info window.

  	ENDCASE

  	WHEN iconbar% : h$=This is the MyApp icon

ENDCASE

=h$



Then save and reload !MyApp - and then load the RISCOS !Help application, If you now move the pointer over the info window or the iconbar icon you will see the short help text appear.

Similarly, for menu items, use FNuser_menuhelp, eg:


DEF FNuser_menuhelp(menu%,item%)

h$=

CASE menu% OF

	WHEN iconbarmenu%

   CASE item% OF

      	WHEN 2 : h$=Click <select> to quit\"

	ENDCASE

ENDCASE

=h$


Save the !RunImage again and re-run !MyApp to try things out. (After doing this you may find it best to quit - or just Suspend - the !Help application, to stop the interactive help messages continuing to appear.)


[Your !RunImage listing should now look like listing RI_07 in Tutor1 (apart from the REM lines, perhaps). Do not destroy it as the tutorial picks up again in Section 2.14 where it continues from this stage.]


The only important further points to note are that:


a) the string |M (that is, ASCII character 124 followed by M) can be inserted at any point(s) in your text to force a new line in the displayed text - but it takes up 2 characters each time you use it;

b) the maximum allowed length of a returned help string (including any occurrences of |M) is 235 characters.


No further explanation is necessary: it really is very simple. 


You will appreciate that for many applications the above lists of help text items might be very long.


Also, help text in this form lends itself very well to using Message files to hold the text and using appropriate calls to FNwimp_messlookup in FNuser_help and FNuser_menuhelp. (See Section 2.9 for details on using Message files.) In this way, for instance, help text in a choice of languages can be provided.



11. Dragging or double-clicking files

Whenever a file (or directory or application) is dragged and dropped onto a window (or the iconbar icon) belonging to your application - or, indeed, just double-clicked on - then


FNuser_loaddata(path$,window%,icon%,ftype$,workx%,worky%)


is called automatically. Note that its default return is 0, which is discussed later below.


The parameters are:


path$ 	is the full pathname of the file that has been dragged/double-clicked (the source file).

window% is the window handle where the drag ended. (It will be 0 if the file was double-clicked rather than dragged.)

icon% 	is the icon number where the drag ended.  (It will be -1 if no icon is involved, or if the file was double-clicked rather than dragged.) Most of the time you would only need to check the window handle, but the icon handle can be used for drop-boxes. These are boxes with text in saying something like: Drop file to load here.

ftype$ 	is the filetype of the source file. Eg: for text files it is FFF. Files have a three character hexadecimal filetype, but directories are 1000, and applications are 2000. (Note that letters willbe in upper-case, and if the hex number is less than &100 then there will be leading zeros added automatically e.g. filetype &AF will appear as 0AF)

workx%,worky% are the work area coordinates (in the window window%) where the drag ended. (These will both be -1 if the file was double-clicked on rather than dragged.)


With these values passed to you by Dr Wimp it is up to you to add any particular code to access or manipulate the file/directory/application.


The other important point to note is that you, the programmer, must also help the Wimp by letting it know if you are responding to the dragging/double-clicking of the file - and this is the role of the return from the user-function, entirely similar to that employed when saving data to a file via a save box - see Section 2.7.


So, if you respond to the dragging/double-clicking of any file you must return a 1 from this user-function - otherwise the default 0 must be returned. This is vital because the return value is used by DrWimp to send a message to the Filer saying that you are taking action on it.



Here is an example piece of code for loading the contents of a text file line-by-line into an array (for simplicity it assumes the file is not empty and that the array is large enough):


DEF FNuser_loaddata(path$,window%,icon%,ftype$,workx%,worky%)

LOCAL return%,L%

return%=0

IF ftype$=FFF THEN

	file%=OPENIN(path$)

	L%=1

	REPEAT

		A$(L%)=GET$#file%

		L%+=1

	UNTIL EOF#file%

	CLOSE#file%

	return%=1

ENDIF

=return%


What this does is to check if the dragged/double-clicked file is a text file and, if so, load each of its lines into an array called A$ (which you will need to create in PROCuser_initialise).


Try altering !MyApp so it can load in a text file, then using the save box, allow the user to save the text file to somewhere else. All you have to do is alter the save code so it saves the contents of the array.



When a file is double-clicked it can also be made to load in your application first, if it isn't already loaded. The only thing you need to add to achieve this is a line like the following in your applications !Run file:


Set Alias$@RunType_xxx <Obey$Dir>.!Run %%*0


Change xxx for the hex value of the filetype you are using, eg. FFF for text files.


Note that, when a file is loaded in this way, the parameters window% and icon% passed to FNuser_loaddata will be 0 and -1 respectively and the workx%/worky% coordinates will both be -1. See above. You could therefore use these values to filter double-click loading if you wished.



12. Loading files into memory

There are many circumstances where you will wish/need to load an existing file into memory. In particular, the display and/or printing of drawfiles, sprites, JPEGs generally requires them to be loaded into the computer memory first.


Dr Wimp provides a standard method for loading any file into memory. It is a simple three-step procedure, but it must be followed rigourously. The steps are:


1) measure size of file using FNwimp_measurefile;

2) create memory block of at least this size;

3) load file into block with the appropriate file-loading wimp-function.

and there are currently four choices for Step 3):


	FNwimp_loadsprites() - for sprite-files

	FNwimp_loaddfile() - for drawfiles

	FNwimp_loadjpegfile() - for JPEG files

	FNwimp_loadfile() - for any other types of file



A typical coding sequence for a single file - taking a sprite-file as an example - is:


size%=FNwimp_measurefile(spritefile$,0)

DIM block% size%:REM** Or create a Dynamic Area instead. **

dummy%=FNwimp_loadsprites(spritefile$,block%,0)


Step 1), the use of FNwimp_measurefile(), is very important and you should not measure the file size in any other way. The first parameter is the full path of the file to be loaded. The second parameter is a flag determining whether the wimp-function will give a warning if the file cannot be found. Here it is set to 0, meaning that no warning will be given. Setting it to 1 will give a warning.


Step 2), creating the block of memory, is straightforward and using a Dynamic Area (see Section 2.20) is probably better than DIM - but either is fine.


Step 3), the actual loading of the file into the created memory block, needs more explanation and although our example uses FNwimp_loadsprites() exactly the same comments apply to the other available file-loading wimp-functions. The first parameter is, as before, the full path of the file to be loaded. The second parameter is the start address of the memory block into which the file is to be loaded - here block%. The third parameter, again as before, is a flag determining whether the wimp-function will give a warning if the file cannot be found.


The critical point to note is that this file-loading wimp-function is an FN and hence returns a value - assigned to dummy% here. The returned value is the address of the next byte in the memory block after the file has been loaded. This may seem a little odd at the moment but comes into its own when we want to load more than one file into a single memory block - see next. In the above example we are only concerned with one file so the returned value is of no interest to us - hence the assignment to the variable dummy% (which needs to be unused elsewhere and best made LOCAL!).


With the sprite-file safely loaded into memory, the start address block% effectively becomes the handle of the loaded sprite-file for display/printing/saving etc. - and this is covered in later Sections.


If more than one file is to be loaded then, of course, there is nothing wrong with using the above procedure more than once. However, it is just as easy to measure all the files first and create one block large enough to load them all. The coding then becomes:


size%=0

size%+=FNwimp_measurefile(file1$,0)

size%+=FNwimp_measurefile(file2$,0)

size%+=FNwimp_measurefile(file3$,0)

DIM block% size%:REM** Or create a Dynamic Area instead. **

first%=block%

second%=FNwimp_loadsprites(file1$,first%,0)

third%=FNwimp_loadsprites(file2$,second%,0)

dummy%=FNwimp_loadsprites(file3$,third%,0)


The result is that the three files are loaded into one block and their respective handles become first%, second% and third% - and this method can be extended as necessary, with the final return always being assigned to an arbitrary unused variable.


(There is, of course, no reason why all the files have to be of the same type. If they are different then just ensure that the appropriate file-loading wimp-functions are put in their corresponding places in the last three lines.)


It is very important that you become familiar with this file-loading sequence as it will be assumed in several of the following Sections.


When using the non-file-specific wimp-function FNwimp_loadfile(), the loading of a file automatically stores the length of the file in the 4-byte word preceding the returned handle. If the contents of the loaded file are amended in any way whilst it is in memory it is vital that the file-size is changed accordingly - otherwise its counterpart PROCwimp_savefile() - see next Section - will not work properly.



It is worth remembering here that a spritefile can hold one or more sprites. A spritefile (file-type &FF9/Sprite) has, like any other file, a name and, independently, each sprite within it has a separate name.

You can see which sprites are held within any spritefile by double-clicking on it - which causes !Paint to be loaded and the sprites are then seen in a filer-like window. (If the sprite-file holds only one sprite than !Paint will also open a Paint window with that sprite shown - ready for editing etc.)

13. Saving files from memory


We have already seen how data can be saved using save windows but there are also occasions when you may wish to save a loaded file directly to a hard or floppy disc etc.


Each of the separate file-loading wimp-functions introduced in Section 2.12 has its file-saving counterpart. They are:


	PROCwimp_savesprites() - for sprite-files

	PROCwimp_savedfile() - for drawfiles

	PROCwimp_savejpeg() - for JPEG files

	PROCwimp_savefile() - for any other types of file


and they all work in a similar way. Taking the drawfile case as an example, the call is:


PROCwimp_savedfile(savepath$,dfile%)


where savepath$ is the full destination file and dfile% is the handle of the drawfile already in memory.


In the case of the first three (file-specific) functions the correct file-typing is taken care of automatically, but in the fourth case (non-file-specific) there is an extra parameter for specifying the required file-type.


This non-file-specific case also needs a little care because of the separate storing of the file-size - as already mentioned at the end of the previous Section.



14. Sprite areas & Mouse pointers **

As was introduced in Section 2.12, in order to display/print sprites in a Wimp application they need to be loaded into memory somewhere - as opposed to being left in a file.


All the sprites we have used so far in our tutorial have been from a special area of memory called the Wimp sprite pool which is loaded automatically on computer start-up.


We can add sprites to this pool using the Iconsprites star command - as is usually done in the !Boot and !Run files of an application. However, this method is really only intended for sprites which are to be used by the Filer (e.g. application sprites for Filer windows, iconbar, pinboard, etc.) and we may wish to display other sprites in other circumstances. For example, sprites which are solely for use during the running of our application and which can be safely discarded again when we quit it.


To do this, Dr Wimp allows an application to create its own (private or user) sprite areas - which are stored in the wimpslot, the memory used by the application. This has a speed advantage and also, when the application quits, all the memory is regained. We will use the phrase user sprites to describe sprites that are held in such a sprite area.



Tutorial

We are going to put a sprite-file (holding a single sprite) into a user sprite area by using the sequence described in detail in Section 2.12 for the loading of files into a memory block - here, specifically, the sprite-file case.


Then, rather than display the sprite from this sprite-file in a window, we going to combine two aspects by using the sprite to change the shape of the mouse pointer.


This will conveniently introduce the point that the mouse pointer is also simply a sprite, which can be changed.


So, starting with !MyApp as we left it in Section 2.10 (i.e. as in tutorial listing RI_07) copy the file Sprites from the Tutorials folder into the !MyApp directory. This spritefile holds a sprite called ptr_hand - a small shape of a hand.


Then, in the !RunImage listing, enter the following standard file-loading lines into PROCuser_initialise:


size%=FNwimp_measurefile(\"<MyApp$Dir>.Sprites\",0)

DIM sprites% size%

a%=FNwimp_loadsprites(<MyApp$Dir>.Sprites,sprites%,0)


As Section 2.12 explains, the first line measures the spritefile size; the second creates a corresponding memory block, called sprites% here - and the last line loads the file into that block (with a% being an arbitrary variable not being used elsewhere). sprites% therefore becomes the handle of the loaded sprite-file.


Now lets use the sprite in the sprite-file we have just loaded, and we will be introducing two new user-functions and one new wimp-function.


Whenever the pointer moves in and out of one of your applications windows, the functions PROCuser_enteringwindow() and PROCuser_leavingwindow() are called automatically. They both have the single parameter window%, which will contain the handle of the window concerned.


So, in PROCuser_enteringwindow, add the following lines:


IF window%=main% THEN

  	PROCwimp_pointer(1,sprites%,ptr_hand)

ENDIF


And in PROCuser_leavingwindow, add the following:


IF window%=main% THEN

  	PROCwimp_pointer(0,0,)

ENDIF


Run !MyApp and you should find that when you move the pointer over the main window, it turns into a hand and it changes back to the normal shape when you leave the window. (If you get a No room for this DIM error, you have not copied the file Sprites  to the !MyApp directory!)


The first parameter of PROCwimp_pointer(pointer%,spritearea%,pointer$) tells DrWimp whether to use the Wimps default pointer (0), or a user-defined one (1).


The second parameter tells which sprite area is to be used, 0 for the Wimp sprite pool, or a handle for a user sprite area.


The Wimps default pointer is held in the Wimp sprite pool, so when we want to use the default pointer shape both the first and second parameters should be 0.


However, if we wish to use a sprite from a user sprite area instead, the first two parameters should be, respectively, 1 and the private sprite area handle holding the sprite - which, here, is the handle sprites%.


The last parameter is the name of the sprite to use and it only has relevance if the first parameter is set to 1, in which case we put the name of the sprite i.e. ptr_hand, as in the first case above. If the first parameter is 0 (i.e. we want to use the Wimps default pointer) then the third parameter will be ignored - but there is still a need to put something there and a null string, as in the second case above, is a good idea.)



[Your !RunImage listing should now look like listing RI_08 in Tutor1 (apart from the REM lines, perhaps). Do not destroy it as the next section - Section 2.15 - uses it briefly.]





One of the most frequent uses of user sprites is so that they can be displayed in a Wimp program and/or printed from it. Sections 2.19 and 2.22 are devoted to that topic.


Also, if you recall the early part of Section 2.3 where we introduced the loading of a window template, user sprite areas can be used in icons in the window design provided that they are created prior to the window template loading. In that case, the user sprite area handle is put into the final parameter of FNwimp_loadwindow() - as indicated in that earlier reference.


The number of sprites in a spritefile can be obtained with FNwimp_countsprites, and the names of sprites in a spritefile can be found with FNwimp_getspritename.



Change of pointer sprite using icon validation string

It is convenient to end this section with a mention of a related matter. You may have noticed that, with some writable icons, when the pointer is over the icon it changes into a pointer looking like a caret. This is effected via the P-command of the icons validation string - see Section 2.28 - which simply changes the sprite used for the mouse pointer as it passes over the icon.


For example, in the validation field of  a writable icon you will probably see:


R7;Pptr_write


This particular validation string shows two Commands: an R-command and a P-command, separated by a semi-colon. The P-command specifies a sprite (which must be in the Wimps sprite pool) to be used for the pointer when over the sprite - and ptr_write is the name of the sprite. This sprite is a thin vertical red line - the caret. (R7 describes the particular border given to the icon.)


You will also often see other pointer shapes with other types of icons e.g. a menu shape over menu icons, and their validation strings will show a corresponding sprite from the Wimp sprite pool.



15. Icon sprites & more on the iconbar icon **

Sprite-only icons

If you have an icon which has been defined as a sprite-only icon (such as the file icon in a save window) then you can change it to another sprite by using PROCwimp_puticontext i.e. the same wimp-function that changes text in an indirected text icon. This will only work however, if the sprite-only icon is indirected and of sufficient indirected length, both of which are set up using a template editor.


For example, in the tutorial !RunImage from the previous Section, insert the following line just before ENDPROC in PROCuser_initialise:


PROCwimp_puticontext(save%,0,file_ffd)


(If you are using the nicesave template, the second parameter should be 3, not 0.)


Save the !RunImage, re-run !MyApp and bring up the save box from item 5 of the main menu. The file icon in the save window will now be the standard one for Data.



[The tutorial !RunImage listing RI_08 is not updated to reflect the above trivial change - but keep the whole of the !MyApp application as it now stands somewhere safe, ready to be used again briefly in Section 2.22. A copy exists in the Tutor1 folder for your convenience.

When the tutorial is picked up again in the next section - Section 2.16 - a fresh !MyApp will be started.]






The iconbar icon

This also is a good place to revisit:


FNwimp_iconbar(spritename$,text$,maxlen%,position%)


which we introduced briefly very early on in this tutorial - in Section 2.1. You will recall that we have so far set text$ to a null string and maxlen% to 0 - and the resulting iconbar icon has always been a sprite-only icon i.e. with no text beneath it.


By using other values for the second and third parameters, we can create an iconbar icon with text underneath the sprite and also arrange for this text to be indirected - with a maximum length determined by maxlen% - so that we can change it during the program run if we wish e.g. change the iconbar text (see a little later) to Loaded when file data has been dragged to it and loaded.


Firstly, it is vital to remember that the value you set in maxlen% will only come into effect if text$ is not set to a null string. (In fact, a null string triggers the action in the DrWimp library to create a sprite-only result.)


If you want a sprite-plus-text iconbar icon then a typical FNwimp_iconbar call might be:


iconbar%=FNwimp_iconbar(!myapp,MyApp,5,1)


and the result on the iconbar will be ...............

                                                                              


Here, the second parameter contained text which is 5 characters long and we matched this in the value of the third parameter. (Dr Wimp automatically adds one for the terminator character.) The text is centred on the sprite.


If the value set in maxlen% is less than the length of text set in text$, then maxlen% will automatically be increased to the length of text$. Further, if the value set in maxlen% is greater than the length of text set in text$, then the iconbar text space created will be sufficient to display text of this greater length i.e. ready for you to change the text up to this greater length later in the program.


Finally, if you do not want the initial iconbar icon to show any text but you want to add some later, then simply use something like:


iconbar%=FNwimp_iconbar(!myapp, ,5,1)


Note that the second parameter is not a null string but, rather, is a string with a space character in it. The result will be an iconbar icon with (centred) space beneath it for up to 5 characters (plus terminator) for you to use later in the program.


Once the iconbar icon has been suitably created, as above, its text and its sprite can be altered with PROCwimp_puticonbartext and PROCwimp_iconbarsprite respectively.


 (!Animate in the Example applications folder shows how the iconbar sprite can be changed within a program run, by using PROCwimp_iconbarsprite.)



Finally, a couple of pieces of practical advice:


- try not to use an iconbar text length which extends much beyond the width of the sprite used, otherwise the result looks somewhat ungainly on the iconbar.

- If your text consists of all wide characters (e.g. W) then it is possible that the displayed result on the iconbar might be clipped slightly at each end. If this occurs just increase maxlen% until the display is right.



(Note on iconbar position: Dr Wimp currently only provides a simple choice for positioning the icon on the iconbar i.e. right or left and you will see that your icon is added as the leftmost or rightmost, respectively, with this choice. The Wimp allows the iconbar icon to be placed more precisely than this. It is not difficult to achieve but the rules are too variable to arrange a useful generalised formula suitable for Dr Wimp. However, should any user be interested in more precise iconbar placement in a specific case, please contact the Dr Wimp author who will be very happy to assist further - see start of Manual for contact address.)

16. Bars and Sliders**

When you format a floppy disc a horizontal coloured bar increases in size to show the amount of the disc that has been formatted so far. Similarly, when you look at the free space on a floppy or hard drive you have several bars to show you how much space has been used up, how much is free, and what there is in total. In these examples the user cannot interact with the grapical bar: it is a passive display.


Conversely, when you use the Colour Picker (in, say, !Draw) the idea of a graphical bar is taken further, because there the user can move the bar in order to set a particular colour i.e. the display is interactive.


In Dr Wimp, the difference between these two types of graphical bar display is recognised by calling the passive display a bar and and the interactive display a slider - and Dr Wimp has facilities to handle both.



Bars

In structure, bars are only long, thin icons filled with a colour. DrWimp allows the length (or height) of bars to be changed. This means, for instance, that they can be changed continuously or only just before a window containing them is opened.


For our tutorial, make a fresh copy of the master skeleton !MyApp. From the Tutorial folder (Tutor2 sub-directory) drag the Template5 file into the !MyApp directory, and rename it as Templates.


Then add the following lines to PROCuser_initialise in !RunImage:


main%=FNwimp_loadwindow(<MyApp$Dir>.Templates,main,0)

iconbar%=FNwimp_iconbar(!MyApp,,0,1)

iconbarmenu%=FNwimp_createmenu(MyApp/Quit,0)


and in PROCuser_mouseclick:


IF window%=iconbar% THEN PROCwimp_openwindow(main%,1,-1)


and in FNuser_menu:


return%=0

IF window%=iconbar% THEN return%=iconbarmenu%

=return%


and in PROCuser_menuselection:


IF menu%=iconbarmenu% AND item%=1 THEN PROCwimp_quit(0)


If you now double-click on !MyApp you should get an icon on the iconbar with a menu with a Quit item. Clicking on the icon should produce a small window with a red bar in it.


What we are now going to do is set the bar to a random length when it is clicked on. First we need to know what the maximum length of the bar is, so load the templates into !WinEd by dropping the file onto !WinEds iconbar icon.


In !WinEds main window, double-click on  main. Move the pointer over the bar and look at WinEds Monitor window.


The Monitor window shows that the bars icon number is 1 and that the icons dimensions are 340x36, so the max length is 340.


Take a look at all the details of the bar icon by double-clicking on it in the !WinEd display. This is how you should set up any icons you want to use as bars. Obviously you can change the size, colour and turn the border on, etc.


(Dr Wimp has a wimp-function to tell you the size of icons in a loaded window without using !WinEd, but the above method was chosen here so that you could see the other icon details.)


Returning to !RunImage, add the following line to PROCuser_mouseclick:


IF window%=main% THEN PROCchangelength


Now add the following function to the end of !RunImage:


DEF PROCchangelength

len%=RND(340)

PROCwimp_bar(main%,1,len%,0)

ENDPROC


Re-load !MyApp, and click on the bar or the frame icon behind it. You will see the bar jump to a different (random) length each time you click.


If you want to specify the length as a percentage, just alter PROCchangelength to:


DEF PROCchangelength

len%=RND(100)

len=(340/100)*len% :REM** To factor the bar length correctly. **

PROCwimp_bar(main%,1,len,0)

ENDPROC


As you can see, len% is a percentage chosen at random. (Note change to len from len% in PROCwimp_bar(). )


You can change the bar to look like however you want it, but we would advise against adding any text, sprites, or indirected text.


One thing you might like to do is add a border around the bar by clicking on the Border icon in the relevant !WinEd window. However, if the bar is going to be changing in size rapidly then the part of the border at the right edge may flicker a lot as that part of the screen is constantly redrawn.


If you want the bar to be a vertical one, i.e. it resizes vertically instead of horizontally, then set the fourth parameter of PROCwimp_bar to 1 instead of 0.


And just to finish off, to get an animated bar (without any explanation, at the moment!) alter PROCchangelength to:


DEF PROCchangelength

pcent%=0

REPEAT

 	nlen=(340/100)*pcent%

  	PROCwimp_bar(main%,1,nlen,0)

  	PROCwimp_singlepoll

  	pcent%+=1

UNTIL pcent%>100

ENDPROC


Now when you run the application the bar increases fairly smoothly from 0 to 100%.


You should be able to see that it is now the basis for an internal multitasking operation with the percentage done depicted by the bar. See Section 2.26 for further insight into multitasking.



[Your !RunImage listing should now look like listing RI_09 in Tutor2 (apart from the REM lines, perhaps). Do not destroy it as the following sections continue the tutorial from this stage.]



(See the end of this Section for some general comments on the practical use of bars/sliders.)



Sliders


Structurally, sliders consist of three icons, and must be constructed in a certain way in order to work properly:



The slider back icon goes completely under the slider icon, and defines the total area over which the slider can be dragged. The slider and slider back icons must both have a button type of Click/Drag, be filled and have no borders. They can be any thickness, length or colour you like.


Continuing with our tutorial, copy the file Template6 from the Tutorials folder (Tutor2 sub-directory) into !MyApp and rename to Templates. 


Load Templates into !WinEd and note that in the window slide there are two sliders with associated text icons. Check how the sliders are constructed in detail and make a note of the various icon numbers.



Now, in the tutorial !RunImage, delete (or, better, type REM at the start of) the line where the main window is loaded and after it add:


slide%=FNwimp_loadwindow(\"<MyApp$Dir>.Templates\",\"slide\",0)


Alter the window%=iconbar% part in PROCuser_mouseclick so that is is like:


IF window%=iconbar% THEN PROCwimp_openwindow(slide%,1,-1)


Run !MyApp and you will see that the slider window that appears has two sliders in it. Currently they do nothing.



In the same way that FNuser_savefiletype makes save windows work as soon as some value is returned for them, sliders work as soon as you return relevant values from two related user-functions:


FNuser_sliderback()

FNuser_slider()


FNuser_sliderback is used to tell the Wimp which slider back icon is linked with which slider icon. For the top slider, the slider is icon number 2, and the slider back icon is icon number 1.


So add the following line to FNuser_sliderback:


return% = -1 :REM** Note this empty value, as icons can have the number 0. **

IF window%=slide% AND icon%=2 THEN return%=1

=return%



To complete the pairing, FNuser_slider must also be used to return the icon number of the slider icon, when given the slider back icon number. So, add the following complementary line to FNuser_slider:


return% = -1

IF window%=slide% AND icon%=1 THEN return%=2

=return%


Hopefully that should be clear, and running !MyApp will  now enable you to click on the top slider or the slider back to make it jump to various positions. You can also drag the slider left and right. 


The basics are as simple as that.


But a slider is no good unless you can get a value for it.........


When a slider is moved or dragged,


PROCuser_slidervalue(window%,icon%,pcent%,direction%)


is called automatically, and the percentage of the slider concerned (and its direction, hor/vert) is passed to you in its parameters. So add the following lines to this user-function:


IF window%=slide% AND icon%=2 THEN

  	PROCwimp_puticontext(slide%,3,STR$(pcent%))

ENDIF


STR$(pcent%) converts the percentage to a string, suitable for passing to PROCwimp_puticontext. Icon number 2 is the slider icon and icon 3 is its associated text icon.


Run the application now and you will see the percentage displayed in the box on the right as the slider is moved.


Add the following line to FNuser_sliderback():


IF window%=slide% AND icon%=6 THEN return%=5


and this line to FNuser_slider():


IF window%=slide% AND icon%=5 THEN return%=6



and finally these lines to PROCuser_slidervalue():


IF window%=slide% AND icon%=6 THEN

 	PROCwimp_puticontext(slide%,7,STR$(pcent%))

ENDIF


The bottom slider should now also work, independently.


The percentage can be scaled up or down so different ranges can be used, e.g. 0-255.


Also, the current static percentage of a slider can be read using FNwimp_getsliderpcent and the percentage of a slider can be set using PROCwimp_putsliderpcent. Try these out to see their effect.


Vertical sliders can also be made. If the slider is made higher than it is wide, then DrWimp will automatically assume its a vertical slider.



[Your !RunImage listing should now look like listing RI_10 in Tutor2 (apart from the REM lines, perhaps). This listing is not altered further. When the tutorial is picked up again - in Section 2.26 - a fresh !MyApp will be started.]


Additional comments about bars and sliders


- The example applications !Bar and !Sliders show typical usage.

- In addition, these example applications both introduce nudgers/bump icons (the Style Guide calls them adjuster arrows) which are often used to complement sliders/bars by providing a means to fine-tune values set with a slider/bar. The listings will show that bumpicons/nudgers are simple to implement using standard Basic statements - and Dr Wimp also has Elixir_05 to provide a flexible standardised coding.

- The example applications also demonstrate some of the practical issues in using sliders/bars - not unique to Dr Wimp. For instance, it is often not possible to use the mouse pointer accurately enough to set every value in the slider/bar range (hence the need for nudgers/bump icons).



17. The redraw process

As you will already have seen, if you have a window where all the action takes place in icons, the Wimp automatically does all the updating for you when you open/move/update the window.


However, if your window has some graphics/text plotted straight onto the window background (which we will call user graphics) then the Wimp needs your help to draw/redraw them when necessary. For example, you could be using PROCwimp_plotwindowcircle() to draw a circle in a window.


The Wimp asks for this help by asking you to redraw all or part of the user-graphics whenever needed. Mostly, redrawing is necessary every time a window is moved/scrolled etc., because moving/scrolling a window on the screen is done by successively deleting and re-opening it.


It is vital to note that, in order for the redraw process to work, the window must have its auto-redraw flag unset - which is normally done in the template editor.


In Dr Wimp, when the Wimp wants a redraw, PROCuser_redraw() is called automatically. In its parameters, the handle of the window is passed, plus the position of the particular rectangle on the screen that needs to be redrawn - and the Wimp may call PROCuser_redraw() several times for different rectangles, to build up the total area to be redrawn.


The programmer has to decide how best to redraw each rectangle: the simplest option is to redraw all the user-graphics in the window - and this is often acceptable. But if the window is large and/or the graphics complicated a total redraw may take too much time and slow down other user-actions e.g. moving the window. In these cases you will need to arrange the coding so that only the parts required are redrawn, although this adds complication to the coding. (The Example application !Grid shows how this can be done.)


This Manual will not cover in detail the principles behind the redraw process (although this is done in the charity book Dr Wimps Surgery, mentioned in Section 1.1).


However, Dr Wimp has many wimp-functions to assist with the redraw process and later sections give details about the more likely needs e.g. Section 2.19 (for displaying Drawfiles, Sprites and JPEGs) and Section 2.21 (for plotting Text). There is also Elixir_01 for helping to provide fast-scrolling lists with plotted text.


There are also mini-applications in the Examples folder showing how PROCuser_redraw() and Elixir_01 are used in practice.



18. Large menus, rebuilds and Font menus

This section is again concerned with menus - including how to create very large menus, how to completely change a menu (ie. a re-build), and add and remove items. Also, how to create menus of the fonts loaded in your machine.


Please note that Dr Wimp creates all the title and item text in menus as indirected - and therefore you do not need to worry about the maximum text length. These should be transparent features but it may help if/when you examine the coding in the DrWimp library.


Allowing for extra menu items

Menus can be created so that they can grow and shrink in accordance with what your application wants.


You should recall from the introduction section that when a menu is created a block of memory of a fixed size is reserved to put the data that the Wimp needs in. So for example:


menu%=FNwimp_createmenu(MyApp/Info/Quit,0)


will reserve a block of memory (handle/start address assigned to menu%) just big enough to hold the menu with only the two items specified.


But what happens if you want to add another item to the menu? This would create three items, so all the data for one item will be pushed into the next part of the memory. This could be holding the contents of variables that you are using, thus corrupting them, or even more likely you will crash the application, because you are trying to write to some memory addresses that dont actually exist (address exception errors are the result of this).


What is needed is a way of making sure the block of memory is big enough. This is where the last parameter to FNwimp_createmenu comes in. If it is less than or equal to the number of items specified in the string, then the block of memory will be just big enough to hold the items given. If it is bigger, then it is the maximum number of items that can be on that menu.


So if you used:


menu%=FNwimp_createmenu(MyApp/Info/Quit,20)


then you would create a menu the same as before, but you can have up to 18 further items added to it later on.


The created maximum number of menu items is stored with each menus definition and can be read using FNwimp_menumaxsize().



Adding/deleting menu items

PROCwimp_putmenuitem and PROCwimp_removemenuitem add and remove items from menus. Note: a non-fatal warning is given if the menu is already at its maximum size (as defined at its creation) and therefore cannot accept extra menu items.


PROCwimp_putmenuitem(menu%,item%,item$)

PROCwimp_removemenuitem(menu%,item%)


The parameters are mainly self explanatory. If item% in PROCwimp_putmenuitem is greater that the total number of existing items+1 then it will just be added onto the end. If item% is less than or equal to the number of existing items, the new item is inserted at item% and those below it are shuffled down. Removing items works similarly, with remaining items being shuffled up.



Re-creating the whole menu

If you wanted to re-build or re-create a menu from scratch again, but still have the same handle as the last one, then you could call FNwimp_createmenu, which would get another chunk of memory and put the data needed into it. This means that the block of memory with the original menu in is still occupied and therefore wasted. If you do this repeatedly then more and more memory is taken up until your application runs out, crashing it.


A much better way is to use the wimp-function PROCwimp_recreatemenu, which updates the data in the block of memory containing the old menu.


PROCwimp_recreatemenu(menu%,menu$)


menu% is the handle of the menu to re-create. menu$ is a string to build the menu from, and is in the usual form, eg:


MyApp/Info/..../..../Quit


The number of items in the new (re-created) menu must not be greater than the specified maximum value when FNwimp_createmenu was called - and a warning will be given is this is being attempted.


When a menu is re-created, all the item attributes like dotted lines, greying out, and ticks are removed and therefore need to be subsequently re-applied if still wanted. (And dont forget that the item number for Quit might well change - the tip given earlier is very useful here.)


If you want to change only the text of menu items then use PROCwimp_putmenutext instead, as all the attributes are then retained.



Handling very large menus

However, FNwimp_createmenu and PROCwimp_recreatemenu have a major limitation: very large menus cannot be built - simply because the slash-separated menu text is a single string, which is limited to 255 characters.


DrWimp provides two solutions to this - using arrays or message files. These are examined in turn below.


Menus from string arrays

The first solution is to put all the menu items into an array, then build the menu from the array. This lends itself very well to reading in items of data from support files for your application.

For this method, you firstly need to decide the maximum number of items in the menu. Add one to the total size, and DIM a string array.


Then fill the array elements with the required item text - array element 1 for menu item 1, element 2 for menu item 2, etc. The first element of the array (element 0) is for the menu title. The last item must be the string END, so DrWimp knows how much of the array to use. 


Note: END will not appear as a menu item; the element before it will be the last one.



Here is some example code:


maxitems%=20

DIM menu$(maxitems%+1):REM** array large enough for 20 menu items. **

menu$(0)=MyApp:REM** Menu title string. **

menu$(1)=Info :REM** First menu item. **

menu$(2)=Options :REM** Second menu item. **

menu$(3)=Quit :REM** Third (and last, here) menu item. **

menu$(4)=END

iconbarmenu%=FNwimp_createmenuarray(menu$(),20)

PROCwimp_attachsubmenu(iconbarmenu%,1,info%)


which will create a three-item menu with the title MyApp and items Info, Options and Quit.


As you can see, FNwimp_createmenuarray is passed the name of the array (with empty brackets) and the maximum number of items. The last parameter is exactly the same as for FNwimp_createmenu. So it could be made 0 if the size is not going to change subsequently. Here it is set to maxitems%. (Note that END always needs to be put in the array element after the current last item. If re-creation causes the number of items to increase then END needs to be moved accordingly.)



Menus can be re-built using arrays as well. Instead of using PROCwimp_recreatemenu, use:


PROCwimp_recreatemenuarray(menu%,array$())

Menus from Message files

It is also possible to create menus automatically from a message file - and you may need to refer back to Section 2.9 to recap on the message file structure in the following.


The big advantage of using this method is that the size of the menu is not restricted in any way.



The following is an example of the necessary message file structure and - as with all message files - the first step is to initialise the message file (with FNwimp_initmessages()) to obtain its handle. We will assume that this has been done and that the handle is messagefilehandle%:


BMenuT:Iconbar menu

BMenu1:Info

BMenu2:Quit



Then,  by using:


iconbarmenu%=FNwimp_createmessagemenu(messagefilehandle%, \"BMenu\",\"\",0)


a menu will be created with the title Iconbar menu, and two items, the first being Info and the second being Quit. The first parameter of the above wimp-function is the messages file handle. The second is the token string (see Section 2.9) and is used to find the individual items of the menu in the messages file. token+T is the title, token+1 is item one, token+2 is item 2 and so on.


The third parameter is the menu title. In this case its an empty string, so the one in the messages file is used. If, instead, we had put:


iconbarmenu%=FNwimp_createmessagemenu(messagefilehandle%, \"Bmenu\",appname$,0)


then the menu title would be the string appname$, overriding the title in the messages file. In fact if you specify a menu title, then the token in the messages file for the title doesn't have to be included, and you can just specify the items.


The final parameter is the maximum size of the menu. It is exactly the same as the last parameter of FNwimp_createmenu.



It is vital to note that the Wimp demands very strict discipline of the message file structure. For instance:


BMenuT:Iconbar menu

BMenu2:Quit

BMenu1:Info


would fail, simply because the entries must be in the same file position as their number sequence.

Further, Dr Wimp also imposes a small format requirement concerning the title item. As has already been stated, there is no need to include a title item - but it is essential not to include the title token element with a null string entry e.g.:


BMenuT:

BMenu1:Info

BMenu2:Quit


will fail (and you will find that an extra blank menu item occurs as a result).



From Dr Wimp 3.61 onwards (as already mentioned in Section2.9) there is also:


PROCwimp_recreatemessagemenu(menu%,messagefilehandle%,token$,

                                                      title$)


whose use should now be self-explanatory, and:


FNwimp_getnumberofmessages(messagefilehandle%,token$)


which reads a messages file and returns the number of messages in it having the given token.



Flexibility

A menu that has initially been created with any one of the three wimp_createmenu.... functions can be recreated with any one of the three wimp_recreatemenu... functions.


Dynamic sub-menu manipulation

Finally in this section, we come to PROCuser_overmenuarrow. This user-function is called whenever the mouse pointer passes over one of those little arrow-heads to the right of a menu item when it has a sub-menu (or window) attached to it. Its format is:


PROCuser_overmenuarrow(rootmenu%,rootmenuitem%,RETURN nextsubmenu%,nextsubmenunumber%,parentmenuitem%,x%,y%)


The parameter rootmenu% holds the handle of the root menu and rootmenuitem% holds the currently selected menu item in that root menu. (The root menu is the first menu of the particular menu tree in use.)

The handle of the sub-menu/window about to be opened is given in nextsubmenu% (note this is a RETURN parameter, see later) and its position in the current tree in nextsubmenunumber% i.e. if the sub-menu about to be opened is the first submenu of the tree then nextsubmenunumber% will be 1, and if it is the second sub-menu it will be 2, etc.

The menu item number of the item whose arrow-head the pointer is over will be contained in parentmenuitem% and the x/y values (in screen OS units) of the pointer position when moving over the arrow head will be in x%, y%.


This user-function provides considerable flexibility for handling menu trees - including the means to alter/rebuild etc. the about-to-be-opened sub-menu dynamically if you so wish - or even to display a totally different sub-menu/window.


For example, assuming the standard main menu with Info as its first item and the sub-menu (a window, here) handle of info% attached to it, you could make PROCuser_overmenuarrow look like:


DEF PROCuser_overmenuarrow(rootmenu%,rootmenuitem%,RETURN nextsubmenu%,nextsubmenunumber%,parentmenuitem%,x%,y%)

CASE nextsubmenu% OF

	WHEN info%

	CASE parentmenuitem% OF

		WHEN 1: PROCwimp_puticontext(nextsubmenu%,0,TIME$)

	ENDCASE

ENDCASE

ENDPROC

which would put the current time into icon number 1 of the info window each time you open it.


Another practical example might be:


CASE nextsubmenu% OF

	WHEN submenu1%

	CASE parentmenuitem% OF

		WHEN 2

		IF condition%=TRUE THEN

			PROCwimp_menuenable(nextsubmenu%,3,1)

		ELSE

		  	PROCwimp_menuenable(nextsubmenu%,3,0)

		ENDIF

	ENDCASE

ENDCASE


which would grey out Item 3 of the up-coming submenu if the current state of condition% is FALSE or enable the same item if condition% is TRUE - with condition% only being tested at the time the pointer goes over the arrowhead.


This user-function is particularly useful for large menu trees e.g. if you have a fourth sub-menu about to be opened from a third sub-menu then PROCuser_overmenuarrow will be called with the fourth submenu handle in nextsubmenu%, the value 4 in nextsubmenunumber% and the third sub-menus currently selected item number in parentmenuitem%. (And, of course, the root menu handle and selected item will always be contained in  rootmenu% and rootmenuitem%.)


Note that the x/y values made available in this user-function can often conveniently be passed directly through to other wimp-function calls that you might make here, for example to open a window at a certain place relative to the x/y values.


Finally, the purpose of the RETURN with the first parameter of this user-function. With this you can, if you so wish, completely change the sub-menu/window handle at this same over arrow-head point e.g. so that the user is presneted with one sub-menu/window in one set of circumstances and another in another set.


This is effected simply by reassigning the variable nextsubmenu% within the user-function. For example:


DEF PROCuser_overmenuarrow(rootmenu%,rootmenuitem%,RETURN nextsubmenu%,nextsubmenunumber%,parentmenuitem%,x%,y%)

CASE nextsubmenu% OF

	WHEN info%

	IF registered%=FALSE THEN nextsubmenu%=unreginfo%

ENDCASE

ENDPROC


This would substitute the window unreginfo% for info% if the flag registered% is FALSE. (The window unreginfo% would, of course, need to be already loaded.)


As you can see, PROCuser_overmenuarrow really does allow you to manage your menus comprehensively.



Font menus

In some applications the user needs to select the font he/she requires for display or printing. This is invariably done by providing the user with the means to display a menu of the available fonts - which are those which have been loaded into your machines !Fonts application, or otherwise made active by a font manager utility. (A quick look at Style.Font name from the main menu in a !Draw document will refresh your memory on what a font menu looks like.)


To produce menus of current fonts in your own applications, two wimp-functions are available: namely FNwimp_createfontmenu, which has no parameters, and FNwimp_recreatefontmenu(), which has one parameter.


FNwimp_createfontmenu creates a font menu definition - comprising the full menu/sub-menu tree of all the fonts currently active on the users machine - and returns the corresponding menu handle.


Should you wish to re-create an existing font menu definition, then FNwimp_recreatefontmenu(fontmenu%) is used - where fontmenu% is the existing font menus handle.


If you want a font menu to appear as a sub-menu then the font menu handle can be attached to a normal menu/sub-menu  in the usual way - using PROCwimp_attachsubmenu().



Bearing in mind that the fonts available on any machine might well change during the run of your Dr Wimp application, it is usual to make an initial creation of a font menu at application start-up i.e. within PROCuser_initialise, and then re-create the font menu immediately prior to each opening of that font menu.


You can also create multiple font menu definitons, each with its own handle - for applications where you need to provide more than one independent font menu actions e.g. for changing the font independently in two icons in the same window.


As will be explained in more detail later, selection from a font menu is made in the usual way and the selected full font name (period separated) is automatically passed to the third parameter in:


PROCuser_menuselection(menu%,item%,font$)


In addition (and this is different from the practice with normal menus) the font menu handle is passed in menu%.


With normal menus/sub-menus, where the programmer always knows all the menu and sub-menu handles, menu% will hold the handle of the menu or sub-menu from where the selection was actually made. However, with font menus, the programmer only knows (and only needs) the handle of the complete font menu definition and does not know the many font sub-menu handles. So it is the overalll font menu handle which is passed in font menu cases, irrespective of where, in the font menu tree, the font selection is made.



The programmer can thus use the menu% and font$ information as he/she wishes, in the usual Dr Wimp way.



With the above we can now look at some practical usage.


To create a font menu, all that is necessary is to use a line such as:


FontMenu1%=FNwimp_createfontmenu


and thats all there is to it. Here, the handle of the font menu has been assigned to the variable FontMenu1% which can then be used in the same way as any other menu handle.


However - because of the point made earlier about catering for changes in the active fonts made during the run of an application - it would be sensible to place the above creation call in PROCuser_initialise and then arrange to re-create the font menu afresh each time it is to be displayed.


Thus, for example, after making the above call, if you wanted to display the up-to-date font menu when <menu> is pressed over a particular window, then you might code of FNuser_menu() as follows:


DEF FNuser_menu(window%,icon%,screenx%,screeny%)

return%=0

CASE window% OF

	WHEN main%

   FontMenu1%=FNwimp_recreatefontmenu(FontMenu1%)

   return%=FontMenu1%

ENDCASE

=return%


This would ensure that you always see the up-to-date font list.


Similarly, if you wanted the menu to appear by using PROCwimp_menupopup() then you would use PROCuser_mouseclick() and, again, display the menu just after a re-creation call.



As already stated, if you want the font menu tree to open as a submenu off an item in another (already defined!) menu, then you simply use PROCwimp_attachsubmenu() in the normal way. This will automatically attach the complete font menu tree (i.e. with all its font sub-menus) as a sub-menu structure.


Thus, if you also wanted the same font menu to appear as a sub-menu from Item 2 of an iconbar menu you would simply add:


PROCwimp_attachsubmenu(Iconbarmenu%,2,FontMenu1%)


to PROCuser_initialise after the initial creation of FontMenu1% - and then make DEFFNuser_menu() look like this:


DEF FNuser_menu(window%,icon%,screenx%,screeny%)

return%=0

CASE window% OF

WHEN Iconbarmenu%

 	FontMenu1%=FNwimp_recreatefontmenu(FontMenu1%)

 	return%=FontMenu1%

WHEN main%

   FontMenu1%=FNwimp_recreatefontmenu(FontMenu1%)

   return%=FontMenu1%

ENDCASE

=return%



Further, if you needed the actions resulting from the main% and Iconbarmenu% font selections to be completely independent then it would simply be a matter of creating a second font menu as FontMenu2% in PROCuser_initiliase and substituting that in one of the above cases e.g.:


DEF FNuser_menu(window%,icon%,screenx%,screeny%)

return%=0

CASE window% OF

WHEN Iconbarmenu%

 	FontMenu1%=FNwimp_recreatefontmenu(FontMenu1%)

 	return%=FontMenu1%

WHEN main%

   FontMenu2%=FNwimp_createfontmenu(FontMenu2%)

   return%=FontMenu2%

ENDCASE

=return%



For even more flexibilty with a font menu as a sub-menu, you could also use PROCuser_overmenuarrow(). For example:


DEF PROCuser_overmenuarrow(rootmenu%,rootmenuitem%,RETURN nextsubmenu%,nextsubmenunumber%,parentmenuitem%,x%,y%)

CASE nextsubmenu% OF

	WHEN FontMenu1%

 	REM** FontMenu1% is previously-created font menu handle and previously attached as a sub-menu to a menu. **

 	FontMenu1%=FNwimp_recreatefontmenu(FontMenu1%)

	nextsubmenu%=FontMenu1%

ENDCASE

ENDPROC


This method relies on the RETURN in the third parameter to change the sub-menu handle (in nextsubmenu%) to the one just newly re-created - and this occurs each time the pointer moves across the menu arrow.



Font menu selection

Having got the font menu displayed we need to look at PROCuser_menuselection() to see how to retrieve and use the font selection. The user-function is:


DEF PROCuser_menuselection(menu%,item%,font$)


As usual, when a selection is made from any menu, this user-function is called automatically by Dr Wimp with the parameters set to the live values ready for your use. With font menus the only differences are that:


-  for a selection from a normal menu: menu% and item% are used as normal, but font$ is always set automatically to a null string; and

- for a selection from a font menu: item% is always automatically set to 0; menu% is set to the font menu handle and font$ carries the complete period separated font name. (To be absolutely clear: if you have created a font menu with the handle FontMenu1% and made a font selection from it, then menu% will always hold the value FontMenu1% - whether you made the selection from the root of the font menu or one of its sub-menus.)

So, a typical general coding might include:


DEF PROCuser_menuselection(menu%,item%,font$)

....

....

IF font$<> THEN

    CASE menu% OF

    WHEN FontMenu1%

	    selectedfonthandle1%=FNwimp_getfont(font$,12,12)

	    <etc.>


    WHEN FontMenu2%

    selectedfonthandle2%=FNwimp_getfont(font$,16,16)

	    <etc.>

    ENDCASE

ENDIF

....

....

ENDPROC



To help take advantage of the font menu facilities the wimp-function:


PROCwimp_puticonfont(window%,icon%,fonthandle%)


allows the font used for text in an icon to be changed.


The usage should be self-explanatory, but you do have to ensure that the icon definition specifies that an outline font is used - otherwise a non-fatal error occurs and no change is made.


The Example application !FontMen demonstrates these font menu facilities.


Finally, it needs to be noted that the detailed contents of font menus cannot be changed in the same way as other menus - and, in fact, you would not normally wish to do so. For example, you cannot add/remove items with PROCwimp_putmenuitem/PROCwimp_removemenuitem, nor can you colour an item with PROCwimp_menuitemcolour, etc. etc.


So, all of the menu contents changing wimp-functions (although still usable with ordinary menus) will give a non-fatal error if you try to apply them to a font menu. However, FNwimp_menusize can still be used.



19. Displaying Sprites, Drawfiles and JPEGs

The display of these common graphics files is straightforward using Dr Wimp and they all use a common approach designed to involve PROCuser_redraw().


Similarly, generally, the graphic file needs to be loaded into memory first - using the sequence described in Section 2.12 and choosing the correct file-loading wimp-function depending whether the file is a sprite, drawfile or JPEG.


It is worth noting at the outset that the display of graphics and the printing of graphics are very much related in Wimp programs and in many cases the same functions are used for both - under the general heading of rendering a graphic. This will explain why many of the wimp-functions use render rather than display or print in their function names.



There are a few differences between the different types of graphics files and these will be covered in the individual sub-sections below - and the first sub-section on Sprites will contain a detailed description which will generally apply to all the graphics types.



Sprites


Assuming that the sprite-file has already been correctly loaded into memory as in Section 2.12 - and that the main wish is to display a sprite in an applications window - the wimp-function to use for displaying the sprite is:


PROCwimp_renderwindowsprite(window%,sname$,sarea%,bx,by%, minx%,miny%,maxx%,maxy%,xscale,yscale)


This looks more complicated than it is. window% is the handle of the window in which the sprite is to be displayed - and it is vital that this window was created with its auto-redraw option unticked.


sname$ is the sprite name within the sprite-file - already loaded at sarea%.


bx% and by% are the work area coordinates (in OS units) of the bottom left-hand corner of the required sprite position in the window. i.e. the x/y values with reference to the top left corner of that window - so all visible y values will be negative.


minx%,miny%,maxx%,maxy% are the coordinates of the rectangle to be redrawn (the clipping rectangle), Thses do not need to worry us here because they are merely copied through directly from the parameters passed in DEF PROCuser_redraw() where you will see the same set of four values.


xscale and yscale (note real rather than integer numbers) are your required x/y scaling factors for the sprite, with values <1 meaning a reduction in size and values >1 meaning enlargement, in their respective directions.


This one call can simply be placed inside DEF PROCuser_redraw() - with suitable filtering to ensure that it is only relevant to the window intended. E.g. for a sprite called mysprite already loaded into block%, the coding might be:


DEF PROCuser_redraw(window%,minx%,miny%,maxx%,maxy%, printing%,page%)

CASE window% OF

    WHEN main%

        PROCwimp_renderwindowsprite(window%,mysprite,block%, 100,-300,minx%,miny%,maxx%,maxy%,1,1)

ENDCASE

ENDPROC


which will - if the window is fully visible and not scrolled - display the sprite at full size in the window with its bottom left corner at a position 100 OS units in from the left-hand edge of the window and 500 OS units down from the top edge of the window.


Note the important point that it doesnt matter where the window is moved to on the screen: this call will ensure that the Wimp will automatically keep the sprite displayed in the correct relative location. By the same token, if you scroll the window the sprite will stay in the same position relative to the true window left/top edges - so the sprite will move to the left if you scroll the window horizontally and will start to disappear as the scroll exceeds 100 OS units.


If you were to set the value of the sprite area parameter to 0 (it is set to block% above) it would be telling the Wimp that your chosen sprite is already in the Wimp sprite pool and you could then use any of the sprite pool sprite names for display e.g. all the sprites in Resources:$.Resources.Wimp.Sprites would be available to display.


In the Examples folder there is a full application demonstrating these rendering operations.


It is worth noting that we have ignored the passed parameters printing% and page% here. As you will have guessed they come into there own when printing and are not used when only displaying, but it reinforces the earlier point about the use of redraw for both printing and display..


There is a counterpart to PROCwimp_renderwindowsprite called PROCwimp_rendersprite i.e. without the window in its name. Accordingly, it does not have the window% parameter but is otherwise the same. Its purpose is predominantly for printing and, when used, the bx%/by% are put in screen/paper coordinates i.e. with reference to the bottom left corner of the display screen (see Section 2.22).


There is also a wimp-function for finding the width/height of a sprite. It is:


FNwimp_getspritesize(sname$,sarea%,side%)



where the first two parameters are as before and side% is set to 0 to get the width, or 1 to get the height - both in OS units.



Please note that sprites can also exist within a drawfile and they are then automatically rendered/printed using Dr Wimps drawfile facilities, as described below.



With regard to sprites in the Wimp pool, you will be aware that it is normal for all applications to add some items to this pool, via an *Iconsprites call in their !Run and/or !Boot file. For instance, the unique sprite(s) for an applications filer icon and iconbar icon would normally be loaded into the Wimp sprite pool in this way and that is quite correct.

There is therefore a temptation to treat all of your sprites in this way, but it has the major disadvantage of taking up memory space even after the application has been quit. So you should use the user sprite area approach for all other sprites.





Drawfiles

(Note: rendering drawfiles with Dr Wimp requires RISCOS Version 3.60 or higher.)


Unlike sprite-files, a drawfile contains only one draw document - but this can, of course, be made up of numerous objects including text, sprites, transformed text, transformed sprites and JPEGs.


Before display, a drawfile needs to be loaded into memory as described in Section 2.12.


But there is also one further thing that needs to be done - a single call to PROCwimp_initdfile needs to be made.


It has no parameters and only needs to be made once, for any number of drawfiles. Its role is to set up some small special memory blocks behind the scenes and the details do not need to concern us here.


As with sprites, the main call of interest for displaying a drawfile has window in its name. It is:


PROCwimp_renderwindow(window%,dfile%,bx%,by%, minx%,miny%,maxx%,maxy%,xscale,yscale,origin%)


The only differences from the sprite equivalent call are that, firstly, xscale and yscale can take negative numbers which will render the drawfile back-to-front and/or upside-down (but this will not work for JPEG objects in a drawfile).


Secondly, the handle of the stored drawfile, dfile%, is sufficient in the drawfile case and there is the added parameter called origin% which is a flag to activate an optional feature explained below.


The natural origin of all drawfiles is the bottom left corner of the !Draw page. However, very often, a drawfile is constructed of objects drawn higher up on the page - with, say, some empty space below and/or to the left of a rectangular bounding box which would just surround all the objects, as below:





Such a drawfile can be rendered in one of two ways: if origin% is set to 0 then the whole drawfile page will be rendered naturally i.e. the bottom left corner of the drawfile page (A) will be located at the specified x/y position. However, if origin% is set to 1 then the drawfile will be rendered with the bottom left corner of its overall bounding box (B) located at the specified x/y position - i.e. exactly as if the overall bounding box of the objects was at the bottom left corner of the drawfile page.


This latter option makes it much easier to place drawfile objects exactly where you want them without needing to worry about any unwanted offsets which may occur when using natural rendering. This option also correctly takes into account any scaling required by xscale and yscale.


As with the sprite case, there is a counterpart to PROCwimp_renderwindow for drawfiles called, simply, PROCwimp_render i.e. without the window in its name. And as before, its purpose is predominantly for printing.


Also similar to the sprite case, FNwimp_getdfilesize returns the width and height of a drawfile. In fact, it returns the sizes of the bounding box containing all the drawfile objects.



(If you are using the utilities !FontFix or !SpecialFX at the same time as a Dr Wimp application which renders drawfiles a few users have reported a clash. The problem disappears if you disable those utilities temporarily - and their Help files say how.)



JPEG files


You will not be able to use Dr Wimps JPEG facilities if your RISCOS Version is less than 3.60 - but it might be possible if you load the SpriteExtend 0.99 Module available for download free at http://acorn.riscos.con/riscos/releases/spriteextend.arc


The JPEG format is a very popular method of storing digital images, particularly photographic images. Like sprites, it is a bit-map process. A JPEG file has a filetype &C85 (JPEG).


As for sprites and drawfiles, a JPEG file needs to be loaded into memory first, using the sequence described in Section 2.12.


Then, for displaying a JPEG in a window, this is the call:


PROCwimp_renderwindowjpeg(window%,jpeghandle%,bx%,by%, minx%,miny%,maxx%,maxy%,xscalereal,yscalereal)


It is entirely similar to the sprite case above, but now with jpeghandle% being the handle of the memory block where the file has been loaded.



As with the sprite and drawfile cases, there is a counterpart to PROCwimp_renderwindowjpeg called PROCwimp_renderjpeg i.e. without the window in its name. And as before, its purpose is predominantly for printing.


Also similar to the sprite and drawfile cases, FNwimp_getjpegsize returns the width and height of a JPEG. (There is an option to return either its natural size or the size for the JPEG displayed at 90dpi.)



(Note that JPEG images can also exist within a drawfile and are then automatically rendered/printed using Dr Wimps drawfile facilities, as described above.)



However, for JPEGs only, there is an option to carry out display-only operations (i.e. not printing) without needing to load the file into memory first.


The corresponding wimp-function calls are then:


PROCwimp_renderwindowjpegfile(window%,jpegfilepath$,bx%,by%, minx%,miny%,maxx%,maxy%,xscalereal,yscalereal,warning%)


PROCwimp_renderjpegfile(jpegfilepath$,bx%,by%,minx%,miny%, maxx%,maxy%,xscalereal,yscalereal,warning%)


FNwimp_getjpegsizefile(jpegfilepath$,side%,dpi90%,warning%)


and the use of the filepath rather than the memory handle should be self-explanatory. The only addition is the final parameter warning% which - as in several other wimp-functions - allows the programmer to choose whether or not a warning will be given if the filepath cannot be found.



Possible practical problems

The most common practical problems with displaying graphics concern getting the coordinates right i.e. with reference to the top left corner of the unscrolled window. Remember that displaying in a window uses the calls with window in their name - made inside DEF PROCuser_redraw() - and that all visible y-values are negative.


By and large, if your rendering action appears to produce nothing visible yet no error messages appear, then it is very likely that the rendering is actually off-screen/off page or outside the window (and with a drawfile this could also simply be the result of having the flag origin% set wrongly). (The charity book Dr Wimps Surgery takes you through the rendering and coordinate conversion processes step by step.)



You may (rarely) run across a sprite which does not render in the correct colours. If this happens, try using the alternative sprite rendering method i.e. if a sprite in the Wimp sprite pool gives wrong colours, copy it to a user sprite area and try again (not forgetting to reset the spritearea% parameter!) - or drag the sprite to a drawfile and render the drawfile instead.


Finally, as we have seen, the wimp-functions provided for rendering allow scaling in the x and/or y direction. However, any other required translation e.g rotation/shearing/reversal etc. of objects needs to be done previously in the source sprite/drawfile.



20. Dynamic Areas

(You will need a RISCOS Version of 3.60 or higher to use Dr Wimps Dynamic Area facilities.)


Often it is necessary to be able to load data into memory which is set aside for that purpose.


Traditional method

Traditionally, a block of memory to be used for data storage is created with something like:


DIM block% 2048


which creates a block, called block%, 2048 bytes in size (2049 bytes actually - bytes 0-2048!).


The main problems with this are that the size of the block, and hence the maximum size of data that can be loaded, in is hard-wired into the program and, further, the block needs to be catered for in the size of the WimpSlot.


One partial solution to this is to put the size of the memory block into the !Run file by using a system variable. Thus:


Set MaxSize 2048


and then reading the value of the system variable MaxSize into the program with FNwimp_getsysvariable and creating the block accordingly. However, this requires that the application user edits the !Run file - and maybe the WimpSlot too - so this solution is not ideal.


A better solution is to use a dynamic area.


Dynamic areas

A dynamic area is a block of memory - dedicated to your application - but it can shrink and expand in size, and it does not form part of the WimpSlot. The memory is taken from and returned to the free application memory pool as the block changes size, and thus the only limit on the size of a dynamic area is the amount of memory in the machine.


With Dr Wimp an application can create its own dynamic areas . These will be referred to as ADAs, for Application Dynamic Areas. Once created, these can then be expanded or shrunk as you wish - and they also appear in the Task Manager display.



The wimp-functions

DrWimp provides four wimp-functions for the creation, management and deletion of dynamic areas:


FNwimp_createdynamic()

FNwimp_changedynamic()

FNwimp_measuredynamic()

PROCwimp_deletedynamic()


Taking these in turn:


Creation


block%=FNwimp_createdynamic(size%,maxsize%,drag%,name$)


creates a dynamic area. The initial size, in bytes, is specified in size% and the maximum size to which this dynamic area can be expanded is put in maxsize%. It is important to try to set maxsize% to a realistic limit - and, often, size% and maxsize% can be made the same i.e. when you dont need to adjust the dynamic area size at all. If you really do not want to limit the maximum size and you dont know what value to use then you can set maxsize% to the special value of -1. This will then allow that dynamic area to expand up to the maximum your machine can cope with. But be warned! Using this value is not recommended as it can severely limit the use and management of dynamic areas and be the root of odd fatal errors.


name$ is the text that will be shown on the Task Display for this dynamic area - and setting drag% to 1 allows the size of the dynamic area to be changed by dragging the corresponding bar on the Task Display.


So, a typical call might be:


block%=FNwimp_createdynamic(1024,8192,0,\"Test DA\")


which will create a Dynamic area of 1024 bytes (but see later) with the capability of being expanded to 8192 bytes. The Task Display will show this area with the name Test DA but the area will not be able to be changed by dragging.



Note that RISC OS currently limits the minimum size of ADA dynamic areas to 4kbytes (4096 bytes) and also only allows ADA dynamic area sizes to be multiples of this same value i.e. ADA dynamic areas will only have values 4kbytes, 8kbytes, 12kbytes, ..... etc. There is no need for these exact values to be used in the calls: any specified value will be rounded up automatically. Provided that the actual size of an ADA is at least large enough for your needs it can be used without restriction. (Because of the 4k lumps, if the need is to load, say, more than one file into memory, then it would normally take less overall memory space to create one ADA to hold all the files - as described in Section 2.12.)



After creation of an ADA you can store data in it, such as drawfiles, spritefiles, or anything you like. The previous examples given for sizing and loading sprite-files, drawfiles and JPEG files need only substitute a dynamic area handle for the DIMmed handle. For example, if a sprite-file has the path path$ the measuring and loading sequence would be:


size%=FNwimp_measurefile(path$,0)

block%=FNwimp_createdynamic(size%,size%,0,Sprite Files)

d%=FNwimp_loadsprites(path$,block%,0)





Changing size

It is easy to change the size of an existing ADA with:


FNwimp_changedynamic(darea%,absolute%,size%)


darea% is the existing dynamic areas handle. If absolute% is set to 0 then the value of size% is treated as incremental (+ or -). If absolute% is set to 1 then the value of size% is interpreted as the new required size.


The function returns the handle of the re-sized ADA and it should be noted that it will not necessarily be the same as before. It is therefore quite common to use the call in the following way, re-assigning the new handle to the old handle:


For example, to increase a dynamic area by 4096 bytes:


block%=FNwimp_changedynamic(block%,0,4096)


or to shrink it by 4096 bytes:


block%=FNwimp_changedynamic(block%,0,-4096)


Or, to make the new size 8192 bytes:


block%=FNwimp_changedynamic(block%,1,8192)



Note that the previously mentioned point about ADA dynamic areas being constrained to steps of 4kbytes often has much more practical effect when changing dynamic area sizes. For instance,  reduction of less than 4kbytes will leave the actual size of an ADA dynamic area unchanged.



Finding the size of an existing dynamic area

The current size (in bytes) of an existing dynamic area can be obtained with:


size%=FNwimp_measuredynamic(darea%)


Deleting dynamic areas

When any dynamic area is finished with it is good housekeeping to delete it immediately - to avoid wasting memory. Simply use:


PROCwimp_deletedynamic(darea%)


(Note: Any dynamic areas created by your application with FNwimp_createdynamicarea() but not specifically deleted during the program run will be deleted automatically when you quit the application. This includes quitting due to most fatal errors.)


Note: To manage Dynamic Areas properly Dr Wimp needs to set the maximum number of dynamic areas that can be used by any one of its applications. This value is set by the global variable wMaxdynamicareas% in DEF FNwimp_initialise (near the start of the DrWimp library listing). As supplied, it is set to 16 which is likely to be more than adequate for most applications. However, the value can be changed for any specific application, if required.


21. Plotting text on the screen

You should, by now, be able to plot sprites, drawfiles and JPEG files in a window, using PROCuser_redraw. DrWimp provides similar facilities to plot text in a variety of ways directly onto a window or the screen, using outline fonts.


Choosing and defining a font

Before plotting text it is necessary to decide which outline font is to be used - and at what size and colour. Dr Wimp imposes no restrictions here.


Dr Wimp allows a font to be specified as a name or as a font handle - by conveniently providing complementary pairs of wimp-functions, as will be seen below.


Font names

Those wimp-functions requiring the name of the font use a string descriptor in what is called the period separated form. For example:


\"Trinity.Medium\"

\"Homerton.Bold.Oblique\"

\"Corpus.Medium.Oblique\"


i.e. there are periods (full stops) between each part - conforming with font file naming, in fact.


Font handles

Those text-plotting wimp-functions requiring a font handle need to be preceded by the use of a call to FNwimp_getfont(), such as:


fonthandle%=FNwimp_getfont(font$,pointsizex,pointsizey)


where font$ is the period-separated font name (as described above) and pointsizex, pointsizey are the required font width and height in points. Note that these latter two are not integer parameters, so decimal values can be used.


The return is the font handle - here, fonthandle% - which is unique to the specific font name/size combination. If the font name cannot be found (most usually because the named font is not present on your computer) the return will be 0 and you will need to take account of this and perhaps arrange for one of the RISCOS standard fonts to be used instead and warning the user accordingly.


It is often best to call FNwimp_getfont() during an applications initialisation i.e. inside DEF PROCuser_initialise, for each of the font/size combinations which are going to be used. Thus providing a set of font handles from the start.


If you have not come across font handles before it is probably best to consider them like file handles, because the Wimp uses them in a way more akin to file opening/closing. e.g. a font handle is opened by a call to FNwimp_getfont() as above - and the font ought to be closed after its last use in the application using PROCwimp_losefont. For example:


PROCwimp_losefont(fonthandle%)


As with Dynamic Areas, any font handles not already closed when the application quits are automatically closed by Dr Wimp. However, this is best regarded as a fall-back facility and there are many circumstances where it is best for you to carry out specific font handle closures during the normal program run.


The text-plotting wimp-functions

Once the font has been chosen the most useful text-plotting wimp-functions to use will be:


PROCwimp_plotwindowtext()

PROCwimp_plotwindowtexth()


These are a complementary pair with only the h in the name signifying that the latter requires the font to be defined as a font handle - and therefore the former requires the font to be defined as a name. Both of these have many parameters:


PROCwimp_plotwindowtext(window%,t$,f$,sizex,sizey,align%,x%,y%, fr%,fg%,fb%,br%,bg%,bb%,minx%,miny%,maxx%,maxy%, scalex,scaley,blending%)


PROCwimp_plotwindowtexth(window%,t$,font%,align%,x%,y%, fr%,fg%,fb%,br%,bg%,bb%,minx%,miny%,maxx%,maxy%, scalex,scaley,blending%)


The only differences between them, as you will expect, is that the first one has f$,sizex,sizey to define the font/size combination by name, whereas the second has just font% for the font handle.


The other common parameters are:


window% is the window in which to plot the text;

t$ is the text string to plot;

align% determines the justification. 0 means left justified, 1 means centred and 2 means right justified (all with respect to the plotting position);

x%,y% is the required plotting position in work area OS coordinates (remember, visible y values will be negative);

fr%,fg%,fb% define the foreground text colour (0-255 Red, Green, Blue);

br%,bg%,bb% define the background text colour (0-255 Red, Green, Blue);

minx%,miny%,maxx%,maxy% is the clipping rectangle passed through from the PROCuser_redraw parameters (as with the graphics display cases in Section 2.19);

scalex,scaley are the text scales required in the x/y directions with, as before, 1 meaning 100%;

blending% is a flag determining whether font blending is to be used - see a little later below.


A typical sequence placed inside PROCuser_redraw might be:


IF window%=main% THEN

PROCwimp_plotwindowtexth(main%,\"Test\",trinity12%,0,50,-50,0,0,0, 255,255,255,minx%,miny%,maxx%,maxy%,1,1,0)

ENDIF


which would plot the text Test in the main% window, left-aligned at 50,-50 with Blak text on a White background without enlargement/reduction and without font blending. The font name/size combination would be captured by the font handle trinity12% - provided by a call to FNwimp_getfont() previously.


With both this pair of text-plotting calls, if the specified font cannot be found then the default font of Trinity.Medium will be substituted automatically. This is an essential safeguard in case the user of your application does not have your specified font on his/her machine.


Note that if the font name version is used, a call to FNwimp_getfont() is made automatically within the call (and PROCwimp_losefont afterwards) so the f version of the pair is always a little quicker.

(Note: With the ability to scale text in outline fonts, it becomes much easier to offer a Print preview option in your applications.)


Additional wimp-functions

As with the graphics plotting cases in Section 2.19, there is a pair of wimp-functions mainly used for plotting text during printing. They are:


PROCwimp_plottext()

PROCwimp_plottexth()


i.e. without the window in the name. The details are similar to their window counterparts but without the window handle parameter, plus a need to use coordinates with respect to the bottom left of the screen/paper.


Checking the text size before plotting

There is also a pair of wimp-functions giving the to-be-plotted width and height of the text. They are:


FNwimp_gettextsize()

FNwimp_gettextsizeh()


These functions - which include the ability to get the size of scaled text - are very useful when it is required to place text precisely - although the align% parameter in the plotting wimp-functions is sufficient in many cases where only alignment in the x-direction is needed.


Note that FNwimp_gettextsize returns a size of 0 if it cannot find the specified font, but FNwimp_gettextsizeh will produce a fatal error if the specified font handle cannot be found.


Font blending

The parameter blending% is in all four of the text plotting wimp-functions introduced above and it has been set to 0 in the example call shown earlier.


If blending% is given any other value then - if the computer on which the Dr Wimp application is running uses Font Manager called 3.35 or higher - font blending will take place. This means that RISCOS will automatically attempt to blend the text with the background colour(s), producing a significantly better visual result.


However, there is a potential price to pay for this facility as it can slow down the text rendering process. In practice, therefore, blending is best not used in all text plotting operations - but rather kept to those cases where blending will be worthwhile i.e. typically when text plotting takes place over a non-white background e.g. text superimposed on a graphic.


It is for this reason that font blending has been introduced as an option.


Modifying the text with control codes

Not just simple strings of text can be plotted with the above wimp-functions. In addition, strings of control code sequences can be inserted into the string-to-be-plotted to turn underlining on and off, change the font, or change the font colour within the line of text. DrWimp provides functions to produce these control strings. For example:


t$=\"Cat \"+FNwimp_fontunderline(1)+\"dog\"+ FNwimp_fontunderline(0)+\" hen.\"


when plotted would result in the word dog being underlined. Note the positioning of the spaces between the three words so they don't get underlined as well.


An example of turning the text red:


t$=\"Cat \"+FNwimp_fontcolour(255,0,0,221,221,221)+\"dog.\"


would make the word dog. become red (on an anti-aliased background of light grey - standard Wimp colour 1). The text can be turned black again afterwards with 0,0,0,221,221,221.


And for changing the font (assuming homerton20% is a font handle already found):


t$=\"Cat \"+FNwimp_fontchangeh(homerton20%)+\"dog.\"


would make the word dog. appear in the font whose handle is homerton20%.


Note that there isn't an equivalent FNwimp_fontchange (no h) as the control sequence only works with font handles.


Any combination of these can be used to produce the effect you want. Note that if you plot a string and the end of it is in red for example, then the next line you plot will be in black again. There is no need to change the colour back to black as all effects such as colours, underlining and changing font apply for that plotting action only.


Matching the desktop font

Finally, there are two functions which also plot text but they use the current desktop font - which, depending on the RISC OS Version, may or may not be an outline font.


The functions are PROCwimp_deskplotwindowtext() and PROCwimp_deskplottext() and they both need RISCOS Version 3.50 or higher. Their parameters are straightforward if you have read the whole of this Section and you will note that there is not a font blending option.


These two functions are useful for matching the fonts displayed directly onto the window with that used, for example, by default in icons.





22. Printing


Dr Wimp provides comprehensive facilities for you to print via the standard RiscOS printer drivers. These make the programming for printing very much simpler - but you still need to have a fairly good grasp of how to use DrWimp before you boldly go.


As there a quite a bit to set up before the printing actually starts - and nothing can be tested until its mostly all done - it is not practicable to have a step-by-step tutorial for this section. However there is a pretty comprehensive example application in the Examples folder. Further, at the end of this section, there is a suggested sequence for practical programming. ( .... and Dr Wimps Surgery covers printing in more detail.)


General points

Dr Wimp provides two methods of printing and which you choose depends on the application - and there is no reason why you cant use both methods for different purposes within the same application.


If you want to print out what is being shown in a window which has all been written/drawn in PROCuser_redraw, then you would normally use what we will call the redraw method (which is, essentially, wysiwyg).


If on the other hand you want to print out something that is independent of the display, then you do all the work in a user-function PROCuser_print. We will call this latter the user method.


(Note that there is a PROCuser_print, a FNuser_printing and a PROCwimp_print. Dont mix them up!)


With either method, the main workload involved is coordinate conversion between screen/work area and paper. This is fairly straightforward with the wimp-functions provided, but it needs a methodical approach.


DrWimp also provides facilities to find out about the paper size, the  printer driver and a means for the application to tell the user what is going on and giving them the option to cancel the printing.


Also, with Dr Wimps introduction of scaling for outline fonts, it becomes much easier to offer a Print preview option in your applications.


Early checks and setting-up

The first thing your application needs to do is have some sort of 'Printing choices' window (or menu) where the user can specify the range of pages to print, how many to fit onto a page and the number of copies to print etc. As a bare minimum, a simple Print button will suffice.


Another early check needed is to ascertain that a printer driver is loaded, otherwise your application will produce errors and probably quit. For example, using:


loaded%=FNwimp_pdriverpresent


will result in loaded% being TRUE (-1) if a printer driver is loaded, or FALSE (0) if not. (Note the difference from the usual Dr Wimp practice of returning 1 or 0.)




This isnt the end of printer driver checking though. Remember that users can load, change and quit printer drivers at any time whilst your application is running. So it needs to be checked continually and Dr Wimp has a user-function to do just this. It is PROCuser_printerchange and it is automatically called any time the status of the printer driver changes. Thus you can fill this user-function with routines to react as you wish when it is called. For instance, you could check if a driver is still loaded, show its name, and enable/disable icons accordingly e.g. to prevent a Print button from being pressed if no driver is present and/or to show different print margins.



A common practice is to put the name of the current printer in the titlebar of the 'Printing choices' window. So, for example you could use:


loaded%=FNwimp_pdriverpresent

IF loaded%=TRUE THEN

 	printername$=FNwimp_getpdrivername

  	PROCwimp_putwindowtitle(print%,printername$)

ELSE

  	PROCwimp_putwindowtitle(print%,\"No printer loaded\")

ENDIF


with print% being the handle of your 'Printing choices' window. Its easy to see that in the above IF..ELSE..ENDIF structure you can enable and disable icons in the print window depending on whether the printer driver was loaded or not.


Paper size and printing borders

If you wish you can also get information about the paper size and the printer borders (i.e. the areas in which you can't print). With this you could, for example, draw grey and white rectangles in a 'Printing choices' window to depict the page and its borders. But be careful not to try and get any information about the page unless a printer driver is loaded!


As a very brief example, here is a sample piece of code that could go in PROCuser_redraw for a 'Printing choices' window (assuming its auto redraw flag is not set):



IF window%=print% THEN

	IF FNwimp_pdriverpresent=TRUE THEN

    	w%=FNwimp_getpapersize(0,0)

    	h%=FNwimp_getpapersize(1,0)

    	IF h%>=w% THEN scale=h%/120

    	IF w%>h% THEN scale=w%/120

    	w=w%/scale

    	h=h%/scale

    	PROCwimp_setcolour(160,160,160,0)

		PROCwimp_plotwindowrectangle(print%,0,-h,w,h,1)

    	lm=FNwimp_getpapersize(0,1)/scale

    	r=FNwimp_getpapersize(0,3)/scale

    	bm=FNwimp_getpapersize(1,1)/scale

    	t=FNwimp_getpapersize(1,3)/scale

    	PROCwimp_setcolour(255,255,255,0)

    	PROCwimp_plotwindowrectangle(print%,lm,-h+bm,r-lm,t-bm,1)

  	ENDIF

ENDIF


which will draw in the window a small depiction of the paper with its printing borders.



We havent finished with the 'Printing choices' window quite yet!


Currently DrWimp supports printing ranges of pages, multiple copies and fitting one, two or four A4 pages onto a single physical A4 page, so these are further options you can provide in your print window. For an example see the template file Print in the Tutorials folder.



Further, as was said before, at any time the user could change the current printer, and then PROCuser_printerchange will be called automatically. When it is, you would check to see if the printer driver is still loaded, and update all your page measurements, what icons to enable and disable in the print window etc. Basically do all your checks again just as if the print window was being opened for the first time.



Catering for Postscript printers

If you are printing with outline fonts, which is probably very likely, then there is one more preparatory consideration to take into account. The users of your application may be using Postscript printers and therefore it becomes a sensible precaution to declare all outline fonts that are going to be used - before you use them in printing.


This is done in the user-function PROCuser_declarefonts by using, as appropriate, PROCwimp_declarefont(), PROCwimp_declarefonth() and PROCwimp_declaredfilefonts() - the latter only if drawfiles are to be printed.


Initiating the printing

Once you have everything set up you are ready to print and, for either method of printing, one wimp-function initiates it.


PROCwimp_print(user%,window%,fpage%,lpage%,persheet%,interval%,copies%,orient%,xscale,yscale,order%,invert%)


Setting the parameter user% to 0 prints using the redraw method and setting it to 1 prints using the user method. Both of these will be discussed in more detail later, but an initial look at the parameters of PROCwimp_print will be helpful.


If using the redraw method then window% is the handle of the redraw window. In other words the window whose contents you want to print out (wysiwyg). The value in the parameter window% is ignored if printing with the user method (i.e. when user%=1)  - but a value must be present, of course, and 0 will be acceptable.


fpage% and lpage% are the page numbers of the first page to print and the last page, respectively. These are inclusive, and it doesnt really matter to DrWimp what they are as long as lpage% is equal to or larger than fpage%. The numbers you specify for the range of pages are arbitrary as far as DrWimp is concerned, as the whole range of page numbers will be returned to you one by one as you are requested to print each page.


persheet% can currently be either 1, 2, or 4. If you set it to 1 then each page to be printed will be printed normally on 1 sheet of the printer-configured paper (usually an A4 sheet). If you specify 2 then two pages will be scaled to about 70%, rotated through 90 degrees, and placed side by side on a single sheet of paper. If you specify 4 then each page will be scaled to 50% and four pages will be printed on a single sheet of paper. All this is done automatically and the printing process as far as you are concerned is exactly the same - only the actual output is affected.

interval% allows pages in a print sequence to be skipped - for example, to allow only odd/even pages to be printed. If interval% is set to 1 it means that every
page will be printed. Setting it to 2 means every other page, etc.

copies% is the number of copies to print. For example if you want to print from page 1 to 4, with two copies, then eight pages will be printing, two lots of four. The number of physical pages printed depends on persheet% though.


orient% specifies the orientation of the paper. If orient%=0 then the paper is portrait, but if you set orient% to 1 then the paper will be treated as landscape. The orientation parameter is also required when converting to and from paper coordinates, as the orientation of the paper affects where the work area and screen coordinates translate to on the paper.


xscale and yscale allow the printed output to be scaled. A value of 1 means no scaling i.e. 100% - with values less than 1 being a reduction in size and values greater than 1 being an enlargement. (There is an arbitrary lower limit of 0.05 for both values.)


order% applies only when persheet% is 2 or 4 and allows the position of each page on the sheet to be changed. When order% is 0 (the normal setting) the position of the pages is as follows:



When persheet%=2




and when persheet%=4





However, if order% is set to 1 then the positions become:


When persheet%=2




and when persheet%=4





Finally, if invert% is set to 1 the output page will be printed upside down on the paper sheet. Please note that if persheet% is 2 or 4 then the inverting will apply to each page individually rather than to the printed sheet as a whole.


(When persheet% is 2 the effect of setting invert% to 1 will be effectively the same as setting order% to 1 - apart from any printing margin differences.)

Progress of the printing job

During printing you may wish to keep the user informed of the progress of the printing and give them the option to cancel. This is achieved using FNuser_printing which is repeatedly called automatically by Dr Wimp. From its parameters you can read the current copy being printed, the current page number, the total number of pages that are being printed, and the current page being printed (from one to the total number). The return from this user-function is used to tell Dr Wimp whether to continue with the printing or not - see below.


From the total number of pages and the current page being printed, you could calculate the percentage of pages already printed and display a progress bar using PROCwimp_bar. You could also display the current copy and current page out of interest.


Finally, in the progress window you could add a cancel button, and when it is clicked on you set a global variable to indicate that the user wishes to cancel printing. Then, when FNuser_printing is next called, you look at the variable and return a 1 if the printing is to be cancelled. Otherwise you return a 0.


Here is an example of the sort of thing you might put into this user-function:


DEF FNuser_printing(copy%,page%,totpages%,pagepos%)

PROCwimp_puticontext(progress%,0,Printing page+STR$(page%)+ (copy +STR$(copy%)+))

PROCwimp_bar(progress%,2,(pagepos%/totpages%)*466,0)

=cancel%


In this example, progress% is the handle to the progress window, the progress bar is icon number 2, which is 466 OS units long, and icon 0 is just a text icon to display information.


cancel%, a global variable, would be set to 0 just before PROCwimp_print is called, and in PROCuser_mouseclick there would be a line like the following:


IF window%=prog% AND icon%=4 THEN cancel%=1


where icon 4 is the cancel button. FNuser_printing can then simply return cancel% to indicate if printing is to be cancelled or not.


Here are a couple of further examples to help you understand the difference between page% and pagepos%:


Say the user wanted to print pages 2 to 8, one copy. Then, as printing progresses, copy% will stay at 1, page% will start at 2 and increase to 8, totpages% will stay at 7 (printing pages 2 to 8 inclusive), and pagepos% will start at 1 and increase to 7 (totpages%).


If the user was printing pages 4 to 6, 2 copies, then copy% will start at 1 and increase to 2, page% will start at 4 and increase to 6, totpages% will stay at 3, and pagepos% will start at 1 and increase to 3 (totpages%).


Now, at last, we come to the actual printing: the actual construction of the pages. (Dont forget that you have already called PROCwimp_print somewhere.)



The redraw page construction

First, using the redraw method i.e. you called PROCwimp_print with its first parameter set to 0.


In this case, PROCuser_redraw is called automatically and Dr Wimp will set its penultimate parameter printing% to TRUE, and its last parameter page% will contain the page number to print.


Lets take a simple example of plotting on the screen one line of text in Trinity.Medium at 12pt and printing it. We will assume a handle for the font has already been obtained and is in trinity12%. The window we are displaying/plotting in has the handle main% (ie. the window handle passed to PROCwimp_print was main%), and the unscaled text is placed at the work area coordinates 50,-100 left-aligned.


Firstly, looking at just the screen display needs:


DEF PROCuser_redraw(window%,minx%,miny%,maxx%,maxy%, printing%,page%)

IF window%=main% THEN

  	x%=50:y%=-100

  	string$=\"DrWimp printing test.\"

	PROCwimp_plotwindowtexth(main%,string$,trinity12%,0,x%,y%, 0,0,0,255,255,255,minx%,miny%,maxx%,maxy%,1,1,0)

ENDIF

ENDPROC


Now take a look at how it would be modified to allow these same contents of the window main% to be printed on a portrait page.


DEF PROCuser_redraw(window%,minx%,miny%,maxx%,maxy%, printing%,page%)

IF window%=main% THEN

 	x%=50:y%=-100

  	IF printing%=TRUE THEN

    	x%=FNwimp_worktopaper(x%,0,0)

    	y%=FNwimp_worktopaper(y%,1,0)

  	ENDIF

  	string$=\"DrWimp printing test.\"

 	PROCwimp_plotwindowtexth(main%,string$,trinity12%,0,x%,y%, 0,0,0,255,255,255,minx%,miny%,maxx%,maxy%,1,1,0)

ENDIF

ENDPROC


That is, we simply keep the same routine but do a work-to-paper coordinate conversion of the plotting position whenever the penultimate parameter printing% is set to TRUE (by Dr Wimp automatically). (work coordinates being synonymous with window coordinates.)


One thing to note is that the top left corner of the window main% matches up with the top left corner of the paper.


And - after all that setting up - thats it!



Now for an example of printing the page number at the bottom of each page.


The following example assumes the work area of the window main% has been set to the size of an A4 piece of paper. That can be done with:


width%=FNwimp_lengthtoOS(210,100,0)

height%=FNwimp_lengthtoOS(297,100,0)

PROCwimp_resizewindow(main%,width%,height%)


The FNwimp_lengthtoOS calls convert 210mm and 297mm at 100% scale to OS units. The window is then resized. The example also assumes the programmer is keeping track of which page is being displayed with currentpage%.


So, for a portrait page:


DEF PROCuser_redraw(window%,minx%,miny%,maxx%,maxy%, printing%,page%)

IF window%=main% THEN

	x%=50

	y%=FNwimp_getwindowworksize(main%,1)+150

  	IF printing%=TRUE THEN

    	x%=FNwimp_worktopaper(x%,0,0)

    	y%=FNwimp_worktopaper(y%,1,0)

  	ENDIF

  	string$=\"Page \"+STR$(currentpage%)

 	PROCwimp_plotwindowtexth(main%,string$,trinity12%,0,x%,y%, 0,0,0,255,255,255,minx%,miny%,maxx%,maxy%,1,1,0)

ENDIF

ENDPROC


The text is plotted (left-aligned) 150 OS units up from the bottom of the actual paper to allow for printer borders, and to give a bit of space. As stated before, currentpage% contains the number of the page currently being displayed.


There is one problem with this however. It will be displayed fine, but when it comes to printing out, every time currentpage% will contain the page number of the current page being displayed, so it won't change on paper. What is required is a way of using the variable page% passed to PROCuser_redraw to make currentpage% change, but without corrupting it, so when the printing has finished the redraw won't try to show a different page on the screen. Here is one method:


DEF PROCuser_redraw(window%,minx%,miny%,maxx%,maxy%, printing%,page%)

IF window%=main% THEN

	IF printing%=TRUE THEN c%=currentpage%:currentpage%=page%

  	x%=50:y%=FNwimp_getwindowworksize(main%,1)+150

  	IF printing%=TRUE THEN

    	x%=FNwimp_worktopaper(x%,0,0)

		y%=FNwimp_worktopaper(y%,1,0)

  	ENDIF

  	string$=\"Page \"+STR$(currentpage%)

	PROCwimp_plotwindowtexth(main%,string$,trinity12%,0,x%,y%, 0,0,0,255,255,255,minx%,miny%,maxx%,maxy%,1,1,0)

  	IF printing%=TRUE THEN currentpage%=c%

ENDIF

ENDPROC


If PROCuser_redraw is being called for printing (printing% is TRUE) then currentpage% is stored in c% for safekeeping, and set to the number of the page being printed. Then, when the redraw has finished, currentpage% is restored to its initial value.


There is a comprehensive application called !PrintTest in the Examples folder to show many practical aspects of multi-page redraw printing.



Screen and Paper coordinates in redraw printing

In the examples above we have used the window versions of the text-plotting wimp-functions - because these are the most easy to use for displaying in windows. We have then converted from work coordinates to paper coordinates when printing - and we commented that this conversion effectively makes the top of the paper the same position as the top of the window.


You will also note that we have referred to - but not yet given an example of - screen coordinates i.e. with reference to the bottom left corner of the screen.


Very occasionally you will need to use screen coordinates for plotting in a window. For example, when using Basics PLOT codes. In these cases, you would decide the required work position i.e. window coordinates, and then use FNwimp_worktoscreen() to provide the screen coordinates for the PLOT code. The following example will help:



DEF PROCuser_redraw(window%,minx%,miny%,maxx%,maxy%, printing%,page%)

IF window%=main% THEN

	x%=50

	y%=-200

  	PROCwimp_setcolour(255,0,0,0):REM** Red **

  	x%=FNwimp_worktoscreen(main%,x%,0)

  	y%=FNwimp_worktoscreen(main%,y%,1)

  	PLOT 69 x%,y%:REM** Plot a point at x%/y% **

ENDIF

ENDPROC


If you wanted to print this using the redraw method then the code would need to become:


DEF PROCuser_redraw(window%,minx%,miny%,maxx%,maxy%, printing%,page%)

IF window%=main% THEN

	x%=50

	y%=-200

  	PROCwimp_setcolour(255,0,0,0):REM** Red **

  	x%=FNwimp_worktoscreen(main%,x%,0)

  	y%=FNwimp_worktoscreen(main%,y%,1)

	IF printing%=TRUE THEN

		x%=FNwimp_screentopaper(main%,x%,0,0)

		y%=FNwimp_screentopaper(main%,y%,1,0)

	ENDIF

  	PLOT 69 x%,y%:REM** Plot a point at x%/y% **

ENDIF

ENDPROC


That is, solely because - unusually - we need here to display something in a window using screen coordinates, we need to convert screen-to-work for the display and screen-to-paper for the printing. But it is important to note - as will be seen in the next sub-section - that screen-to-paper conversion is a need which is only ever encountered with redraw printing.



The user printing page construction

Now for the user method of printing  i.e. you called PROCwimp_print with its first parameter set to 1.


Instead of PROCuser_redraw being called by Dr Wimp, PROCuser_print is automatically called instead.


The page is described in much the same way. As there is no window involved you do not need to convert between work area, screen and paper coordinates. You simply work in paper coordinates, which are exactly the same in this case as OS screen units i.e.with the origin at the bottom left corner of the paper.


The window versions of the various available text and/or graphics plotting calls cannot be used, but all their counterparts can be, such as:


PROCwimp_rendersprite()

PROCwimp_render()

PROCwimp_renderjpeg()

PROCwimp_plottext()

PROCwimp_plottexth()

PROCwimp_deskplottext()


as well as all the Basic PLOT commands.


For example, to print a black square, slightly in from the bottom left corner of the paper:


DEF PROCuser_print(minx%,miny%,maxx%,maxy%,page%)

PROCwimp_setcolour(0,0,0,0)

RECTANGLE FILL 100,100,50,50

ENDPROC


You can be more precise with your position in real units, for example:


DEF PROCuser_print(minx%,miny%,maxx%,maxy%,page%)

inch%=FNwimp_lengthtoOS(1,100,1)

4cm%=FNwimp_lengthtoOS(40,100,0)

PROCwimp_setcolour(0,0,0,0)

RECTANGLE FILL inch%,inch%,4cm%,4cm%

ENDPROC


will print out a black square one inch from the bottom of the page and one inch from the left edge of the page, with sides 4cm long.


Similarly, if you wanted to print a drawfile (already loaded into memory in accordance with Section 2.12, of course) then you might use:


DEF PROCuser_print(minx%,miny%,maxx%,maxy%,page%)

inch%=FNwimp_lengthtoOS(1,100,1)

4cm%=FNwimp_lengthtoOS(40,100,0)

PROCwimp_render(dfile%,inch%,4cm%,minx%,miny%,maxx%,maxy%,1,1,1)

ENDPROC


which would place the bottom left corner of the drawfiles bounding box 1in in and 4cm up from the bottom left corner of the paper.



With PROCuser_print there is no printing% nor currentpage% variable to use because it is only called when printing is taking place, and the final parameter page% holds the current page number of the page being printed.


There is a standard clipping rectangle supplied in page coordinates which you can use for optimisation, however it is doubtful if the performance gains would be big enough to warrant the extra effort of using the clipping rectangle.



Suggested practical programming sequence for printing

There has been a lot to absorb in this section - mainly to do with the preliminary checks and setting up rather than the printing itself, which latter is fairly straightforward.


When you are programming for printing it is suggested that you deal with the printing process first and return to the checks etc. subsequently. For example a typical programming sequence might be:


1) Make sure you have a printer driver loaded and the printer ready to print.

2) Provide a simple means to trigger the printing process e.g. a Print button in a window or a menu item.

3) Decide whether you want to use the redraw or user method.

4) Program PROCuser_redraw or PROCuser_print accordingly.

5) Cause the Print button/menu item to call PROCwimp_print in the simplest possible way i.e. probably with its last nine parameters set to 1,1,1,1,0,1,1,0,0 respectively.

6) Load the application and try the printing action.

Then revisit steps 4), 5) and 6) to fine-tune and/or extend the process gradually until you are happy with what is happening.


Dont forget that there will probably be a pause between pressing the Print button and the printer starting to operate. Dr Wimp helps here by automatically displaying the hourglass during its own processing time.


If the hourglass comes and goes and there are no error messages and yet your printer does nothing (or produces a blank sheet) take this as good news! The chances are that it is only due to your coding attempting to print off the paper due to wrong coordinate conversions. Also, check that you have set the foreground plotting colour correctly: printing white on white is not difficult to arrange!


If you get an error message you will almost certainly have made a silly coding error somewhere e.g. a variable name without its final % etc. - which can be frustrating to search for (speaking from first-hand experience!). So try to keep to small changes when in Step 5 above.


Until you try it yourself you will have to accept on faith that, so far, the Dr Wimp printing routines have proved to be extremely robust and have not needed modification for some years. They work if you let them!


When you have got the basic process working OK, then go back and tackle the user-friendly bits such as checking for printer driver presence/change, providing a Printing choices window, showing progress etc. Again, take it a step at a time - integrating and checking things gradually.



Note that if you simply wish to send an existing file to the printer - with exactly the same effect as if you had dragged the file from a Filer directory window to the printer icon on the iconbar - then there is a separate wimp-function to do this. It is PROCwimp_sendfiletoprinter() - see Section 3.1 or 3.12.

23. Window & Icon creation

Why create when you can use templates?

Normally, it makes sense to use window templates to create windows and icons - and load them into a program as we have done so far. The !WinEd utility allows you to create your windows/icons in this way and is included in the Dr Wimp package.


However, there can sometimes be advantages in creating windows and icons directly from Basic within your !RunImage instead. For instance, to display search results dynamically when you may not know at the start of the program how many icons are needed. Or, from a security point of view, if you secure your Basic code then no-one can change the windows and icons.


To meet this need, DrWimp provides four functions for creating and deleting windows and icons directly, and these will shortly be described in detail.


Also, a wimp-function is provided to plot an icon directly to a redraw window without becoming part of the window definition. This is PROCwimp_ploticon() - see later.


But be warned! The depth of detail about the Wimp in this topic is necessarily more than is usual in Dr Wimp. But if it starts to bemuse you, Dont Panic! There is a further Dr Wimp utility called !CodeTemps which does it all for you and eliminates the detail - see later.


Flags

The direct creation of windows and icons requires - apart from several other parameters - the use of flags to describe certain aspects of the window or icon to be created. Before looking at the particular cases it is worth diverting for a moment to describe how Dr Wimp implements these flags.


Each flag is represented by one bit - either set or unset (1 or 0 respectively). Several flags can therefore be represented together by a multi-bit combination, such as a byte (8-bits, giving space for 8 flags). Of course, such a flag/bit pattern looks exactly the same as a single integer number and so the number can represent the flags collectively, and be passed as a parameter to the creating wimpfunction.


To demonstrate this, let us assume that we have 8 flags - each of 1-bit. Thus, if we used bits 0-7 of a conventional byte to hold the 8 values, we might produce a byte looking like this, for example:


00101101


Here, reading the bits (conventionally) from right to left, Bit 0 represents flag0 (which is set, i.e. =1); Bit 1 represents flag1 (which is unset, i.e. =0); etc.


This same sequence of bits is also a binary number. So the above example has bits 0, 2, 3 and 5 set (value=1), and the rest unset (value=0).


In BASIC, this binary number would be represented as:


%00101101


or, of course, could equally well be expressed as:


	45 in decimal,

or	&2D in hexadecimal.


So, in Basic, any one of these numbers can be passed as the flags parameter to the wimp-functions, as they all represent the same bit pattern. (You may find the binary format easiest to use as you can quickly work out which individual flags are set and unset - and we will use this form below.)

With this introductory material finished, we can start to look at the particular wimp-functions involved. For various reasons, it makes sense to look at icon creation before window creation - not in the least because, in practice, the need to create icons tends to occur more frequently than the need for window creation.


Creating icons

The wimp-function used to create icons is:


icon%=FNwimp_createicon(window%,wminx%,wminy%,wmaxx%,wmaxy%, flags%,esg%,button%,fcol%,bcol%,font%, text$,sprname$,sarea%,maxind%,valid$)


(With 16 parameters, it is one of the longest wimp-functions in the DrWimp library - and necessarily requires a bit more knowledge of wimp programming than is usual for DrWimp.)


window% is the handle of the window to create the icon in. wminx%, wminy%, wmaxx%, wmaxy% are the work area coordinates that define the position of the icon and its size. For example using 8,-48,48,-8 will create an icon that is 8 OS units in from the left edge of the window, 8 OS units down from the top edge, and 40x40 OS units in size. Remember that the y-values will normally both be negative, if the icon is to appear wholly within the window.


flags% is a 15-bit number that represents most of the Wimps icon flags for the icon. The flags used by Dr Wimp are:

	

	bit:	meaning if set:


	0	icon has text

	1	icon has sprite

	2	icon has border

	3	text/sprite is horizontally centred

	4	text/sprite is vertically centred

	5	icon is filled

	6	icon uses an outline font

	7	icon requires tasks help to be redrawn

	8	icon is indirected

	9	text/sprite is right justified

	10	<adjust> does not cancel other selected icons in same ESG

	11	display the sprite (if any) half-size

	12	icon is displayed as selected

	13	icon is disabled i.e. greyed out and cannot be selected

	14	icon has been deleted


(Note that flag bits 0-11 above line up with the icon flag bits used by the Wimp - and flag bits 12-14 above line up with icon flag bits 21-23 as used by the Wimp. The remainder of the Wimps icon flag bits are covered by other parameters in the wimp-function.)


For example, a flags% value of:


%000000101011101


would signify an icon that (reading from right to left): has text, has a border, the text is horizontally and vertically centred, uses an outline font and the text is indirected. All other options are unset.


esg% is the Exclusive Selection Group (ESG) number for the icon, which can be in the range 0-31 inclusive. All icons with the same ESG (if greater than 0) will be treated as a group and selecting one of them will automatically deselect others in the same group. These are normally only used for radio icons. All other icon types should have the ESG set to 0.


button% is the number of the button type of the icon. (Note that it is not in the above flag format.)


	button%	button type (what action notifies task.)

	value


	0	ignore

	1	always (task notified continuously whilst pointer is over icon)

	2	click (with auto-repeat)

	3	click (once only)

	4	release (initial click selects icon, release over icon notifies task)

	5	double-click

	6	click/drag (as 3 but, also, drag notifies task with button state*16)

	7	release/drag (as 4 but, also, drag notifies task with button state*16)

	8	double-click/drag (as 5 but, also, drag notifies task with button state*16)

	9	menu (pointer over icon selects, moving away deselects, click notifies task)

	10	click/double-click/drag (click notifies task with button state*256,

				drag with button state*16, double-click with button state*1)

	11	radio (click selects and notifies task with button state*1,

				drag with button state*16)

	12	reserved - not used

	13	reserved - not used

	14	writable/click/drag (click gives icon caret and its window gets input focus)

	15	writable (click gives icon caret and its window gets input focus)

		

	Button state means:

		1 for <adjust>

		2 for <menu>

		4 for <select>

		or in combination, e.g. <adjust> + <select> gives 5.


(Note that the button numbers above line up with the button numbers used by the Wimp.)


fcol% and bcol% are the foreground and background colours of the icon in desktop colours, so they are both in the range 0-15. Usually set to 7 and 1 respectively. Ignored if the icon uses an outline font - but values must still be present.


font% is the handle of an outline font, if one is being used i.e. if Bit 6 of flags% is set. If not then this should be set to 0. (If Bit 6 of flags% is set but the value of font% is invalid for any reason, then Bit 6 will automatically be unset - but the icon will be given the default colours of an outline font i.e. Black-on-White. A warning is given.)


If the icon has some text, then it is put in text$, and if the icon has a sprite, then its name is put in sprname$. The sprite area handle is put into sarea%, with 0 denoting Wimp sprite pool.


If the icon is indirected, then maxind% is the maximum number of text characters that can be put into the icon - plus 1 for a terminator. maxind% would, of course, need to be larger than the length of text$ if it is intended that longer text might be introduced when using the application.


valid$ is the icon validation string, which may contain information such as the pointer to use for the icon, the acceptable characters for writable icons, the border type, outline font colours etc. (If a validation string is to be used - i.e. if valid$ is not a null string - then the icon must be indirected i.e. Bit 8 of flags% must be set.)


The function returns a handle to the icon, which is the icon number.


An example, for creating a standard OK button, is:


okbutton%=FNwimp_createicon(main%,8,-76,136,-8, %000000100011101,0,1,7,1,0,OK,,0,3,R6,3)





Creating windows

As said earlier, the wimp-function to create windows is likely to be less used, but here it is:


window%=FNwimp_createwindow(vminx%,vminy%,vmaxx%,vmaxy%,wminx%, wminy%,wmaxx%,wmaxy%,flags%,colourflags%,button%, title$,titleflags%,titlefont%,maxind%,sarea%)



vminx%, vminy%, vmaxx%, vmaxy% are the screen coordinates that describe the area of screen that the visible part of the window will cover when opened. (If you open it centred or centred on the pointer or at specific coordinates, then the position vminx% and vminy% on the screen will be ignored. However, vmaxx%-vminx% and vmaxy%-vminy% set the width and height of the window.) The visible area has to be less than the work area. A window cannot be opened larger than its work area!


wminx%, wminy%, wmaxx%, wmaxy% are the work area coordinates that set the work area of the window. For example setting them to 0, -100, 200, 0 will create a window whose work area is 200x100 in size (remember that the work area origin is at the top left so work area y-values are always negative).


flags% is a 17-bit number that represents the window flags for the window.


	bit:	meaning if set:


	0	window has title bar

	1	window has close icon

	2	window has back icon

	3	window has horizontal scroll bar

	4	window has vertical scroll bar

	5	window has adjust size icon

	6	window has toggle size icon

	7	window can auto-redraw (i.e. no user graphics in window)

	8	window is a pane

	9	window is moveable

	10	window can be opened/dragged outside screen

	11	Scroll Event will be generated (with auto-repeat)

	12	Scroll Event will be generated (without auto-repeat)

	13	Hot key Events will be generated

	14	window forced to stay on screen

	15	dragging adjust size icon ignores right-hand extent of window

	16	dragging adjust size icon ignores lower extent of window


(Note that the flag bits above are in a different order to the bit positions used by the Wimp. This is because the latter are not in a convenient sequential order. However, all options provided by the Wimp are provided.)


For example, a flags% value of:


%00000001011111001


would signify a window which has (reading from right to left) a title bar, no close icon, no back icon, has horizontal and vertical scroll bars, has an adjust size icon, has a toggle size icon, does auto-redraws (i.e. PROCuser_redraw isn't called), isn't a pane, is moveable - and has none of the bits of the more esoteric flags 10-16 set. (Remember that the pane item does not affect Dr Wimps ability to use a window as a pane.)


colourflags% allows the colours of all items of a windows furniture to be specified. There are seven items, as follows - with their standard (Style Guide) colours shown in brackets:


Title foreground (7)

Title background (2)

Work area foreground (7)

Work area background (1)

Scroll bar outer (3)

Scroll bar inner (slider) (1)

Title background when highlighted for input focus (12)


Each item is specified by choosing its colour in the Wimp range of 0-15 and arranging these colour naumbers in the above order from left to right to give a single hex number. Thus the value of colourflags% to produce the standard Wimp colours is &727131C.



button% is the button type number of the window. Essentially, it follows the button types used for creating icons (see earlier in this section) - except that, with windows, there is no concept of a window being selected and simply refers to the <select> or <adjust> button actions. (<menu> clicks in a window are always reported to the task.)


title$ is the title of the window. If it is longer than 11 characters then the title will automatically become indirected (see titleflags% below).


titleflags% is an 8-bit number representing the Title bar flags for the window. They are basically similar to icon flags (see earlier in this section) - except that only a sub-set of them is involved, and hence not so many bits are needed

.

	bit:	meaning if set:


	0	title has text

	1	title has sprite

	2	text/sprite is horizontally centred

	3	text/sprite is vertically centred

	4	title uses an outline font

	5	text/sprite is right justified

	6	sprite (if used) is displayed half-size

	7	title is indirected (will also be set automatically if title$ exceeds 12 characters)


titlefont% is the handle of the outline font for the title text, if one is being used i.e. if Bit 4 of titleflags% is set. If not then this should be set to 0. (If Bit 4 of titleflags% is set but the value of titlefont% is invalid for any reason, then Bit 4 will automatically be unset. A warning is given.)


If the title is indirected, then maxind% is the maximum size that the title can be, plus 1 for a terminator.


If sarea% is 0 then the Wimp sprite pool is used for the window, otherwise sarea% is the handle of a sprite area (just the same as in FNwimp_loadwindow).


As with its icon-generating counterpart, the wimp-function returns a handle - in this case, the window handle.



An example of a simple window is:


main%=FNwimp_createwindow(406,572,790,816,0,-936,1236,0,

			%00000001011111001,&727131C,0,main,%10001101,0,7,0)


which would create a window with a visible area in the rectangle with corners at 406, 572 and 790,816 with respect to the bottom left corner of the screen. The windows work area is 1236 by 936 OS units. The window flags are the same as the example given earlier. The window furniture has standard colours and the button type is 0 (ignore). The window title is main and the title flags are represented by %10001101 (i.e. text, horizontally and vertically centred, indirected - no outline font, so titlefont% is set to 0). The max indirected text length is 7 (6 chars + 1 terminator) and the wimp area is left as the default 0 as no sprites are used in the creation.



!CodeTemps utility

Although the above processes are straightforward, they can be tedious and therefore prone to typing errors. This is where the !CodeTemps utility will make a huge difference. (It is in the Utils folder, supplied with DrWimp.)


With !CodeTemps you can combine the convenience of using window templates with the wish to create windows/icons from within the program.  !CodeTemps converts window templates containing icons into the exact Basic calls to reproduce them with FNwimp_createwindow and FNwimp_createicon - plus FNwimp_getfont if outline fonts are used anywhere.


!CodeTemps is very easy to use - essentially drag & drop - and instructions are contained in its !Help file.



Other points

Here are some further points:

Windows - however created - may be deleted (i.e. their definition removed from the application) using:


PROCwimp_deletewindow(main%)



which will delete the window whose handle is main%. If the window was open then it will be closed. One point to note though is that not all memory used by the window is immediately released. The memory used to store indirected data remains tied up for the run of the program, so a large amount of creating and deleting windows will eventually result in running out of memory.



Similarly, icons can be deleted using PROCwimp_deleteicon, for example:


PROCwimp_deleteicon(main%,2,0)


will delete icon 2 from the window main%. The icon will not necessarily disappear immediately though. It will be deleted at the next redraw. This can be forced by setting the third parameter of PROCwimp_deleteicon to 1, to cause a redraw. Eg:


PROCwimp_deleteicon(main%,2,1)


This redraw action is targetted on the area of the icon only, rather than the whole window.



It is worth noting that you can create an icon with zero width/height, which can sometimes be of use. But if, in this state, you want it disappear completely from the screen, make sure it is un-filled and has no border.

If you create windows/icons be careful to ensure that the value of wimpmem% in the call to FNwimp_initialise() is large enough to cope with the additions. See Section 2.34.


Plotting icons directly

A wimp-function exists to allow icons to be defined and plotted directly to an open redraw window. The wimp-function is:


PROCwimp_ploticon(wminx%,wminy%,wmaxx%,wmaxy%, flags%,esg%,button%,fcol%,bcol%,font%, text$,sprname$,sarea%,maxind%,valid$)


Not surprisingly perhaps, it has exactly the same parameters as FNwimp_createicon(), apart from not needing the latters first parameter window%. Accordingly, all the meanings of the parameters are as described earlier for FNwimp_createicon().


Therefore, the utility !CodeTemps can again be used to obtain the particular values for an icon defined in a window template. In this case, however, you will need to copy the parameters from the !CodeTemps output listing without using the window% value.


PROCwimp_ploticon() will plot an icon (defined by its parameters) directly into a window which is currently being redrawn. So it is intended to be called only from within PROCuser_redraw(), with coding such as:

DEF PROCuser_redraw(window%,minx%,miny%,maxx%,maxy%, printing%,page%)

CASE window% OF

    WHEN main%

    PROCwimp_ploticon(........................)

ENDCASE

ENDPROC


Any icons directly plotted in this way do not become part of the windows definition and will not have any identifying icon handle (which also explains why the call is a PROC rather than a FN). Therefore they cannot be manipulated further using the other wimp-functions such as PROCwimp_puticontext() etc.


But there is nothing to stop you making directly-plotted icons appear/disappear or to replace them with different icons etc. Many possibilities are available using ordinary Basic coding to, say, switch the plotting on/off or to plot different icons for different purposes in the same place. The Example application !IconPlot demonstrates simple switching on/off.


It is worth noting that - just like plotted redraw user-graphics/text - icons plotted this way are displayed underneath icons which are within the windows definition.

24. Colour picker

(Please note that RiscOS Version 3.50 or higher is needed to use the Colour Picker.)


If you have a RiscOS Version from 3.50 onwards you will be familiar with the Colour Picker window, from applications such as !Draw - and now Dr Wimp will enable you to introduce the same features into your own applications.


Essentially, the Colour Picker is a window which, when displayed, enables the application user to choose, visually, what colour is required, from the complete range of colours available. A colour can be specified by clicking on the colour actually displayed in the window, or by specifying the proportions of the constituent colour components (in RGB, CMYK or HSV terms). These are all automatically linked in the Colour Picker window, so a simple but very comprehensive facility is offered.


Dr Wimp provides two ways of harnessing the Colour Picker: one by opening the colour picker window exactly like any other window and the other by opening it as a sub-menu from a menu item. 


The colour models

When the colour picker window is first opened, it will have a default colour already displayed and Dr Wimp allows you to specify this. Further, you can choose between specifying this initial colour in familiar rgb values in the range 0-255 or in the values of one of the three colour models i.e. in the RGB or CMYK or HSV colour model.


Whichever method you choose here will not limit you subsequent ability to use the whole range of the colour picker window settings once the window is open - which includes being able to change the model etc.


Briefly:


The RGB colour model specifies the amounts of the Red, Green and Blue components of a colour in percentage terms i.e. each in the range 0-100. (Note: not 0-255 here.)

The CMYK model specifies the amounts of the Cyan, Magenta, Yellow and Key (black) components of a colour in percentage terms i.e. each in the range 0-100.

The HSV model specifies the amounts of the Hue colour angle in the range 0-359 degrees, and the Saturation and Value components of a colour in percentage terms (0-100).


These different models are merely different ways of specifying a colour and each tends to be used in practice by different groups of people working with colour e.g. artists, printers, scientists.



Making the colour choice

Once the user has decided which colour is wanted, he/she presses an OK button - so you, the programmer, need a means of extracting the choice from the colour picker window and into your program for further use e.g. to draw something in the chosen colour.


Dr Wimp provides two user-functions for this purpose. One provides the chosen colour output in 0-255 rgb values and the other in the values of the model actually selected in the colour picker window at the time the selection was made.


Dialogue type

If you open the colour picker window as a sub-menu it will, as you would expect, close automatically like any other sub-menu if you move the pointer back over the menu item from which it came - and if you click elsewhere on the screen. This is known as the sub-menu dialogue type.


If you open the colour picker window as an ordinary window, Dr Wimp also allows you to have the choice of closing it in the normal way (e.g. by clicking on its Close icon) or closing like a menu i.e. closing when a click is made elsewhere.


In all cases, the window will close automatically when you use <select> over the colour picker windows OK or None buttons (but using <adjust> will keep it open as usual).



Now we can look at the wimp- and user-functions and we will start with the latter.


The user-functions (for reading the chosen colour)

They are:

PROCuser_colourpickerrgb(red%,green%,blue%,none%)


and

PROCuser_colourpickermodel(model%,value1,value2,value3, value4,none%)


Both of these are called automatically every time you make a colour selection in the colour picker window i.e. when the user presses OK or None.


If OK was pressed , then both user-functions will pass the values of the chosen colour in their parameters and none% will be set to 0. If  None was pressed, then the currently displayed colour values in the colour picker window will still be passed, but none% will be set to 1. (So it is up to you to decide how to react to none% having a value of 1. For example, you might want to ignore the colour data in this case, or  you might want to store the values in order to open the window with these values next time.)


Irrespective of the method you chose to open the colour picker window and irrespective of the actual model currently selected in the window at the time you made your colour choice, PROCuser_colourpickerrgb will always give the values red%, green% and blue% in the range 0-255, which is often used in other wimp-functions and can therefore be conveniently passed on directly.


The parameters passed in PROCuser_colourpickermodel need a little extra explanation. They will again reflect the chosen colour values in the model actually displayed in the colour picker window at the time the OK (or None) button is pressed - which, of course,  may not be the same model in which you specified the window to open initially. However:


model% will be either 0, 1 or 2 for RGB, CMYK or HSV respectively.

value1, value2, value3 and value4 will be in percentage values in the range 0-100 - except that value1 will be in the range 0-359 if model% is 2 (i.e. the colour angle in degrees in the HSV model). Also, value4 only has relevance for the CMYK model i.e. when model% is 1 - and it will be set to -1 for other models.


The wimp-functions (for opening the colour-picker window)

Now let us look at opening the colour picker window - firstly as a normal window.


The two available wimp-functions are:


PROCwimp_opencolourpickermodel(model%,dialoguetype%,value1, value2,value3,value4,none%,x%,y%)


PROCwimp_opencolourpickerrgb(dialoguetype%,red%,green%,blue%, none%,x%,y%)


From the earlier description of the user-functions, the meaning of most of these parameters will now be clear. The values set the colour that will be initially displayed when the window first opens and also the model that will be initially displayed. (If you use PROCwimp_opencolourpickerrgb the RGB model will be displayed initially with the 0-255 values converted to 0-100 values). Dont forget that value4 must always have a value assigned to it although that value will be ignored if model% is 0 or 2.


none% chooses whether the None button is available or not and whether it is selected when the colourpicker window opens. A value of 0 means None button will not be available for use; 1 means it will be available and initially de-selected; and 2 means it will available and initially selected.


x%/y% are simply the required screen OS coordinates for the top left corner of the opening colour picker window.


The parameter dialoguetype% determines the type of window closure that will apply and can be set to either 0 or 1. If it is 0 then the colour picker window will stay open until you close it by some means or you press OK or None. (This is called the normal dialogue.) However, if it is 1 then the window will also close if you click anywhere outside it. (This is known as the menu dialogue, for fairly obvious reasons.)


With either of these two wimp-functions, you simply call them in similar circumstances to using PROCwimp_openwindow. For example, from PROCuser_mouseclick or PROCuser_menuselection. They are perfectly straightforward to use. (You do not normally need to know the colour picker window handle but it is held, after the call, in the global variable wpickerwindow%.)

Opening the colour picker as a sub-menu is also easy, but involves two steps.


A special global variable called wSUBMENUCOLOURPICKER% (a mouthful, but you wont easily forget it!) has been created in the DrWimp library and is set to 1 as default. If you want the colour picker window to appear as a sub-menu to an (already defined) parent menu item, then the first step is to attach wSUBMENUCOLOURPICKER% to that item as its sub-menu/window handle. e.g.:


PROCwimp_attachsubmenu(parentmenu%,3,wSUBMENUCOLOURPICKER%)


This action ensures that the required item (here, 3) on the parent menu (whose handle here is parentmenu%) correctly displays a sub-menu arrowhead - and that is all it does.


The second, and final, step is to decide which of two wimp-functions you wish to use to actually cause the window to open (when you move across the just-created arrowhead) and put it into DEFPROCuser_overmenuarrow. The two wimp-functions are:


PROCwimp_opensubmenucolourpickermodel(model%,value1,value2,

                                    value3,value4,none%,x%,y%)


PROCwimp_opensubmenucolourpickerrgb(red%,green%,blue%,none%,

                                                        x%,y%)


As you can see, these match the two previously-described wimp-functions except that there is no dialoguetype% parameter (because, in this case, the colour picker window will always act exactly like a sub-menu i.e. it will use the sub-menu dialogue).


A typical coding might therefore be:


DEF PROCuser_overmenuarrow(rootmenu%,rootmenuitem%,RETURN nextsubmenu%,nextsubmenunumber%,parentmenuitem%,x%,y%)

CASE nextsubmenu% OF

	WHEN wSUBMENUCOLOURPICKER%

	PROCwimp_opensubmenucolourpickermodel(1,0,40,55,20,1,x%,y%)

ENDCASE

ENDPROC


This would cause the colour picker window to open when you move across its parent menus arrowhead - and, here, it would open with the CMYK model showing percentage values of 0, 40, 55 and 20, which is an orangey sort of red. It will open in the same place as a conventional sub-menu, because x% and y% have been passed straight through.


As before, the two colour picker user-functions will be called when you actually select OK or None. If you did not change the above initial colour and then selected OK, PROCuser_colourpickerrgb would return 204, 102 and 64 for its red, gren and blue values i.e. in the range 0-255.



In the Examples folder there is an application called !ColPick which gives a practical demonstration of how to use the above-described facilities.



25. Dragging icons

We have already experienced two special types of icon dragging with Dr Wimp i.e. saving data by dragging the drag% icon of a Save box (Section 2.7) and dragging Sliders (Section 2.16).


Dr Wimp has facilities to manage simple dragging of all other icons - provided that they have been defined as draggable in their definition.


The user can also define his/her own drag-box, independent of icons.


Dragging icons

Once a draggable icon is displayed in a window of your application, it needs only one simple item of preparation before it can be dragged around the window by holding down either the <select> or <adjust> mouse button whilst moving the mouse.


In the skeleton !RunImage is the user-function:


DEF FNuser_dragicon(window%,icon%,button%)

=0


This user-function is automatically called whenever the user starts a drag action on an icon which has been defined as draggable i.e. when either the <select> or <adjust> button is pressed and held down over such an icon. As can be seen, the default return is 0 and all you have to do is set the return value to 1 when you want dragging to actually occur.


As usual, the parameters tell you which window/icon pair is involved and which button has been used. (Note that it will be the usual 4 or 1 for <select> or <adjust> respectively.) So, a typical simple coding might be:


DEF FNuser_dragicon(window%,icon%,button%)

LOCAL return%

return%=0

CASE window% OF

WHEN main%

	CASE icon% OF

	    WHEN 6

	    return%=1

   ENDCASE

ENDCASE

=return%


This would mean that dragging would only actually begin to occur when the user seeks to drag Icon 6 in window main%. Any attempt to drag any other draggable icon will be ignored. Clearly you can easily make the coding respond to other possibilities.


When dragging takes place it will actually drag a rectangle (the drag box) the same size as the icon and with a rotating dash border. When you end the drag the rectangle will simply disappear and, at the moment, nothing else will happen.



To allow the programmer to make something happen Dr Wimp provides three user-functions:


PROCuser_seticondragbounds()

PROCuser_draggingicon()

PROCuser_endicondrag()


and they come into play before, during and at the end of the drag, respectively, as follows:



DEF PROCuser_seticondragbounds(startwindow%,dragicon%, dragbutton%,startmousex%,startmousey%,RETURN boundsminx%, RETURN boundsminy%,RETURN boundsmaxx%,RETURN boundsmaxy%)

ENDPROC


This user-function is automatically called from within the DrWimp library at the start of an icon drag and its purpose is to allow the programmer to set the limits of the area in which the dragging can take place.


The passed parameters are: startwindow% - the handle of the window% which owns the dragged icon; dragicon% - the handle of the dragged icon; dragbutton% - the button state whilst dragging i.e. either 4 for <select-drag>  or 1 for <adjustdrag>; startmousex% and startmousey% - the mouse pointer coordinates at the start of the drag, in screen OS values i.e. referred to bottom left corner of screen; and finally boundsminx%, boundsminy%, boundsmaxx% & boundsmaxy% are the required dragging limits, in screen OS values.



You will see that the last four parameters are RETURN parameters (remember to keep a space between each RETURN and its variable) so this gives you the opportunity to set your required values within this user-function - using the other parameters as and if you wish to filter the conditions more precisely.



If you choose to leave this user-function empty the dragging will be confined to the area of the visible window in which the dragged icon starts, but by using this user-function the limits can be changed so that the drag box can be dragged anywhere on the screen.



DEF PROCuser_draggingicon(startwindow%,dragicon%,dragbutton%, startmousex%,startmousey%,mousex%,mousey%,

        overwindow%,overicon%,dragboxminx%,dragboxminy%,

        dragboxmaxx%,dragboxmaxy%)

ENDPROC


This user-function is called repeatedly by the Wimp whilst the icon is being dragged and provides a means for the programmer to take action during the drag, if required.


The parameters startwindow%, dragicon%, dragbutton%, startmousex% and startmousey% are the same as in the previous user-function above, but mousex% and mousey% are now the instantaneous mouse pointer screen OS coordinates during the drag. The parameters overwindow% and overicon% are the handles of the window and icon which the pointer is currently over during the drag. (Values of -1 are given when the pointer is not over a window/icon.)


The parameters dragboxminx%, dragboxminy%, dragboxmaxx% and dragboxmaxy% are the instantaneous screen OS coordinates of the drag box.


Typical uses for this user-function might be to display the corrdinates of the current mouse pointer position, or to trigger certain action when the drag passes over a specific window/icon combination.



DEF PROCuser_endicondrag(startwindow%,dragicon%,dragbutton%, startmousex%,startmousey%,dragboxminx%,dragboxminy%, dragboxmaxx%,dragboxmaxy%,endwindow%,endicon%,endmousex%, endmousey%)

ENDPROC


As its name suggests, this user-function is called automatically when the drag ends - passing to the programmer the end-of-drag values of the various parameters which are, by now, self-explanatory. The wide variety of parameters  gives the programmer many opportunities to decide what action to take when the drag ends.


One such action may be to copy (or move) the icon and Dr Wimp provides Elixir_02 (see Section 2.36) specifically for this. It allows an exact copy of the dragged icon to be created at the place where the drag ends - with the option to delete the original icon i.e. the dragged icon.



User-defined drag-boxes

The user can also define and start to drag any drag-box - independent of icons - by using the simple facility provided in Elixir_04 - see Section 2.36.


However it is worth noting here that, for convenience, Elixir_04 also uses:


PROCuser_seticondragbounds()

PROCuser_draggingicon()

PROCuser_endicondrag()


as described above, but in this case the value of dragicon% will always be -1.


26. Internal multitasking **

We have already said that applications using the Wimp are multitasking - meaning that more than one such application can be active at the same time and the user can take action with any of them unhindered.


However, this section is about multitasking within an application - so that one task can be going on whilst the user takes another action within the same application. This can be useful when there is a process which may take a long time to carry out e.g. complex number crunching, file finding, etc. This Section shows how operations like these can be made to multitask.


Some methods of multi-tasking using Dr Wimp involve the special global variable NULL% which was introduced in Section 1.4 of this Manual. In these cases, it is necessary to set NULL% to TRUE at some point in your programme and this, in turn, causes PROCuser_null to be called - in which your multi-tasking code can be put.


In Dr Wimp, when your application is initialised, NULL% is set to FALSE - and when it enters the main Wimp-poll loop, this ensures that the Wimp is told not to let the application know every time a no-action needed Reason Code (null event) occurs. This is because such events occur more or less continuously and an application simply does not normally need to know about them.

However, if at any time, NULL% is set to TRUE the Wimp poll starts receiving these null events and, in turn, calls PROCuser_null every time that it receives one - i.e. more or less continuously.

Thus, inside PROCuser_null, you could call a routine to do a small bit of work each time - small because you will block the computer unless responses to null events are very short. Hence to utilise this option for a long task is complicated. (There is a simple application, called !FastSlow, using this method in the Examples folder.)


An easier option in Dr Wimp is to use PROCwimp_singlepoll. When called, it goes through the polling loop just once and if, at that time, NULL% is set to TRUE, PROCuser_null will be called once.


Assuming your application is already using the normal Dr Wimp PROCwimp_poll, it will already be in this loop, so all you have to do is call PROCwimp_singlepoll inside it. This very simple technique makes powerful multitasking operations very easy to achieve.


PROCwimp_singlepoll can also be useful without needing to use NULL% or PROCuser_null - as is demonstrated below.


Retrieve the complete !MyApp application as left in Section 2.15 (a copy is in the Tutor1 folder) and in the !RunImage listing change PROCuser_menuselection so it has lines like:


CASE menu% OF

WHEN iconbarmenu% :

	CASE item% OF

  	WHEN 1 : PROCchangeauthor

  	ENDCASE

ENDCASE


Now add the following new custom function definition at the end of !RunImage:


DEF PROCchangeauthor

FOR L%=1 TO 200

  	PROCwimp_singlepoll

  	a$=

  	FOR M%=1 TO 6

    	a$+=CHR$(RND(26)+64)

  	NEXT M%

  	PROCwimp_puticontext(info%,2,a$)

   PROCwimp_pause(0.1):REM** To slow action down ** 

NEXT L%

ENDPROC


Save the !RunIamge, run !MyApp and click on the first item on the iconbar menu. If you now look at the info window, the author field should be constantly changing with random letters. You can still use the desktop, and even quit the application, during this routines run. (Note that this simple demonstration will only act for 200 text changes, over about 20 seconds. The insertion of PROCwimp_pause(0.1) slows down the action so that you can see it clearly.) Note that we have not changed NULL% during this process, nor used PROCuser_null.


[This !RunImage listing is not saved and can be discarded. When the tutorial is picked up again - in Section 2.27 - a fresh !MyApp will be started.]


There is another function that can offer further multi-tasking options; PROCwimp_pollidle. This works similarly to PROCwimp_poll but it repeatedly polls the Wimp at an interval decided by the programmer. For example, the call:


PROCwimp_pollidle(30,1)


causes PROCuser_null to be called once every 30 seconds.


In between this periodic action PROCwimp_pollidle will also react exactly like the normal PROCwimp_poll for other poll events e.g. mouse clicks etc. So it can be used very effectively for actions which need to be carried out with a regular periodicity whilst retaining the ability to intervene if necessary e.g a clock with a facility to change time, set alarm etc. It is usual to set NULL% to TRUE when using PROCwimp_pollidle so that PROCuser_null can be used for handling the regular task. (See !Clocker in the Examples folder for an example of using PROCwimp_pollidle.) Note that if the above listing had called PROCwimp_pollidle(30,0) then the periodicity would have been every 0.3 second, roughly. The second parameter determines whether the first parameter value is taken as seconds or centi-seconds.


In addition, a further option is provided with PROCwimp_singlepollidle, which is the same as PROCwimp_singlepoll but polls the Wimp once after a user-specified delay.



For general multitasking guidance: use PROCwimp_poll or PROCwimp_pollidle to provide the main loop and then use PROCwimp_singlepoll and/or PROCwimp_singlepollidle within that. This also makes it easier to vary the idle time, if required.


Be very wary of using any of the above calls within a file drag saving/loading routine.


(Note: if you have put a banner up and then used PROCwimp_pollidle with a time longer that the banner period, then the banner will stay up until the next PROCuser_null occurs.)

27. Managing the quit/shutdown **

In the tutorial material early in Section 2, when we took action to quit the application it was simple and the application ended without further ado. However, in many cases we need to manage the quit process in a bit more detail.


For instance, there are frequently the following aspects to consider:


a) we may wish to do some good housekeeping tidying up before the actual application closure (e.g. close files and/or fonts etc,);

b) there may be some unsaved data to take care of and we would therefore wish to abort (or pause temporarily) the quit action to allow this do be done.


In addition, the quit action may have been started by the user selecting Shutdown from the Task Manager iconbar menu, intending to quit all running applications and ending the computer session.


All these cases need to be accomodated in a wimp program and Dr Wimp caters for them in a straightforward way, using a combination of FNuser_quit(type%) and PROCwimp_quit(type%). These functions work closely together and use the same parameter: if type%=0 it means that an application quit is involved, and if type%=1 it means that a Wimp shutdown is involved. (These terms are explained shortly.) The return from FNuser_quit() is critical: a return of 1 means that the application has no objection to quitting and a return of 0 means that the application does not wish to quit.


In the following descriptions we will be referring to a window called warn.  So it would help at this point to start with a fresh copy of the skeleton !MyApp and copy the file Template7 from the Tutorials folder (Tutor3 sub-directory) into !MyApp and rename to Templates. Then load the window into your tutorial !RunImage, with the handle warn% - in the same way as we have done before - and have a look at the window in your template editor. It looks like this:



(The Discard button is icon number 0 and the Save button is icon number 2.)


The application quit process

Firstly, lets look at the process of quitting just your application i.e. no other running application is intended to be affected. For simplicity in this text we will call this an application quit. An application quit can be initiated in two ways:


i) by calling PROCwimp_quit(type%) - with type% set to 0 - at some point within the application, typically by selecting Quit from the applications iconbar menu and making the call within PROCuser_menuselection() (as was done in Section 2.2); or

ii) via the Task Display menu.

Either way, the result is that Dr Wimp causes FNuser_quit(type%) to be called, with type% set to 0 - the 0 meaning that an application quit has been started, as opposed to a shutdown.


If you set the return from this call to be 1 (dont confuse the return value with the type% value!) then, without more ado, the application will quit. However, if the return is set to 0 the quit will not take place. It is as simple as that.


So, assuming we want to to stop an application quit if there is some unsaved data, we would need a structure something like this (Dont alter your tutorial !RunImage yet):


DEF FNuser_quit(type%)

return%=1

IF type%=0 AND unsaved%=TRUE THEN

	PROCwimp_menupopup(warn%,2,0,0)

	return%=0

ENDIF

=return%


Here we are assuming that the variable unsaved% is a flag which is set to TRUE/FALSE within the program according to whether or not unsaved data exists. If type% is 0 then the above routine will stop the quit - by returning 0 - and open the (previously loaded) warning window called warn%.


Action on the Discard/Save buttons in the warn% window will take place - as usual - in PROCuser_mouseclick, and might look like this:


DEF PROCuser_mouseclick(window%,icon%,button%,workx%,worky%)

CASE window% OF

	WHEN warn%

    	CASE icon% OF

      		WHEN 0:REM** Icon number of Discard icon. **

        	unsaved%=FALSE

        	PROCwimp_closewindow(warn%)

        	PROCwimp_quit(0)

        

      		WHEN 2:REM** Icon number of Save data icon. **

        	PROCwimp_closewindow(warn%)

    	ENDCASE

ENDCASE

ENDPROC

As you can see, clicking the Discard button would set the unsaved% flag to FALSE and call PROCwimp_quit(0) i.e. call for an application quit again. This, in turn, would call the previous FNuser_quit() routine again - but this time the result will be a return value of 0, because unsaved% is now FALSE.


If we had clicked on the Save button, no action would occur - other than closing the window - and the application continues to run unchanged, allowing us to save the data (and subsequently initiating an application quit again, if we wish).


If we wanted to add some good housekeeping we would need to extend the above to something like:


DEF FNuser_quit(type%)

return%=1

IF type%=0 AND unsaved%=TRUE THEN

	PROCwimp_menupopup(warn%,2,0,0)

	return%=0

ELSE

	IF type%=0 THEN

		PROCapp_housekeeping

	ENDIF

ENDIF

=return%


This would ensure that the housekeeping only takes place if it is an application quit and there is no unsaved data. The reason for this tight constraint will become clearer below.

(Note: The above are illustrative only and not intended to be used in the Tutorial !RunImage.)



Wimp shutdown

As was said earlier, quitting action can also be started by the user selecting Shutdown from the Task Manager iconbar menu: thereby intending to quit all running applications and end the computer session. We will call this shutdown to distinguish it from an application quit.


In this case, the Wimp needs to cater for all running applications and give them each a chance to halt the process. The Wimp has a standard routine for this and Dr Wimp manages this behind the scenes - but it will help to outline the procedure.


When a shutdown is initiated, the Wimp sends a pre-quit message to each running application, asking them in turn if they have any objection to quitting. If an application is ready to quit (i.e. has no objection) then it simply ignores the message. However, if an application does not wish to quit then it returns a reply to the Wimp and the whole shutdown is aborted.


(Note that as the Wimp effectively asks each running application in turn, the shutdown is aborted by the first objection and there could well be other applications who would have objected subsequently if the pre-quit message had reached them.)



The most common reason for not wanting to quit is that an application has some unsaved data, and the usual process then is for the application to send the Wimp its objection and then give the user a choice of saving the data or discarding it. If the user decides to discard it the approved Wimp procedure is for the application to then re-initiate the shutdown process itself - giving the remaining applications the opportunity to object. Please note that this is the only circumstance where a Dr Wimp application should (re-)initiate the wimp shutdown process.


Further, what happens if our application gets the pre-quit message and ignores it (i.e. has no objection to quitting) but a subsequent application makes an objection and the shutdown is aborted? What should our application do in that case?


By and large, most users would probably want our application to continue as if nothing had happened (i.e. good housekeeping actions and/or quitting would not be expected) - but note that there is no recommended practice here and certainly some well-known applications still quit in these circumstances.


How are these shutdown issues handled in the coding? The main point to note is that when the pre-quit message is received by your application Dr Wimp arranges - as it did for the application quit case above - for FNuser_quit(type%) to be called. But this time with type% set to 1, so you know that it is the start of a shutdown action.


If you have no objection to quitting then, as before, you set the return from this call to be 1 (again, dont confuse the return value with the type% value!). Alternatively, if you wish to stop the shutdown action you set the return to 0.


So far, therefore, the actions are the same as for an application quit and the fundamental coding might look like this (again, for illustrative purposes only):


DEF FNuser_quit(type%)

return%=1

IF type%=1 AND unsaved%=TRUE THEN

	PROCwimp_menupopup(warn%,2,0,0)

	return%=0

ENDIF

=return%


which is exactly as before except that the IF line starts with IF type%=1 AND ....


The only difference happens behind the scenes. If you return 0 then Dr Wimp sends a special message to the Wimp notifying it of your objection.



However, we still need to take account of the point that - for the shutdown case only - if we offer the user the chance to save the unsaved data (as we do by opening the warn% window above) then we need to re-start the shutdown process if the user decides to discard the unsaved data. We effect this by modifying the response to the warn% window button click coding, as follows:


DEF PROCuser_mouseclick(window%,icon%,button%,workx%,worky%)

CASE window% OF

	WHEN warn%

    	CASE icon% OF

      		WHEN 0:REM** Icon number of Discard icon. **

        	unsaved%=FALSE

        	PROCwimp_closewindow(warn%)

        	PROCwimp_quit(1)

        

      		WHEN 2:REM** Icon number of Save data icon. **

        	PROCwimp_closewindow(warn%)

    	ENDCASE

ENDCASE

ENDPROC


The only change from the application quit case being the calling of PROCwimp_quit(1) rather than PROCwimp_quit(0). Thus, remembering that we have already halted a shutdown, this coding actually calls for the shutdown to be re-started if Discard is chosen - and Dr Wimp duly takes the necessary action behind the scenes.


Practical coding

The above two subsections have sought to illustrate the application quit and shutdown processes separately, in order to aid understanding. However, in practice their coding needs to be combined because the application may be subject to either case at any time. Fortunately, as we have seen, the separate codings are almost the same so it is a very small matter to arrive at a typical practical coding.


So this time, make the following changes to !RunImage in your fresh copy of !MyApp:


a) Incorporate the Templates from Template7 as stated earlier in this Section.

b) also as stated earlier, add the line:

warn%=FNwimp_loadwindow(<MyApp$Dir>.Templates,warn,0)

to PROCuser_initialise.

c) now add the line:

unsaved%=FALSE

to PROCuser_initialise.

d) Make DEF FNuser_quit() look like this:


DEF FNuser_quit(type%)

return%=1

IF unsaved%=TRUE THEN

  	PROCwimp_menupopup(warn%,2,0,0)

  	quittype%=type%

  	return%=0

ENDIF

=return%


e) Make DEF PROCuser_mouseclick() look like this:


DEF PROCuser_mouseclick(window%,icon%,button%,workx%,worky%)

IF window%=iconbar% THEN PROCwimp_openwindow(main%,1,-1)

IF window%=main% AND icon%=2 AND unsaved%=FALSE THEN

 	unsaved%=TRUE

  	title$=FNwimp_getwindowtitle(main%)

   PROCwimp_putwindowtitle(main%,title$+*)

ENDIF

IF window%=warn% AND icon%=0 THEN

   unsaved%=FALSE

   PROCwimp_closewindow(warn%)

   PROCwimp_quit(quittype%)

ENDIF

IF window%=warn% AND icon%=2 THEN PROCwimp_closewindow(warn%)

ENDPROC



Examination shows that we have amalgamated the separate cases neatly by merely introducing the new global variable quittype% into FNuser_quit() and using its value in PROCuser_mouseclick(). This new variable only comes into play when the user wants to stop the quitting action - whether initiated as an application quit or a shutdown. (You will also see that IF THEN statements have been used instead of the previously shown CASE statements. This is solely to keep the tutorial !RunImage coding consistent with what was already there - but it also demonstrates that Basic usually offers more than one way of achieving an end result .......)



[Your !RunImage listing should now look like listing RI_11 in Tutor3 (apart from the REM lines, perhaps). This listing is not altered further - and there are no further tutorial listings.]



In order to inject a further element of realism, the above coding also arranges things so that clicking the OK button of the main window will trigger the unsaved data status and show this in the main window title in the usual way - by adding an asterisk to it.


Now, run !MyApp, open the main window and click the OK button. An asterisk should appear on the title bar.


Now try to quit the application by selecting Quit from the iconbar menu. The warn% window appears and allows the user to choose what happens next - as described earlier.



Check the similar action on selecting Shutdown from the Task Manager iconbar menu.....


..... and there you have it.



Note that the above coding does not include refinements for:


i) removing the asterisk from the main window title if Discard is chosen;

ii) incorporating the good housekeping addition shown in the application quit sub-section.


which you should be able to tackle without difficulty.


These refinements are also related to your decision as to whether or not your application is to quit if a shutdown is initiated and another application halts the shutdown after your application has said it is ready to quit. If, in that circumstance, you decide that your application should continue to function then you will not want to take the good housekeeping steps.


Another user-friendly feature you might want to consider when the user opts to save some unsaved data, is to arrange for the appropriate Save window to open, ready for the save action to take place.



Final points

The above descriptions are worth re-reading because, although the fundamentals are really fairly simple, the action flows very circularly between FNuser_quit() and PROCwimp_quit() and at first it is easy to mix up the value of the parameter type% and the return value from FNuser_quit().



The only vital point to remember is to be very wary of using the call:


PROCwimp_quit(1)             i.e. as opposed to PROCwimp_quit(0)


because the only occasion that it has meaning is when your application needs to re-start a shutdown that it has just interrupted. If you attempt to use this call at any other time you will get a (non-fatal) error message.


(Please note that PROCwimp_quit(0) is actually designed to exit the main Wimp Poll process, so it should only be called from within a user-function structure - as is the case in the many instances in this Manual.)



28. Icon validation strings

Each icon (and writable menu item) has a validation string. This can be a null string or it can contain some commands which are separated by semicolons. These commands allow the programmer to define many properties of the icon, in addition to those set by the icon flags.


The validation string for an icon is normally set in a template editor when editing the icon, and for those with the RISC OS 3 Programmers Reference Manuals all the options can be found on page 3-102.


The validation string is an indirected text string (see next section) whose memory location is set up as part of the icon definition. An icon cannot have a validation string unless the icon is made indirected. (For writable menu items Dr Wimp automatically creates the needed conditions.)


A common command is Rn, where n is a number from 0 to 7, which specifies the border type for the icon. For example, R6 is the default action type border and R7 is a writable icon type border. R0 is equivalent to not using the R-command.


If the icon can be pressed in then the slab in colour can be set. If you create a default action button in !WinEd you will see that the validation string is R6,3. Try changing the 3 to 7 or 11.


In Section 2.14 we saw that another very common command is Pspritename, where spritename is the name of a sprite for the pointer when the pointer is over that icon.


If you have lots of writable icons in a window then you can make it so that the caret can be moved between them with the Up and Down arrow keys, Tab and Return. If you put Ktar in the validation string of all your writable icons then they can all be navigated in that way. t - Tab, a - Up/Down Arrow keys, r - Return. You can use any combination you like.


The caret will move in order of icon number so if you have writable icons numbered 3,11,7,8,2 then it will move in the order: 2,3,7,8,11 for the Down arrow, Tab or Return and 11,8,7,3,2 for the Up arrow. So make sure that if you are going to use this then your writable icons are numbered in such a way that the caret will move in a predictable manner.


If you want the Wimp to notify your application of all keypresses e.g. so that you can take some specific programming action in response to, say, the function keys, then you will need to use Kn in the validation string (and this would bring the special key codes table in Section 2.4 into use).


As mentioned, more than one validation string command can be used for each icon (or writable menu item) if they are separated by semicolons. So for a typical writable icon you may have: R7;Pptr_write;Ktar


(A more comprehensive explanation of all validation string commands is contained in Dr Wimps Surgery - the charity book mentioned at the start of this Manual.)



29. Indirection


Throughout this manual, you will have seen many references to indirected icons or indirected text. Here is a brief description of what it means, and why it is important to using the Wimp. (Dr Wimp actually removes all the complications of handling indirected or non-indirected features, but it is nonetheless better to have an appreciation of this topic.)


Each icon in the desktop is defined by a small block of memory. This block is of a fixed size (plus any indirected items - see below) and contains a complete description of the icon so that the Wimp can draw it.


This block contains the dimensions, several flags containing information such as whether it is a sprite, text, sprite and text, filled, has a border, etc and some data on what it contains, such as actual sprite name or text. Most of the flags you can toggle between set and unset using a template editor, such as !WinEd.


The total size of the icon block is 32 bytes. 12 of these are used for holding the data concerning the text and/or sprite used in the icon. You can specify a text-only icon, a sprite-only icon or a text-plus-sprite icon. You can also specify whether the text or icon name is to be indirected or non-indirected.


If you choose non-indirected it means that the text (or icon name) is held in the icons data block directly - and thus cannot be changed and is subject to a rather small maximum size (11 characters plus a terminator).


If you choose indirected it means that the icons data block holds the value of the maximum allowable length of the text and a pointer (memory location) to where the text is stored. Thus the text in the icon can easily be changed by changing the text in the memory location where it is stored and it is not subject to the 11+1 character limit. This is what happens when you use PROCwimp_puticontext, which we saw in Section 2.3. An indirected icon can also have a validation string - see Section2.28


Therefore, indirection - which is a general concept - essentially means that the text (or sprite name, or other data) is held somewhere else which is located by its memory pointer. Indirection can apply to many other circumstances e.g. window titles, menu title/text.


If you use an indirected text-plus-sprite icon, the text is indirected as just described but the indirected sprite name is then held in the validation string - under the S-command (see earlier) - which itself is indirected memory space.


Once you have decided whether or not to use indirection in icons and window titles when preparing your window templates, Dr Wimp removes all the complications of handling the consequences of the choice.


By the way, if you define an icon as indirected with an indirected size of, say, 16 and then use PROCwimp_puticontext to try to put in a string greater than 15 characters long (15 plus terminator equals 16), the text of the new string will be truncated automatically to the defined maximum i.e. 15 characters, here.


30. Wimp messaging system

The Wimps messaging system is a means used by the Wimp to manage multi-tasking applications effectively. It is particularly important for handling file tranfers e.g. saving/loading/printing. The DrWimp library routinely receives all these messages and acts automatically on many of them, but does not (yet?) use them all.


For the vast majority of circumstances this messaging system will be entirely hidden from Dr Wimp users (thats the whole point!) but for some advanced operations it can be useful for any messages that are received by your application but unused by the DrWimp library to be passed on to the programmer via a user-function.


This is DEFPROCuser_wimpmessage(messagenumber%,block%,reasoncode%). When it is called, the unused wimp-message number will be in the first parameter and the second parameter will give the address of the memory block holding associated data. (If you know enough to use this facility you will know how to use the second and third parameters!) The final parameter will hold the reason code passed by the wimp poll and this will be either 17, 18 or 19 in these cases.


Because there are frequent wimp-messages and because it will not be a frequently used facility, the option to pass on the unused messages is provided with an on/off switch - and this is set to its default value of off at application start-up.


The switch is controlled very simply by the special global variable UNUSED%. This is set to FALSE within FNwimp_initialise, on application start-up, but you can set it to TRUE at anytime after that (including within PROCuser_initialise, if you wish).


During any time that UNUSED%=TRUE the message number of any wimp-messages received but not used within the DrWimp library will be passed via PROCuser_wimpmessage for you to detect and act upon if you so wish.


For your information, the current version of the DrWimp library uses the following wimp-messages, so these values will never be passed via PROCuser_wimpmessage:


0			Quit

&1			DataSave

&2			DataSaveAck

&3			DataLoad

&4			DataLoadAck

&5			DataOpen

&8			PreQuit

&A			SaveDesktop

&502		HelpRequest

&400C0		MenuWarning

&400C1		ModeChange

&400CC		WindowInf

&47700		ColourPickerColourChoice

&47702		ColourPickerCloseDialogueRequest

&80147		SetPrinter

31. Iconiser

Iconising is the result you get on pressing a windows Close icon whilst holding down <shift> The window is converted to an icon on the Pinboard, from whence it can be re-opened by double-clicking on it (see User Guide). With later versions of RISC OS the same can be achieved by pressing a special iconiser button on the window furniture.


Your DrWimp application responds automatically to the Wimps iconiser protocol and allows you to alter the text and sprite used - for customising. It does this by calling PROCuser_iconise whenever iconising action takes place.


If you do nothing, the iconised sprite will be the default one supplied by the Wimp (a framed question mark for an application window) and the default text beneath it will normally be the title of the window being iconised. However, if there is no window title text, or the text includes the word untitled, then the default text will be the name that you used for your application in FNwimp_initialise e.g. YourApp.


If you want to use a customised sprite and/or different text, then all you need to do is set the names of them in PROCuser_iconise, as follows. You will note that the skeleton !RunImage contains:


DEF PROCuser_iconise(window%,RETURN text$,RETURN spritename$)

ENDPROC



When called by the DrWimp library, these parameters will contain the window handle where the iconising action has taken place plus a default text and default sprite name. The text is straightforward - as mentioned above - but note that the Wimp will probably automatically truncate all text to the first 10 characters.


However, for iconising, the Wimp always uses sprites whose name begins with the prefix ic_ e.g. ic_draw or ic_yourapp etc. The prefix ic_ is added automatically by the Wimp. So, spritename$ only needs to contain the wanted sprite name without the prefix e.g. if your applications declared name is YourApp then, when PROCuser_iconise is called, the default name in spritename$ will be YourApp.


If you do nothing then the contents of spritename$ will not change and the Wimp will, using the above example, be looking for an iconiser sprite called ic_yourapp - sprite names are not case-sensitive. If it finds one with the right name it will use it. Otherwise it will use the Wimps own default iconiser icon.


Conversely, to demonstrate iconiser customisation, lets say that you want the text beneath the iconised window (whose handle is main%) to be AppMain and you want a sprite called ic_neat to be used. You would effect this simply by using something like:


DEF PROCuser_iconise(window%,RETURN text$,RETURN spritename$)

CASE window% OF

	WHEN main%

		text$=AppMain

		spritename$=neat

ENDCASE

ENDPROC

and, of course, you would have to supply sprites called ic_neat in the !Sprites/!Sprites22 spritefiles. Thats all there is to it.  You can easily see that this can be used to show a different text and/or sprite for each of your applications windows, if you wish.


However, please note that the Wimp does not allow sprite names to be greater than 10 characters. Hence, if you want to customise the iconiser it is vital that the name you use in spritename$ above does not exceed 7 characters - to allow for the prefix ic_. If the overall sprite name length does exceed 10 characters then the Wimp will truncate the name to the leftmost 10 characters and try to find a sprite name to match. If it cannot find one, the Wimps default iconiser sprite will be used instead. You will be warned if your intended customised sprite name is too long. (This point also explains why it can help to keep application names to no more than ! plus 7 characters.)


(If you use !Fabricate - see Section 2.35 - the resulting customised skeleton application will include a rough (very!) sprite for iconising purposes, called ic_myapp - which is also included in the !MyApp skeleton. !Fabricate will also warn you about, but not prevent, your application name exceeding 7 characters.)

32. Grubby tasks and front-ending

You will sometimes see tasks that load onto the iconbar, but when the icon is clicked on they leave the desktop and monotask. When the user has finished, they are returned to the desktop, with the application still loaded onto the iconbar. Acorn calls these tasks Grubby tasks, and they are simple to implement with Dr Wimp.


Alter PROCuser_mouseclick so it has a line like:


CASE window% OF

	WHEN iconbar% :

	PROCwimp_starttask(BASIC -quit <MyApp$Dir>.Mono)

ENDCASE


Create a BASIC file called Mono inside the !MyApp directory containing the following:


MODE12

PRINT This is monotasking!

A$=GET$

*DESKTOP

END


Re-load !MyApp and click on the iconbar icon. Press a key to return to the desktop. Note: change the mode number to one suitable for your monitor.



You will probably want to mangle up the second BASIC file as well as !RunImage with DrWimp to give you more security. This is possible if you dont use DrWimp in the second BASIC file. Mangle it up with !MakeApp3 in the usual way, and then change the PROCwimp_starttask to something like:


PROCwimp_starttask(Run <MyApp$Dir>.Mono)



Similarly, PROCwimp_starttask() opens the door to frontending i.e. constructing a simple Wimp program to provide the input/output for routines which are normally based on Command Line operations.

33. Bits & bobs

Here are a few other useful points.


Current day/date/time

It is often useful to be able to insert the current day and/or date and/or time into text etc. The following wimp-function is provided for this:


FNwimp_getdaydatetime(choice%)


Depending on the value of choice% - see Section 3.1 - a string is returned containing either the day, the date, the time, or all three.


Number formatting

There are numerous occasions when numbers need to be presented in a certain format and Dr Wimp provides several wimp-functions for this. For example:


FNwimp_decplacesstr() - gives (as a string) a number rounded to a chosen number of decimal places.

FNwimp_decplacesnum() - as above but returns a number instead of a string.

FNwimp_roundfloat() - rounds a number to the nearest integer.

FNwimp_numtodecstring() - converts a number in any format to a decimal integer (as a string).

FNwimp_numtosigneddecstring() - converts a number in any format to a signed decimal integer (as a string).

FNwimp_numtohexstring() - converts a number in any format to an integer hex value (as a string).

FNwimp_numtobinstring() - converts a number in any format to an integer binary value (as a string).


Note that most of these wimp-functions produce a string output. This is because in wimp-programming the display of numbers is invariably in string form.



Directory paths/Leafnames

Sometimes it can be useful to get a directory path or a leafname from a pathname.


If the pathname is:


IDEFS::Andy.$.Progs.Project1.!Wow.Sprites


then the the directory path is IDEFS::Andy.$.Progs.Project1.!Wow. (note the trailing fullstop.)


and the leafname is Sprites


DrWimp can extract these names for you with:


FNwimp_getdirectorypath(path$)



which returns the directory path, including the trailing fullstop (or trailing colon if something like Boot:!Help is the full path) and:


FNwimp_getleafname(path$)



which returns the leafname.


Filer actions with files and other directory objects

It is often convenient to be able to replicate normal Filer actions by programming instructions. Several wimp-functions are provided for these purposes. They are:


FNwimp_copyobject(sourcepath$,destinationpath$,deletesource%,ne-wer%,restamp%,force%,warning%)

FNwimp_deleteobject(filepath$,force%,warning%)

PROCwimp_setfiletypenumber(file$,filetype%,warning%)

PROCwimp_setfiletypehexstring(file$,filetype$,warning%)

FNwimp_getobjecttypenumber(path$,warning%)

FNwimp_getobjecttypehexstring(path$,warning%)

PROCwimp_doubleclickobject(path$,warning%)

PROCwimp_createdir(path$,warning%)

FNwimp_renameobject(existingpath$,newpath$,warning%)

PROCwimp_opendirectory(dir$,default%,topx%,topy%,width%, height%,iconsize%,sortby%,warning%)

PROCwimp_closedirectory(dir$)


FNwimp_copyobject() can be used for both copying and moving a file/directory/application. Its first two parameters define the object to be copied/moved and the pathname of the copied/moved object. (Both can be wildcarded within the same constraints as using the *Copy star command. Recursion will take place, as necessary.)

If the third parameter, deletesource%, is set to 0 the object will be copied, and if it is set to 1 the original object will be deleted after it has been copied - effectively moving the file. But note that the move option (i.e. setting the third parameter to 1) will not work for locked files unless the force% parameter is also set to 1.

The parameter newer% only comes into effect if the copying action would overwrite existing objects, when setting newer% to 1 will only overwrite if the source object is newer than the destination object.

If set to 1, the parameter restamp% gives the option of re-stamping the copied object with the current time/date.

If warning% is set to 1, a warning will be given if the source object does not exist. (If the object does not exist and warning% is set to 0 then no action will take place.)

Finally, this function normally returns 1, but will return 0 if the copying action fails in any way.



FNwimp_deleteobject() is similar but, of course, takes only one file-path. If force% is set to 1 locked objects will be deleted: if it is set to 0 they will not be. Again, directory recursion and wild-carding can be used. warning% acts as in the previous function. Also, the function normally returns 1, but will return 0 if the action fails in any way.


PROCwimp_setfiletypenumber() is straightforward. The required filetype needs to be set in the second parameter filetype% as a numerical value in the range 0 to &FFF. (Anything outside this range will be set as &FFF.) Again, warning% acts as in the previous functions but covers more circumstances. Its companion is PROCwimp_setfiletypehexstring() and in this case the required filetype needs to be set in the second parameter filetype$ as a string in the hex form &FFF or just FFF. The same range correction will apply and warning% acts as in the previous functions but covers more circumstances.


To find the file-type of a named object use either FNwimp_getobjecttypenumber() or FNwimp_getobjecttypehexstring(). The first returns the filetype as a number and the second as a string. Again, warning% acts as in the previous functions.

Note that the second function is an exact repeat of FNwimp_testobjectpresent() but with a different name for convenience. Note also that the file-type of an object identified by number in a named directory can be found using FNwimp_getdirectoryobjecttype().


PROCwimp_doubleclickobject() acts exactly as if the user has double-clicked on the specified object. Again, warning% acts as in the previous functions.


PROCwimp_createdir() is straightforward and creates an empty directory. Again, warning% acts as in the previous functions but covers more circumstances.


FNwimp_renameobject() is also straightforward - it will rename an existing Filer object. Again, warning% acts as in the previous functions but covers more circumstances.


PROCwimp_opendirectory() opens a Filer directory window - and if warning% is not 0 a non-fatal warning if the specified directory cannot be found. If default% is not 0 then the window opens centred on the screen and with the default settings currently in force for the Filer. If default% is 0 then the other parameters are taken into account to specify the window position, the size of the Filer icons and how they are sorted. See Section 3.1 for details.


PROCwimp_closedirectory(dir$) simply closes the specified directory window.


Note that the above wimp-functions have deliberately been structured to avoid giving fatal errors. Further, those that are FNs give a return of 0 (or null string) if the required action does not take place. You are therefore able to capture the return value to take action on errors if you so wish.



Sending a file to the printer

The wimp-function PROCwimp_sendfiletoprinter(filepath$,delete%) is intended to have the same effect as dragging a file to the printer icon on the iconbar.


filepath$ is the full path of the file to be sent to the printer and delete% gives the option of deleting the file after it has been printed. If delete%=0 the file will not be deleted.


Note that this wimp-function will give non-fatal errors if a printer driver is not loaded or the specified file cannot be found.


Caret location

FNwimp_getcaretposition returns information about the current location/position of the caret.

Five items of information are available: the handle of window and icon with the caret in them; the x and y work area coordinates of the caret in a window; the position (index) of the caret within the text of a writable icon.



DrWimp library version number and upgrades

The DrWimp library periodically gets upgraded with modifications or improvements and this can mean that applications which you have made with earlier versions may not work properly (or at all) if you try to substitute the new DrWimp library.


To protect against this, there is a wimp-function to read the version number of the library. So, for example, at the start of your program you could add a short routine to read the library version number and alert you if it is not the same one as you used to create the application.


The wimp-function is FNwimp_libversion and it returns the DrWimp library version number x 100. So, if it is Version 4.30 then it will return 430.


Dont forget that there is no need to use any later DrWimp version with an application that is working to your satisfaction with an earlier version - even less need if you have used the post-programming utilities such as !Linker, etc.


However, if/when you decide to upgrade your application then it will probably make sense to use the then latest Dr Wimp version to do it and you can start by incorporating the new DrWimp version before making other changes. Always read the Upgrade file - within the Documents folder - to see what changes (if any) will need to be made to applications constructed with previous DrWimp library versions. Usually, where changes are necessary, they are very simple to do.


Of course, if you are starting a new application then it always makes sense to start with the latest version of Dr Wimp.


It is probably obvious, but in any complete version of the Dr Wimp package, the !Fabricate utility will always produce its skeleton application using the !RunImage/DrWimp library version of that package.



Resizing windows

PROCwimp_resizewindow resizes a windows work area to the supplied width and height. The work area is set to the new values, but the visible size will not be changed (unless the new work area is smaler than the visible size).

Use PROCwimp_resizewindowvisible to alter displayed size. N.B. If the visible window is wholly on the screen before using this wimp-function then it will be kept wholly on the screen after the re-sizing i.e. scrolling may take place automatically to achieve that.



Scrolling windows

There are three wimp-functions to manipulate the scrolling of windows from your program:


PROCwimp_scroll() allows you to scroll a window up/down/left/right by a user-given amount from its current position.


PROCwimp_scrollto() allows you to scroll a window to a specific scroll position (vertically or horizontally).


FNwimp_getscroll() returns the current scroll position of a window (vertically or horizontally).


All three wimp-functions can be used when the window is closed - and, with the first two wimp-functions, the new scroll position will be correctly in place when the window is next opened.


Note that the position of a vertical scroll will normally be a negative value.


To scroll a window at any particular time it must, at that time, have a visible size less than its full size (in the direction of the scroll) - and the definition of its minimum allowable visible area (in this same direction) must be such as to permit the required scroll. Dr Wimp will always carry out the scroll to the maximum extent possible if scrolling to the full amount intended is restricted. (If scrolling does not appear to happen it is invariably due to the fact that the window is either already at full size or already at one of its defined limits of allowable scroll.)



Icon colours

PROCwimp_colouricon can be used to change the colour of the text/background/border of an icon. The colour choice is from the standard 16 desktop colours - numbered 0-15.


From Dr Wimp version 3.62 colour change can be applied to icons defined to use either outline fonts or not.


However, if the icon is defined to use an outline font then some other conditions must exist in order that colour changing can be effected. The main condition is that you must then design the icon with a validation string which includes an F-command (See Section 2.28). If you omit an F-command - even for the default colours of Black on White (F-command F07) - colour changing will not work for outline font cases. Non-fatal warnings will appear to tell you what is wrong. To enter a validation string into an icon definition it will also be necessary to tick the text and indirected options in the Icon edit window of the Template editor.


When intending to change the colours of icon text/background/border, care needs to be taken to ensure that you have the appropriate border and/or filled options ticked in the icon definition. For example, you cant change the background colour if the icon isnt filled. Similarly, the border colour (same as text colour) will only be seen if a border has been chosen.


Note that with PROCwimp_colouricon you can grey-out labels which usually look better if not filled. (If you do that with PROCwimp_iconenable(window%,icon%,0) then the unfilled background turns white.)


Icon size and position

FNwimp_geticonsize is like FNwimp_getwindowvisiblesize in that is returns the dimensions of an icon - and FNwimp_geticonposition returns the work area position of an icon.

If you want to change the size (and/or position) of an existing icon in a window you can use PROCwimp_resizeicon() or, only to move it, PROCwimp_moveicon(). 


Icon selected/de-selected

FNwimp_geticonselect returns 1 if the icon is selected, or 0 if it isn't.


Icon hide

FNwimp_iconhide allows an existing icon to be hidden from display, or displayed again if it is hidden - or toggled between these two states.


Icon flag bits

PROCwimp_iconbit allows a specific bit of an icons icon flags to be set, unset or toggled between the two states.

It is complemented by FNwimp_geticonbit which returns the current state of a specified bit of an icons icon flags.


Graphics colours

PROCwimp_setcolour sets the current foreground or backround GCOL colours for drawing/printing when the colour setting is not a part of the plotting function parameters. Dithering is used if the exact colour is not available in the current mode.


This function is best used immediately before the plotting/printing action to which it is to apply. In particular, when this function is required in a redraw process it is essential that it is used within DEF PROCuser_redraw rather than outside it.


Also, it is often wise to restore the foreground/background to their original colours after they have been changed for a particular plotting/printing action.


Simple geometric shapes

Intended for use within PROCuser_redraw, there are wimp-functions to plot, respectively, a line (full or dotted), a rectangle, a circle, an ellipse (rotatable) and a triangle in a window. Where relevant, there is an option to draw the shape filled or in outline. The functions are:

PROCwimp_plotwindowline

PROCwimp_plotwindowrectangle

PROCwimp_plotwindowcircle

PROCwimp_plotwindoweelipse

PROCwimp_plotwindowtriangle.


(These functions will often be used in conjunction with PROCwimp_setcolour, described in the preceding sub-section.)


Storing strings and integers in memory blocks

Although arrays are the traditional way to store indexed strings and numbers, the storage space they use (via the DIM statement) is necessarily part of their applications WimpSlot. This can sometimes be a disadvantage: for instance, when the number of strings/numbers needs to change while the application is running, perhaps because the user loads a different data file.


As an alternative, for strings and integer numbers only, Dr Wimp offers a small suite of functions which carry out the same purpose as arrays but can, if required, use dynamic area storage space. Their speed of operation is only very marginally slower than using arrays.


For strings, a storage block is created using:.


block%=FNwimp_createstringblock(n%,len%,da%)


where n% is the maximum number of strings to be stored and len% is the maximum length of any of the strings (limited to 255, as usual).

If da% is any value other than 0 then the storage block will be created as a dynamic area. If da% is 0 then a normal DIM creation will be used.

The return - here, assigned to block% - is the handle of the created storage space.


Once the block has been created, strings can be put in it using:


PROCwimp_putinstringblock(block%,string$,pos%,error%)


where block% is the block handle, string$ is the string to enter and pos% is the string position in the block (i.e. the same as an array index).


error% is a flag to determine what happens if you try to use a value of pos% outside the range for which the block was created. E.g. if a block for a maximum of 30 strings was created then the valid range for pos% would be 1-30. If error% is any value other than 0 then an error messge will be generated and no action will be taken. If error% is 0 then the string will be put into the lowest position (1) or the maximum position, depending whether pos% is less than 1 or greater than the maximum.


Similarly, to retrieve a string from a block use:


s$=FNwimp_getfromstringblock(block%,pos%,error%)


where the meanings of the parameters are the same as above.


However it is important to note that the function always needs to generate a return whatever the values of pos% and error%. If pos% is outside the valid range and error% is not 0 then the return will be the string stored in either the lowest or highest position. Whereas if pos% is outside the valid range and error% is 0 the return will always be a null string. As these returns are otherwise valid strings - albeit false - extra care should be taken to ensure pos% is not used outside its valid range. (In this respect it is strongly suggested that error% ought to set to 1 during development of an application to ensure that use of non-valid values of pos% are picked up and the reasons eliminated.)

The final function of the small suite is:


PROCwimp_setstringblock(block%,string$)


which is hopefully self-explanatory and is provided to set all elements of a created block to the same value - in a similar way to using


arrays()=string$


to set all elements of an array.


For integer numbers there is an entirely complementary suite comprising:


FNwimp_createintegerblock(n%,da%)

PROCwimp_putinintegerblock(block%,value%,pos%,error%)

FNwimp_getfromintegerblock(block%,pos%,error%)

PROCwimp_setintegerblock(block%,value%)



Hourglass

PROCwimp_hourglasson and PROCwimp_hourglassoff turn the hourglass on and off respectively. Once the houglass has been switched on, it can be changed to show a percentage value using PROCwimp_hourglasspercentage.

Please note that the percentage value must be in the range 0-99 and any value outside this range will switch off the percentage display.

Further, note that calls to turn the hourglass on/off can be nested but any use of the percentage can only be associated with the nesting level in which it is initially started - and turning the hourglass off from that nesting level will cancel the percentage display.


Desktop save

You have the option to choose whether or not your application responds to the Wimps desktop save protocol.


This protocol means that if a user selects Desktop save  from the Task Manager iconbar menu whilst your application is running then - if you have chosen to activate the option -  your application will be duly entered into the list of tasks to be run automatically on future start-ups. (See User Guide for more details on desktop save.)


The option is exercised on task initialisation by setting the fourth (final) parameter of FNwimp_initialise. Seting this parameter to 0 disables the action: setting it to 1 enables the action. See Section 2.1 also.


Auto-extraction of any start-up options and/or start-up file

Two special global string variables called wStartupoption$ and wStartupfile$ have been created within the DrWimp library.

If, for any reason, you wish to start your application with a call of the form, say:

Run <MyApp$Dir>.!RunImage %*0 -option1 -option2

or

Run <MyApp$Dir>.!RunImage <filepath$> -option1 -option2

then, after start-up, wStartupoption$ will contain:

-option1 -option2

There can be as many of these options as you wish (up to the usual string limit of 255 characters) but each must be separated by a <space> character as shown. N.B. Any such options must be at the end of the command, as in the examples above.

You can then interpret this options string as you wish in your application coding.

As you will already know, if you start your application by double-clicking on a file that is owned by the application - or include a file in a starting command as shown above - then Dr Wimp automatically passes that file to your application by calling FNuser_loaddata() - see Section 2.11. Additionally, after start-up, the global variable wStartupfile$ will also contain the full path of the same file. This feature is offered for convenience only and can be useful in some circumstances: it does not impinge on the normal operation in any way.


Buffer space

Those of you who delve may wish to know that attempts have been made in DrWimp to avoid unnecessary re-DIMming of buffers etc.  e.g. when a change of indirected text can fit into the existing buffer space. This should be entirely invisible to you, but some users like to know.


Debugging

With any programming exercise there will always be a need for debugging i.e. locating and correcting the source of errors.

There is no perfect solution and each programmer has their own favourite methods. However, in recent years some very useful debugging utilities have appeared on the PD scene, One in particular has a very wide range of easily-understood and easily-used facilities - and is under active support. It is !Reporter, which is Freeware by Martin Avison and is available from:


http://www.avisoft.force9.co.uk/

Post programming utilities

Please dont forget to explore the utilities included in the Dr Wimp package (in the Utils folder) for use after you have completed the programming of an application. You may find them helpful. They include:


!Linker	for merging your !RunImage with the DrWimp library and at the same time eliminating any wimp-function DEFs not actually used. This often allows a significant reduction in the required WimpSlot size.

!StrongBS (Freeware by Mohsen Alshayef) a very comprehensive Basic compactor. This always gives a good reduction in program size (WimpSlot need - see Section 2.34) and renders it very difficult to read and amend. A run-time speed increase also normally results.

(Note that !StrongBS has options to carry out the same actions as !Linker and !MaheApp - at the same time as compacting, if required.)


Using a Basic compiler

The purpose of a Basic compiler is to take a completed Basic application and convert it into a machine-code equivalent, so that the program no longer runs in Basics interpreted  mode - and therefore, in principle, runs faster.


At the time of writing there is only one compiler known to be available; namely the ABC compiler (A Basic Compiler) from Castle Technology.


This compiler currently will not handle operations involving whole arrays - a standard Basic operation which is used in Dr Wimp in two places:


FNwimp_createmenuarray

PROCwimp_recreatemenuarray


both of which include a whole array as one of their parameters.


Therefore, if you are intending to try the ABC compiler on your Dr Wimp product you must not use either of these wimp-functions.


Neither must you use any operations on whole arrays in any of your own coding that you add in developing your !RunImage. For example, the common whole array operation statement:


array%()=0


used to set all elements of an array to the same value (here 0) would need to be replaced with a suitable FOR/NEXT loop, perhaps like this:


FOR N%=0 TO arraysize%

    array%(N%)=0

NEXT


Finally, for compiling it is always best to declare any global variables before you first use them - and doing this in DEFPROCuser_initialise is a good place.


Amount of free RAM available

The wimp-function FNwimp_getfreeRAM allows you to check the amoint of free RAM available at any time. It is useful to use this to check before, say, creating or increasing the size of Dynamic Areas.



34. Application memory needs


In order for any Wimp application to run successfully it is essential that it has enough memory space reserved for it.


Using Dr Wimp, there are two critical values that you need to check. They are:

- the WimpSlot

- the size of wimpmem% i.e. the second parameter of FNwimp_initialise - Section 2.1.


WimpSlot

The WimpSlot is invariably set initially in your applications !Run file and Dr Wimp follows this standard practice. Have a look in the !Run file of the supplied !MyApp application - or in the application produced by !Fabricate. You will see a line like this:


WimpSlot -min 192k -max 192k


We dont need to explain this star command in detail - but it worth noting that the spaces in this line and the dashes in front of min and max are essential. Note also that the same value (here, 192k - denoting 192 kilobytes) is used in both places. This is another common practice.


In most cases, the WimpSlot is not altered again after its !Run file setting, but DrWimp offers PROCwimp_increaseslot to allow you to icrease the slot size from within your program if you wish.


The WimpSlot value needs to be sufficient to cope with the total running needs of your application. It needs to cater for at least the following:


!RunImage and DrWimp (and any other) library size

Cumulative size of all window/icon/menu definitions including their indirected data

Variable names and values

Arrays

DIMed memory, but not RMA/Dynamic Areas (DIMmed memory includes any use of the Dr Wimp file-loading wimp-functions for sprite-files/drawfiles etc.)


When you bear in mind that the !MyApp !RunImage and DrWimp library as supplied currently exceed 100kilobytes in size, you will appreciate that a default WimpSlot value of 256 kilobytes gives room for some addition of your code etc.whilst you are working without linking or compacting - but is by no means generous and might well be exceeded as you develop your application. So you must keep reassessing your WimpSlot needs as the application grows.


A sure sign that the WimpSlot is large enough to load but not large enough to run is the sudden onslaught of (possibly different and apparently unrelated) error messages that you werent getting before the last code change. These are signs that the program is overwriting already-created parts of the memory in use. Even the common error Unknown or missing variable can then result - and many others.


If the WimpSlot is too small to allow the application to load then it will probably just hang and you will need to resort to <Alt-Break> to clear it.


When you are happy with your application - and/or you have used the post-programming utilities (see Sections 1.7 and 2.35) - you can take steps to reduce the WimpSlot size. A good idea for this purpose is temporarily to add the line:


VDU4 : PRINT (END-PAGE) : VDU5


just before the natural end of your program i.e. just before Line 100 of the !RunImage in the supplied !MyApp.


Then, when you Quit the application, you will get a value shown (in bytes) - normally in a small Task Window. This will be approximately the minimum size of the WimpSlot needed. So add a small amount to it and divide it by 1000 to get a rough number of kilobytes needed. Then change both the values in the !Run file line accordingly.


But remember exercise your program before taking the above Quit action - otherwise the reported value is likely to be too low for safety. (Indeed, it is interesting to compare the values from quitting immediately after loading and then after loading and exercising it.)


Also, try to remember that if/when you revisit the application to upgrade it, you are sure to want to use the unlinked and uncompacted source version - and these are unlikely to work with a WimpSlot size reduced for a released version .........



wimpmem%

This variable appears solely in the second parameter of:


FNwimp_initialise(name$,wimpmem%,ver%,desktopsave%)


which is called just once (see Line 80 of !RunImage of supplied !MyApp). Its default setting is 7000 (bytes) in the supplied !MyApp or via !Fabricate.


The value you enter here needs to be large enough to hold the largest single window definition to be used in the application. Each window needs 88 bytes plus 32 bytes for each icon within it (plus any indirected data) - including any icons that might be added to a window by creation within the program. Thus, the default of 7000 will cope with around 215 icons in a window (without indirected data). This should be adequate for many applications.


If you are using the supplied !WinEd window template editor, the Statistics option from its main menu will supply the necessary value for you - but remember to add more for any icon creation within the program. (Note also that you need to ensure that there is sufficient space for the maximum indirected text lengths that you have specified in the window/icon/menu definitions - and not just the sizes that you might use initially. !WinEds Statistics window takes this into account.)


35. Saving time with !Fabricate

After writing a few applications, at the start of each you will find yourself having to find a templates file with an info window in it, rename the sprites and all occurrences of MyApp to your application's name, create an iconbar icon and iconbar menu, fill in the details in the info window, set the version, etc, etc.


Doing this routine work over and over again gets tedious, hence the utility !Fabricate in the Utils folder has been designed to avoid all this. It can do all those things for you - and more - leaving you to get on with writing the interesting parts.


The user can design and automatically incorporate a custom iconbar menu as an alternative to the standard 2-item menu. Also the users own window template file and custom sprites can be specified (by dragging) and will automatically be loaded by the output skeleton application. Further, one of these windows can be chosen to open when the iconbar icon of the resulting application is clicked.


Thus !Fabricate automatically builds a customised initial application which already goes a lot further down the development path than the skeleton !MyApp.


Its really worthwhile getting into the habit of using this utility application at the start of any new program development.


Instructions for using !Fabricate are in the !Help file within its application folder.


36. Dr Wimps Elixirs


The main aim of Dr Wimp is to provide a comprehensive flexible and integrated set of facilities to allow the user to build Wimp applications easily and without many restrictions. Consequently the vast majority of user- and wimp-functions address items which are of general applicability and might therefore be used in a very wide range of applications.


However, from time to time, a way of meeting a more specific programming need presents itself and, where practicable, it seems useful to make these solutions available to users to add to a particular application as and if they are needed - rather than to add them as permanent parts of the skeleton !RunImage and/or DrWimp Library.


These optional additions are called Elixirs - because they aim solely to cure a particular problem!


Elixir_01 - Redrawing long scrolling lists

If you have a long list of text lines (to be plotted directly to a window rather than using stacked icons to show the text) the window will need to be much larger in height than the screen. i.e. a vertically scrolling window is needed to show the whole list.

When the window is scrolled the redraw process is used to update the list lines in sympathy with the scroll position.

It soon becomes obvious that if you seek to redraw the whole list each time a scroll occurs you will find that your usual desktop operations are very seriously affected - purely because of the (repeated) time it takes to redraw the whole list - and the same undesirable effects occur if you drag/resize etc. another window on top of this text list window.

The solution is to ensure that the redraw action constrains itself solely to those text lines which are actually going to be visible at any point in time, and this is the purpose of Elixir_01.


This Elixir consists of a matched pair of one user-function DEF and one wimp-function DEF:


PROCuser_redrawtextline(x%,y%,line%)

PROCwimp_calcredrawlines(leftmargin%,topmargin%,totallines%,

									linespacing%)


If you want to use the elixir then both these function DEFs must be added to your !RunImage listing.


You must not alter the contents of PROCwimp_calcredrawlines(). Among other things, it calls its paired user-function PROCuser_redrawtextline()- and it is to this latter that you will need to add coding.



PROCwimp_calcredrawlines() needs to be called from within PROCuser_redraw() when the list window needs updating - merely ensuring that its parameters reflect your choices, as follows:


leftmargin% - (OS units) the horizontal distance from the left edge of the list window to the start of the text line. Normally a positive value but can be negative if required.

topmargin% - (OS units) the vertical distance from the top of the list window to the top of the area in which the list is displayed. Normally a positive value but can be negative if required. Typically used to provide space for a superimposed non-scrolling pane at the top of the list, so that the list can scroll under the pane without hiding the first line when the scroll is at zero.

totallines% - the total number of text lines in the list.

linespacing% - (OS units) the vertical spacing between list lines. (Note also that the first line of the list will be plotted at this value below the value of topmargin%, because the text-plotting functions use the bottom of the text as the y-value reference.)


As indicated earlier, you will need to add your specific code to:

DEF PROCuser_redrawtextline(x%,y%,line%)

and the needs are very simple indeed.


All you need to do is add the code to plot the text of one line using the passed parameters:


x% - actual plotting x-position of line of text (in screen OS values)

y% - actual plotting y-position of line of text (in screen OS values)

line% - the number of the text line to plot.


Note that the x/y values are in screen OS units so that you need to use the direct screen text plotting functions rather than the window text plotting functions.


To maintain good speed, it is normally best to store the list of text lines in an array, which needs to be set up separately.


A typical complete coding might be as simple as:


	In the main redraw user-function:


DEF PROCuser_redraw(window%,minx%,miny%,maxx%,maxy%,

										printing%,page%)

CASE window% OF

WHEN listwindow%

PROCwimp_calcredrawlines(leftmargin%,topmargin%,listlength%

											linespacing%)

ENDCASE

ENDPROC


 	plus:


DEF PROCuser_redrawtextline(x%,y%,line%)

PROCwimp_plottexth(text$(line%),listfont%,x%,y%,0,0,0

											255,255,255,0)

ENDPROC


In the Examples folder there is an example application called !Scroll to demonstrate Elixir_01.





Elixir_02 - Copying a dragged icon

Dr Wimp has facilities to manage the dragging of ordinary icons - provided they have been defined as draggable - and it is for the programmer to decide what should happen (if anything) when dragging occurs. (This Elixir does not work for icons of button type 14  - Write/Click/Drag)


One of the popular requirements might be to copy the dragged icon to the place where the drag ends, perhaps ending up with two identical icons or perhaps deleting the original icon to give the effect of moving the icon from one place to the other. Elixir _02 exists solely for this purpose.


The elixir consists of just one wimp-function DEF:


FNwimp_copydraggedicon(startwindow%,dragicon%,dragboxminx%, dragboxminy%,dragboxmaxx%,dragboxmaxy%,endwindow%, delete%)

 

and it is designed to be used only in DEF PROCuser_endicondrag() with which it shares all but one of its parameters - so these can be copied through.


The exception is the final parameter delete% which determines whether or not the original icon (i.e. the one which was dragged) is to be deleted in the operation.


If delete% is set to 0 then no deletion will occur and the dragged icon will remain in its original position with a copy being created at the end-of-drag position. If delete% is set to 1 then the dragged icon will be deleted from its original position - giving the effect that it has been moved from its start position to its end-of-drag position.


In either case, the new (copy) icon will be created as part of the window definition of the window in which it appears. It will have its own icon number (the lowest available, see later also) and can then be treated as any other icon defined in the window e.g. wimp-functions such as PROCwimp_puticontext() etc. can be applied to it. 


Commonly, the programmer will want the icon copying to take place only within the window from where the dragging starts - and in this case endwindow% will be the same as startwindow%. It is, however, perfectly OK to copy the icon into another open window - provided that the other window is a window of the same application. 


Finally, if the copying is confined within its own window and you choose to set delete% to 1, then the moved icon will take on the same icon number as the original icon (now deleted) - as long as you ensure that there are no gaps in the icon numbering of your initial definition of the window.



Elixir_03 - Constructing a custom sprite

There are some occasions when user graphics/text are sufficiently long-winded to make them inconvenient for a redraw window, perhaps because the graphic up-dating time becomes very evident when the window is moved/scrolled etc. For instance, displaying a graph could fall into this category.


In such cases, it is often practical to plot the graphics/text to the canvas of a large blank sprite and then display the sprite using Dr Wimps normal sprite-plotting functions. The main advantage of this method is that redraw window updating is instantaneous (in human terms, anyway). Another advantage is the fact that ordinary Basic VDU/PLOT-type commands can be used for the graphics drawing.


Elixit_03 exists solely to help with this sprite-building process.


The elixir comprises a small suite of function DEFs:


FNwimp_buildsprite(spritename$,sprwidth%,sprheight%)

PROCwimp_plotinsprite(spritearea%,spritename$,sprwidth%, sprheight%)

PROCuser_spritegraphics(spritearea%,spritename$,sprwidth%, sprheight%)

PROCwimp_setdrawspritegraphiccolour(colour%)

PROCwimp_writedrawspritetext(text$,fonth%,spritex%,spritey%, foreground%,background%)


(There is also an internal function DEF FNwint_setupspritearea() in the suite. This needs to be copied into your !RunImage with the above functions but it is not for programmer access !)


To use this elixir - after having copied the whole suite to your !RunImage - you need to make a single call to FNwimp_buildsprite() at the appropriate place and place your graphics/text needs in DEF PROCuser_spritegraphics(). The latter returns the handle of the resulting sprite area which can then be used in the standard wimp-functions to render the sprite (probably within DEF PROCuser_redraw() ) and/or to print it. (See Sections 2.20 and 2.25).


The call to FNwimp_buildsprite(spritename$,sprwidth%,sprheight%) is simple: spritename$ is your chosen name for the sprite e.g. MySprite, whilst sprwidth% and sprheight% are your required width and height for the sprite - in OS units.


In effect, this call initially defines a blank rectangular sprite canvas of your chosen size - which will start with a default white background. It then goes on to make a call to PROCwimp_plotinsprite() - which is the wimp-function which automatically calls PROCuser_spritegraphics(). (The reason for making PROCwimp_plotinsprite() separate will become clear later.)


It is usually best to place the single call to FNwimp_buildsprite() within DEFPROCuser_initialise. However, this is not essential.


The use of PROCuser_spritegraphics() is best explained with a simple example:


DEF PROCuser_spritegraphics(spritearea%,spritename$, sprwidth%,sprheight%)

MOVE 50,50

PLOT 21,400,300

RECTANGLE 100,100,200,300

ENDPROC


This sequence of ordinary Basic VDU/PLOT-type graphic commands will (using the default plotting colour of Black) draw a dotted line from the point 50,50 to the point 400,300 on the default (White) background of the blank sprite - and then will draw a rectangle of width 200 and height 300 with its bottom left corner at 100,100. All measurements in OS units.


The result would be a sprite looking something like this (assuming the chosen size of the sprite was large enough to show all the graphics drawn here):



There would not be much point in producing a sprite for this trivial graphic and its use is merely to show the principles involved.


For greater choice Elixir_03 includes two other wimp-functions solely for use within PROCuser_spritegraphics().


The first is:

PROCwimp_setdrawspritegraphiccolour(colour%)

whose role is just to set the foreground colour of the subsequent graphic commands.


The second is:

PROCwimp_writedrawspritetext(text$,fonth%,spritex%,spritey%, foreground%,background%)

which is somewhat more comprehensive and plots user-chosen text in an outline font in anti-aliased colours starting at a chosen point in the sprite. The font handle must have already been declared in the usual Dr Wimp way.



If, in the same application, you wish to construct more than one sprite in this manner then each must be created with a single call to FNwimp_buildsprite(). In addition, DEFFNuser_spritegraphics() needs to hold the graphic/text drawing commands for all the sprites - which is simple to arrange by using their sprite area and/or sprite names (passed in spritearea% and spritename$) to differentiate between the needs of each one.



Should you need to change the contents of the sprite after its initial creation in this way, it is again easy to do so, by calling PROCwimp_plotinsprite() independently yourself at an appropriate place - and ensuring that there are appropriate coding and constructs within DEFFNuser_spritegraphics() to respond accordingly.


(This is why PROCwimp_plotinsprite() has been made a separate wimp-function in this Elixir. Dont forget that it is called once automatically by FNwimp_buildsprite() to enable the initial sprite contents to be drawn. Thereafter, you may call it independently whenever you wish to change the contents. Just ensure that FNuser_spritegraphics() contains the code to cope!)


The Example application !BuildSpr shows how to call PROCwimp_plotinsprite() independently in order to change a sprite contents.



If you wish to change the sprite contents completely, it helps to precede the new graphics/text plotting with the sequence:


PROCwimp_setdrawspritegraphiccolour(0):REM White **

RECTANGLE FILL 0,0,sprwidth%,sprheight%:REM Whole sprite rectangle **


which will effectively wipe the sprite canvas clean, ready for your new plotting commands.



Finally, if you wish to save a sprite constructed using this Elixir then you can do so with PROCwimp_savesprites() - simply by using the sprite area handle returned by FNwimp_buildsprite(). This will save the sprite in a conventional sprite-file.



Elixir_04 - User-defined drag boxes

This Elixir takes advantage of the comprehensive facilities already provided in Dr Wimp for icon-dragging and contains just one wimp-function and one user-function:


PROCwimp_startuserdragbox(window%,button%,mouseworkx%, mouseworky%)


PROCuser_definedragbox(startwindow%,dragbutton%, startmouseworkx%,startmouseworky%,RETURN userboxminx%, RETURN userboxminy%,RETURN userboxmaxx%, RETURNuserboxmaxy%)



Calling PROCwimp_startuserdragbox() - normally within PROCuser_mouseclick() in order to capture the current mouse position - is all that is necessary to start the drag action. window% is the window in which the drag is to start; button% is set to 4 (<select>) or 1 (<adjust>) depending on which button you want to effect the drag and mouseworkx%/mouseworky% are the starting mouse positions - in work OS units.


This wimp-function automatically calls PROCuser_definedragbox() and this is where the user defines the size and position of the drag-box. In this user-function startwindow%, dragbutton%, startmouseworkx%, startmouseworky% are self-explanatory and allow the programmer to set the starting conditions fairly comprehensively.

The four parameters userboxminx%, userboxminy%, userboxmaxx% and userboxmaxy% are all RETURN parameters - which means that the programmer can set them to the drag-box size required (different sizes under different conditions, if required). By default i.e. if the programmer leaves PROCuser_definedragbox() untouched, a drag-box of just 32 OS units - centred on the mouse position - is generated, just to show that things are working correctly. When you set your own values here, they all need to be in work OS units.


Once the drag-box has been defined the three standard user-functions used for icon-dragging come into play - but, in them, the value of dragicon% will now always be -1, to signify that no icon is involved. This provides one of the main factors used to filter the action. Thus:


PROCuser_seticondragbounds() is now used to limit (in screen units) the dragging area of the user-defined drag-box. As for icon-dragging, the default is the visible area of the window in which the drag is started.


PROCuser_draggingicon() and PROCuser_endicondrag() are used, as required, to take actions during and/or at the end of dragging.


The only point needing care is to note that work OS units are used in some functions and screen OS units in others.


The Example application !Scroll has been extended to show Elixir_04 working in practice.



Elixir_05 - Managing nudger/bump icons

This Elixir is a little different to others in the series in that it merely offers optional wimp-functions for a common need - that of managing nudger or bump icons. (The Acorn Style Guide calls these adjuster arrows.)

A typical arrangement of nudger icons is shown in the following screenshot:



For the purposes of this Elixir, the white icon with 100 in it will be called the value icon and the two nudgers to its right will be called the down iconand up icon respectively.


You will no doubt be familiar with the operation: clicking once with <select> on the down icon will cause the value icon to decrease in value and  clicking once with <select> on the up icon will cause the value icon to increase in value. If the clicking is done with the <adjust> button the actions are reversed.


The Elixir currently offers two independent wimp-functions - both intending to be used within DEFPROCuser_mouseclick.


The first is:

PROCwimp_nudgeinteger(window%,icon%,downicon%,upicon%, valueicon%,increment%,lowvalue%,highvalue%)


which is designed specifically to manage integer numbers in a simple way. It is best expalined by example. A typical use might be:


(Assume that the icon number of the value icon is 10, the downicon is 6 and the up icon is 22.)


DEF PROCuser_mouseclick(window%,icon%,button%,workx%,worky%)

CASE window% OF

WHEN main%

    CASE icon% OF

    WHEN 6,22

        PROCwimp_nudgeinteger(window%,icon%,6,22,10,1,-5,5)

    ENDCASE

ENDCASE

ENDPROC


This would increment/decrement the contents of the value icon by 1, between the limits of -5 and +5.



The second wimp-function is:


PROCwimp_nudgereal(window%,icon%,downicon%,upicon%,valueicon%, increment,shiftincrement,lowvalue,highvalue,decplaces%)


which offers more functionality and also accepts real numbers. It is called in exactly the same way as its more simple counterpart above, except that there are now two increment values to supply and the extra parameter decplaces%.


The value placed in the parameter increment is the real number increment/decrement which is applied when the user clicks on the nudger icons with either <select> or <adjust> - whereas shiftincrement is the real number increment/decrement applied when the user clicks on the nudger icons with either <select> or <adjust> with the <shift> key held down.


As real numbers are involved it is important to control the format of the results placed in the value icon and the parameter decplaces% specifies the format.


A typical call might then be:


PROCwimp_nudgereal(window%,icon%,6,22,10,1,0.1,-5,5,1)


Here, the normal increment/decrement is 1 - but this changes to 0.1 if the <shift> key is held down whilst the <select> or <adjust> mouse button is clicked. Again, the value can range between -5 and +5.


(If there is interest, other nudger management options could be added to this Elixir in the future.)


Elixir_06 - Saving/retrieving window positions

Many applications offer the user the option of customising window positions so that, for instance, a window (or windows) always opens at a user-chosen position (and sometimes also visible size/scrolls).

In addition, the programmer often has a need to ensure that large windows do not open off the screen if the user happens to be operating in a smaller screen-mode - or on a mode change whilst the application is running..

This Elixir offers a solution to these issues, with the complementary pair of wimp-functions:


PROCwimp_savewindowsettings(window%,windowname$,savedir$)

PROCwimp_getandsetwindowsettings(window%,windowname$,savedir$, hide%,warning%)


The first of these saves a text file containing the current on-screen position, visible size and scroll values of the window whose handle is window%. This window must be already loaded/created in the application, but it does not need to be open when this call is made.

The programmer needs also to specify a name string for this window in windowname$ - and it is suggested that a string version of the window handle variable is used (e.g.  if the window handle variable is main%, use main for windowname$). This name will be used as the saved files leafname - but with the prefix W added i.e. Wmain will be the leaf name in the above example.

The third parameter savedir$ also needs to be set, but if the programmer sets it as a null string the function will automatically save the file in <Choices$Write> within a sub-directory with the same name as the programmer has used in the first parameter of FNwimp_initialise() i.e. the application name. For example if the application name is MyApp then the file will be saved to the sub-directory <Choices$Write>.MyApp.

Thus, in this example, the complete saved file path will be <Choices$Write>.MyApp.Wmain.

However, there is nothing to stop the programmer from specifying any other directory in savedir$ instead. If this is done, a trailing . must not be included.


The saved file will be a text-file. This is a deliberate choice to make it easy to edit or, indeed, to create off-line. The format of the file is simply a set of numbers in string form and is best shown with a typical example:


354

452

600

800

0

-10

(remember to ensure that there is a <return> after the last entry):


These numbers represent, respectively:


Screen position of LH edge of window in OS units

Screen position of Bottom edge of window in OS units

Screen position of RH edge of window in OS units

Screen position of Top edge of window in OS units

Amount of x-scroll in OS units

Amount of y-scroll in OS units (normally a negative value, if not 0)



Having saved such a file, the other half of the process is to retrieve the saved values and use them to set the window state accordingly. This is done with the second wimp-function:


PROCwimp_getandsetwindowsettings(window%,windowname$,savedir$, hide%,warning%)


The first three parameters match those in the saving wimp-function described above. Obviously it is vital that you match the parameters exactly - and, again, the window must be already loaded in the application. If the file cannot be found nothing will happen - but you can choose to to get a warning of this by setting warning% to any value other than 0.

The parameter hide% enables the window to be altered to reflect the file settings without opening it. If hide% is set to 0 then the window will be opened after its state has been changed. But if hide% is set to 1 the windows state is altered invisibly. A typical use would be to make the call with hide% set to 1 during application initiation, immediately after loading the window. This will change the window state behind the scenes so that when subsequent user action calls for the window to be opened it will do so in its changed state - as required.


As a saved file in the right format can easily be created in a text editor, one practical idea is to create more than one file for a particular window with the intention of matching each file with a particular screen mode - which could be checked during application initiation using FNwimp_getscreenres(). The window could then be set up to correspond to the screen mode.


By the same token, windows can be re-sized automatically if the screen mode is changed whilst the application is running. The key to doing this is to use PROCuser_modechange() to set a flag to TRUE when the mode is changed and then use this flag in PROCuser_openwindow() to trigger a call to PROCwimp_getandsetwindowsettings().



Elixir_07 - Actions on multiple windows, icons and menu items


Sometimes you need to carry out the same operation on several windows or several icons or several menu items. This small suite of wimp-functions helps with this.


PROCwimp_group(handle%,type%,string$,state%)


This wimp-function allows you to enable/disable/toggle a group of icons in the same window, or to enable/disable/tick/untick a group of menu items in the same menu, or to select/de-select/hide/show a group of icons in the same window.


handle% is the window (or menu) handle.


type% determines the type of action:

type%=1 means a group of icons is to be enabled/disabled/toggled;

type%=2 means a group of menu items is to be enabled/disabled/toggled;

type%=3 means a group of icons is to be selected/de-selected/toggled.

type%=4 means a group of menu items is to be ticked/unticked/toggled;

type%=5 means a group of icons is to be hidden/shown/toggled.

string$ is a comma-separated list of the icon numbers (or menu items) to which the action is to be applied e.g. 6,17,19,1,3. (As can be seen it does not need to be in numerical order.)

Further, a range of consecutive icon numbers (or menu items) can be included. For example, changing the value of string$ to become 6,15-19,1,3 would mean that the icon numbers (or menu items) would be 6,15,16,17,18,19,1,3


state% has the same meaning as in the corresponding wimp-functions in the main DrWimp library. For example:


state%=0 means disable (or de-select, or hide) the icons - or disable (or de-select, or untick) the menu items;

state%=1 means enable (or select, or show) the icons - or enable (or select, or tick) the menu items;

state%=2 means toggle the current state of the icon/menu item.



PROCwimp_groupwindow(string$,type%,centre%,stack%)


This wimp-function allows a group of windows to be opened/closed/redrawn.


string$ is a comma-separated list of window handles: that is, typically in the form:


STR$(handle1%)+,+STR$(handle2%)+,+STR$(handle3%) etc.


type% determines the action:

type%=1 means the group of windows will be opened

type%=2 means the group of windows will be redrawn

type%=3 means the group of windows will be closed


When type%=1 the values of centre% and stack% have the same meaning as in PROCwimp_openwindow(). (When type%=2 or 3 these values are ignored.)



FNwimp_findmenuticksstring(menu%)


FNwimp_findmenuticksnumber(menu%)


This is a pair of wimp-functions which find, for the menu whose handle is menu%, which menu items are currently ticked. Their only difference is in the way they provide the result. If menu items 2, 4 and 5 are currently ticked:


- the first wimp-function returns a comma-separated string 2,4,5.

- the second returns the integer number 52 (binary number %110100 i.e. Bits 2, 4 and 5 set). (Note that Bit 0 is always 0 and is never used.) This wimp-function can only be used with menus which have 31 menu items or less.


Elixir_08 - OLE (Object Linking and Embedding)

(Although its basic use is very simple the OLE Elixir is much larger than other Elixirs and several inter-linked directories are involved in order to give options for a full range of features. For this reason, no mention of this Elixir appears in Section 3 of this Manual and detailed documentation is held separately in the Elixir folder. The following is intended as a simple introduction only.)


OLE is the acronym given to a Wimp process whereby one application can call up another application automatically to do some work for it - and capture the results for its own purposes subsequently.

For instance, if your Dr Wimp application displays drawfiles then, with OLE, you could arrange for the displayed drawfile to be edited by !Draw and the results saved back for display by your application - all controlled within your application. In this case, your Dr Wimp application is called an OLE client and !Draw is called the OLE server.

Similarly, if your Dr Wimp application can edit/process files of a particular file-type then it can be made into an OLE server application, which will start-up and respond to other applications calls for editing of files of that file-type.


Elixir_08 provides facilities to make it very easy to turn your Dr Wimp application into an OLE client and/or an OLE server. Full details of both the client and server processes provided by this Elixir are contained in the comprehensive separate documentation included with the Elixir files - together with a fully-featured example application called !OLETest.


However, it may assist better understanding of the OLE process if an outline introduction is given here, and this is done below by constructing a cut down OLE client called !Ollie. (The finished !Ollie cut down application is included with the !OLETest application.)


Simple client operations

!Ollie will load a drawfile, use OLE to modify it using !Draw and then retrieve the changed drawfile.


Start by finding the completed !Ollie application with the Elixir_08 files and open the folder to locate the CustomTmpl file and the testfiles folder.


Then load Dr Wimps !Fabricate utility application - and in its main window:


a) change the Application Name to !Ollie;

b) tick the option to use a custom window template file and drag in CustomTmpl as located above. Tick the option Iconbar click opens one of these windows and click over the Name of window to open box to select main (the only choice).

c) change the Info window contents as you wish;

d) tick the option to include a standard save window.

(All other settings can be left as default.)

e) Create a new customised skeleton application called !Ollie by clicking the OK button at the top right of !Fabricates main window - and drag the resulting save icon to wherever you wish (but NOT to the Elixir_08 location of the completed !Ollie application!).


With this new skeleton application, the initial programming steps are housekeeping to ensure that the appropriate OLE Elixir functions are available to be brought into play.


The OLE Elixir is quite large and its various functions are split among several interlinked folders. It is therefore safest to keep these folder intact and to adhere strictly to the following procedure for all uses of this Elixir:


1) Display the folder containing !DrWimpOLE. Doing this will make sure !DrWimpOLE and other related folders are seen which will automatically set a key system variable called DrWimpElixirOLE$Dir and a few other related system variables. This simple action makes it unnecessary to move the bulk of the OLE functions to your application. Instead they can be referenced as a Library, using the above system variable. The other related OLE functions will then also be linked automatically.

2) Load the new !RunImage into your editor. Then open the !DrWimpOLE folder and copy the contents of ole-user to the end of your new !Ollies !RunImage listing. These are the few OLE user-functions to which you will, as usual, need access for developing the programming. Re-save the !RunImage.


Also, but only for our cut down example application, copy the previously-located testfiles folder into your new !Ollie application folder (and ensure that the Access attributes will allow both reading and writing to the enclosed drawfile).


Now everything is in place and we can start building on the new !Ollie !RunImage listing.


Add the following line to the new !RunImage after the (Line 20) LIBRARY call to the DrWimp library:


LIBRARY <DrWimpElixirOLE$Dir>.Elixir_ole

This effectively loads the OLE Elixir functions and gives the application access to them.


The next step is to call FNwimp_ole-init() in !Ollies initialisation sequence. The call is made by adding the following line to the current end of DEF PROCuser_initialise() - just before the ENDPROC:


saveblk%=FNwimp_ole_init(appname$,,saveblk%,FALSE,TRUE,TRUE, FALSE)


This call sets up several data blocks etc. for internal use during the OLE process. (It also sets the Dr Wimp special global variable UNUSED% to TRUE - an essential step for Elixir_08 to operate.) The detail of the parameters is available in the separate Elixir_08 documentation and also in Section 3.16 of the Dr Wimp manual, but there is no need to examine it at this introductory stage.


Next, we need to load a drawfile to be used as our OLE testbed. A suitable file is contained in the testfiles folder we previously copied, so we need to add the following sequence to DEFPROCuser_initialise(), just after the above addition:


TestFile$=<Ollie$Dir>.testfiles.DrawFile

Testfilesize%=FNwimp_measurefile(TestFile$,0)

Testoledata%=FNwimp_createdynamic(Testfilesize%, 10*Testfilesize%,0,Ollie)

dummy%=FNwimp_loadfile(TestFile$,Testoledata%,0)

Testfiletype%=&AFF

Testfiletype$=AFF


You will recognise most of these lines as Dr Wimps standard drawfile loading sequence - in this case into a dynamic area which has been given the ability to expand up to 10 times the original file size - an arbitrary expansion capability but more than enough for this example.


(At this point, after saving the augmented !RunImage, it is worth running the new !Ollie just to check that it loads correctly and the normal infrastructure is working.)


We now need a way to kick off the OLE action and this is going to be done with a click on the drawfile icon (icon number 0) which appears in the small main window. We therefore need to make changes to DEF PROCuser_mouseclick() - and suitable new total contents are shown below:


DEF PROCuser_mouseclick(window%,icon%,button%,workx%,worky%)

CASE window% OF

	WHEN iconbar%

	REM** Click iconbar icon to open main window. **

	PROCwimp_openwindow(main%,1,-1)

	WHEN main%

	REM** Start OLE session when Icon 0 is clicked. **

	CASE icon% OF

		WHEN 0

		session_started%=FNwimp_start_ole_session(Testoledata%, 0,,main%,0,0,Testfiletype$,Testfiletype%,1,)

	ENDCASE

ENDCASE

ENDPROC


With this, a click on Icon 0 will call FNwimp_start_ole_session() which passes details of the drawfile loaded earlier plus the window handle etc.


If you now run the application, click on the iconbar and then click on the drawfile icon in the window, you will find that !Draw is started and the !Ollie-loaded drawfile loaded into it and displayed - ready to edit. (Note from the file-name it the !Draw window title-bar that this editable drawfile is held as a Scrap file.)

However, at the moment, any editing cannot be captured back to !Ollie, and that is our final stage.


First, a quick visit to DEF PROCuser_wimpmessage() is needed, into which we need to add:


LOCAL done%

done%=FNwimp_catch_ole_msgs(messagenumber%,block%,reasoncode%)


FNwimp_catch_ole_msgs() is a multi-purpose OLE wimp-function which responds to various OLE wimp-messages. Here, its role is to trigger actions by our application when:


a) OLE has been correctly activated (and !Draw started, if need be);

b) !Draw has modified our file;

c) the OLE session has ended.


Of these, b) is our main current concern because we need to generate code to tell our application what to do to retrieve the modified drawfile - and this is done within DEFPROCuser_ole_file-changed() which is one the ole user-functions copied to the !RunImage earlier.


In this user-function we want to save the amended drawfile back to the Ollie-created dynamic area from whence it came (which might mean increasing the dynamic area size) and also save the same result back to the originating file in the testfiles folder. This is straightforward coding and the modified user-function becomes:


DEF PROCuser_ole_file_changed(filename$,ftype%,session_handle%, whan%,x%,y%,sendertask%,RETURN useroledata%, RETURNoledatasize%)

LOCAL newolefilesize%,dummy%,newTestoledata%

IF whan%=main% THEN

	REM** Measure ole-edited file size. **

	newolefilesize%=FNwimp_measurefile(filename$,0)

	IF newolefilesize%>0 THEN

		IF newolefilesize%>Testfilesize% THEN

			REM** Increase DA if need be. **

			newTestoledata%=FNwimp_changedynamic(Testoledata%,1, newolefilesize%)

			IF newTestoledata%<>0 THEN

				REM** Re-assign variables. **

				Testoledata%=newTestoledata%

				Testfilesize%=FNwimp_measuredynamic(Testoledata%)

				useroledata%=newTestoledata%

				useroledatasize%=Testfilesize%

			ENDIF

		ENDIF

		REM** Re-load ole-edited file into DA. **

		dummy%=FNwimp_loadfile(filename$,Testoledata%,0)

		REM** Re-save ole-edited file as new test file. ** PROCwimp_savefile(TestFile$,Testoledata%,ftype%)

	ENDIF

ENDIF

ENDPROC


You should be able to follow this, with the REMs to help - bearing in mind that the filename and file-type of the edited drawfile (and other potentially useful items) are passed to you by the parameters.


As far as this cut down OLE example is concerned, we have finished. So, save the !RunImage and run the application. When you now start the OLE process, modify the displayed drawfile and carryout an apparently normal Save action on the amended drawfile, you will find that the original version of the drawfile (in your applications testfile folder) will have been altered correspondingly - and the amended version also loaded into the dynamic area ready for further OLE action.


Thus, the basics of using Dr Wimps OLE Elixir are very simple. However, there are several other issues that would need to be done in a fully-featured application - for instance, to allow more than one OLE session (server and/or client) to be active at the same time and to safeguard against conflict with multiple scrap files. To see more on the differences needed it is easiest to compare the !RunImage listings of !Ollie and !OLETest whilst examining the separate detailed documentation for this Elixir.



---------------------------------------------





If you have an idea for an elixir please contact the Dr Wimp author.


The best ideas come from actual users!

37. Final comments

Sections 1 and 2 of this Manual are designed to get you up and running. They do not cover every aspect of using Dr Wimp. Many other features of DrWimp are demonstrated by the examples in the Examples folder. Their !RunImage files are well commented to show what is being done and why.


Section 3, which follows, contains information about every user- and wimp-function available in the Version indicated on the Front Cover of the Manual.


Good programming!


Dont forget: suggestions for future additions, bug reports and help requests are always very welcome, either by E-mail or post.


Also, the latest version of DrWimp can be obtained from the web page below:


	World Wide Web: http://www.rayfavre.me.uk/


which also contains some helpful articles about using Dr Wimp and links to applications written by many Dr Wimp users - as well as details about Ray Favres popular charity books.



or you can get Dr Wimp directly from:


	Email: drwimp@rayfavre.me.uk


	Post: Ray Favre, 26 West Drayton Park Avenue, West Drayton, Middlesex, UB7 7QA, U.K.

		(An SAE would be appreciated.)



 

Section 3. Functions

1. Misc

FNwimp_initialise(name$,wimpmem%,ver%,desktopsave%)

This function registers your application with the Task Manager, reserves some important memory and determines if the application will

give a response to the Wimps desktop save protocol and whether it will pass on unused messages from the Wimps messaging system.

Returns Wimp-assigned task handle.

name$ = the name of your application eg. MyApp.

wimpmem% = number of bytes to reserve for window, icon and menu definitions. (Space for indirected data is allocated automatically.)

ver% = minimum version of RISC OS that the application is allowed to run on, multiplied by 100. (Needs to be at least 360 to use all Dr Wimps facilities.)

If desktopsave% <> 0 then application will respond to Wimps desktop save message.



FNwimp_OStolength(osvalue,scale,inch%)

Converts OS units to mm or inches.

osvalue = OS value to convert, can be integer or floating point.

scale = scaling factor 0-100 (%) can be integer or floating point.

If inch%=0 the value returned is in mm. If inch%=1 the

value returned is in inches.



FNwimp_lengthtoOS(length,scale,inch%)

Converts a length in mm or inches to OS units.

length = value to convert, can be integer or floating point.

scale = scaling factor 0-100 (%) can be integer or floating point.

If inch%=0 the length value supplied is in mm. If inch%=1

the length value supplied is in inches.



FNwimp_getdaydatetime(choice%)

Returns current day/date/time as a string.

If choice%=0, string format is Mon 06 Jun 2005 15:09:37

If choice%=1 (day only) string format is Mon

If choice%=2 (date only) string format is 06 Jun 2005

If choice%=3 (time only) string format is 15:09:37

For each choice the string length/format is always the same as shown.





FNwimp_changecase(string$,upper%)

Converts a string all to upper or lower case characters.

string$ = string to convert

If upper% = 0 then conversion is to lower case

If upper% = 1 then conversion is to upper case

(The conversion only affects the alphabetical characters A-Z and a-z.

All others are left unchanged.)


PROCwimp_error(title$,error$,from%,spritename$,spritearea%,button%,-altbutton$)

Reports an error using an error box with only one action button.

title$ = title of error window. (If title$= then the title will be the application name.)

error$ = error message.

If from%=0 then title has no prefix

If from% = 1 then the title is prefixed by Error from .

If from% = 2 then the title is prefixed by Message from .

spritename$ is name of a user-chosen sprite to be added to error box.

spritearea% is spritearea of above sprite: 1 meaning the wimp-pool.

If button%=1 then the single button will be called Continue.

If button%=2 then  the single button will be called Cancel.

altbutton$ contains, if required, a user-chosen name for the single button. If it is not a null string it will be used irrespective of the button% value.

(See Section 2.8 for details.)



FNwimp_errorchoice(title$,error$,from%,type%,spritename$,spritearea-%,continue%,cancel%,extrabutton$)

Reports an error using an error box with 1 or more action buttons, returning the number of button pressed.

title$ = title of error window. (If title$= then the title will be the application name.)

error$ = error message.

If from%=0 then title has no prefix

If from% = 1 then the title is prefixed by Error from .

If from% = 2 then the title is prefixed by Message from .

If type%=1 then the error box will have an information icon.

If type%=2 then the error box will have an error icon.

If type%=3 then the error box will have a program icon.

If type%=4 then the error box will have a question icon.

spritename$ is name of a user-chosen sprite to be added to error box.

spritearea% is spritearea of above sprite: 1 meaning the wimp-pool.

If continue%=1 then the error box will have a Continue button.

If cancel%=1 then the error box will have a Cancel button.

extrabutton$ allows the error box to have extra/alternative buttons. It should be a null-string if no extra/alternative buttons required, or a comma-separated list of the required button text(s).

Returns the number of the pressed button: 1 is Continue (if present); 2 is Cancel (if present); 3, 4, 5 etc. is one of the other buttons in their order in extrabutton$.

(See Section 2.8 for details.)





FNwimp_testobjectpresent(path$,warning%)

Checks whether a Filer object is present and returns, as a string, its file type.

path$ - full path of object which may be a directory, application or file.

For a file, the return is normally of the form XXX, where &XXX is the filetype. Leading zeros will be added as necessary to bring the return string up to three characters. (But, exceptionally, an untyped file will return the string -1)

For a directory, the return is 1000

For an application, the return is 2000

If the object is not found the return is a null string.

If warning% is not 0, then a warning will be given if the object is not present. There are no fatal errors.


FNwimp_countdirectoryobjects(dir$)

Returns number of objects (i.e. files/applications/directories) in

specified directory.

dir$ - full pathname of directory or application

Returns -1 if object not found.


FNwimp_getdirectoryobjectname(dir$,objectnumber%)

Returns name (as it appears in Filer window) of a specified object (identified by number) in specified directory.

dir$ - full pathname of directory or application

objectnumber% is 1 for first object, 2 for second object, etc.

Objects are read in alphabetical order of name - so names starting

with ! (Ascii 33) will come first.

Returns a null string if object not found.

(Use FNwimp_countdirectoryobjects first to find total number of objects present in directory.)



FNwimp_getdirectoryobjecttype(dir$,objectnumber%)

Returns, as a string, the filetype number of specified object (identified by number) in specified directory. A file will

return upper-case XXX where XXX is the filetype hex number e.g. FFF for textfiles - or 0AF for filetype &af.

A directory will return 1000 and an application 2000.

dir$ - full pathname of directory or application

objectnumber% is 1 for first object, 2 for second object, etc.

Objects are read in alphabetical order of name - so names starting

with ! (Ascii 33) will come first.

Returns a null string if object not found.

(Use FNwimp_countdirectoryobjects first to find total number of objects present in directory.)



FNwimp_getdirectorypath(pathname$)

Returns the pathname with the leafname removed i.e. returns the directory specification string. The trailing fullstop (or trailing colon, if pathname$ is something like Boot:!Help) will be included.

Does not check that removed leafname is actually a file i.e it could be a directory or application.

pathname$ = pathname string.

(If pathname$ does not include at least one . or :  character a null-string will be returned i.e. no leafname is present.)



FNwimp_getleafname(path$)

Returns a string containing the leafname from the pathname.

Does not check that leafname is actually a file i.e it could be a directory or application.

path$ = pathname string.

(If there is no . or : character in path$, then path$ is returned unaltered i.e. path$ was already a leafname.)



PROCwimp_createdirectory(dir$,warning%)

Creates a new, empty directory.

dir$ - full path of required new directory.

If warning% is not 0, then a warning will be given if the directory into which the new directory is to be placed is not present - and if dir$ already exists as a file. There are no fatal errors.



PROCwimp_setfiletypenumber(filepath$,filetype%,warning%)

Sets the filetype of the specified file, using a file-type number.

filepath$ - full pathname of file.

filetype% - required filetype as a number in the range 0-&FFF. If value is outside this range, the file will be given the &FFF filetype i.e. Text.

warning% - if not 0, a warning will be given if the object does not exist or is a directory/application


PROCwimp_setfiletypehexstring(filepath$,filetype$,warning%)

Sets the filetype of the specified file, using a file-type hex string.

filepath$ - full pathname of file.

filetype$ - required filetype as a hex string e.g. &FFF or just FFF. If value is outside the hex range 0-&FFF, the file will be given the &FFF filetype i.e. Text.

warning% - if not 0, a warning will be given if the object does not exist or is a directory/application


FNwimp_getobjecttypenumber(path$,warning%)

Returns - as a number - the file-type of a named Filer object

path$ - full path of object which may be a directory, application or file.

For a file, the return is a number in the range 0-4095 (-1 for an un-typed file). The return is 4096 (&1000) for a directory and 8192 (&2000) for an application.

If the object is not found the return is 0 (Note that there is a potential conflict here if the file-type is 0 - which is a very unlikely occurrence.)

If warning% is not 0, then a warning will be given if the object is not present. There are no fatal errors.


FNwimp_getobjecttypehexstring(path$,warning%)

Returns - as a string - the file-type of a named Filer object.

THIS FUNCTION IS IDENTICAL TO FNwimp_testobjectpresent() and is copied under this different name for user convenience.

path$ - full path of object which may be a directory, application or file.

For a file, the return is normally of the form XXX, where &XXX is the filetype. Leading zeros will be added as necessary to bring the return string up to three characters. (But, exceptionally, an untyped file will return the string -1)

For a directory, the return is 1000

For an application, the return is 2000

If the object is not found the return is a null string.

If warning% is not 0, then a warning will be given if the object is not present. There are no fatal errors.


FNwimp_copyobject(sourcepath$,destinationpath$,deletesource%,new-er%,restamp%,force%,warning%)

Copies/moves directory objects (recursively as necessary) - with options. Returns 0 if action fails for any reason, otherwise returns 1.

sourcepath$ - full pathname of object to be copied/moved. (Can be wildcarded.)

destinationpath$ - full pathname of destination. (Leafname can be wildcarded.)

deletesource%  - if not 0, copied object will be deleted after copying i.e. the object is moved.

newer% - if not 0, overwriting an existing object will only occur if source object is newer.

restamp% - if not 0, copied objects will be given new time-stamp.

force% - if not 0, objects will be copied/moved irrespective of any access locks etc.

warning% - if not 0, a warning will be given if the source object does not exist. There are no fatal errors.


FNwimp_deleteobject(path$,force%,warning%)

Deletes a named Filer object (recursively as necessary) - with options.

Returns 0 if action fails for any reason, otherwise returns 1.

path$ - full pathname of object to be deleted. (Can be wildcarded.)

force% - if not 0, objects will be deleted irrespective of any access locks etc.

warning% - if not 0, a warning will be given if the object does not exist. There are no fatal errors.


FNwimp_renameobject(existingpath$,newpath$,warning%)

Renames a named Filer object.

Returns 0 if action fails for any reason, otherwise returns 1.

existingpath$ - full path of existing object.

newpath$ - required full path of renamed object.

If warning% is not 0, then a warning will be given if the existing object does not exist, or if directory into which the renamed object is to be placed is not present, or if newpath$ already exists as a file. There are no fatal errors.


PROCwimp_doubleclickobject(path$,warning%)

Has same effect as double-clicking on a Filer object i.e. an application will be run; a file will be loaded into its parent application (if the latter has been seen) and a directory will be opened to show ite contents.

path$ = full pathname of object.

warning% - if not 0, a warning will be given if the object does not exist.



PROCwimp_opendirectory(dir$,default%,topx%,topy%,width%,height%,i-consize%,sortby%,warning%)

Opens the Filer window for the specified directory.

dir$ is the full directory path (any trailing dot is ignored).

If default% is not 0 the window opens centred on the screen and with the current default Filer window attributes.

If default% is 0 then the window opens using the values in the following six parameters.

topx%, topy% position of top left corner of window in screen OS units.

width%, height% initial visible size of window in OS units.

If size%=1 the Filer icons will be small.

If size%=2 the Filer icons will be large.

If size%=3 the Filer icons will be small with full information.

If sortby%=1 the icons will be sorted by name.

If sortby%=2 the icons will be sorted by file-type.

If sortby%=3 the icons will be sorted by date.

If sortby%=4 the icons will be sorted by size.

If warning% is not 0 a non-fatal warning will be given if dir$ cannot be found.


PROCwimp_closedirectory(dir$)

Close the Filer window for the specified directory.

dir$ is the full directory path (any trailing dot is ignored).


PROCwimp_sendfiletoprinter(filepath$,delete%)

Sends the named file directly to the currently configured printer.

Has same effect as dragging the file to the printer icon on the iconbar.

filepath$ = full pathname of file.

If delete% is not 0, the file will be deleted after being sent to the printer.

(Also listed under Section 3.12 Printing)






FNwimp_getscreenres(direction%)

Returns the resolution (number of pixels) of the current screen mode

in the specified direction.

If direction%=0 then return is horizontal resolution.

If direction%=1 then return is vertical resolution.


FNwimp_getscreensize(side%)

Returns the required dimension, in OS units, of the full screen in

current mode.

If side% = 0 returns width.

If side% = 1 returns height.


FNwimp_worktoscreen(window%,coord%,side%)

Converts the x or y work area coordinate coord% to an x or y screen

coordinate - in OS units

window% = handle of window whose work area coordinate is being converted.

coord% = coordinate (x or y).

If side% = 0 then coord% is a x coordinate, and an x coordinate is returned.

If side% = 1 then coord% is a y coordinate, and a y coordinate is returned.



FNwimp_screentowork(window%,coord%,side%)

Converts the x or y screen coordinate coord% to a work area x or y coordinate - all in OS units.

window% = handle of window whose work area coordinate is being sought.

coord% = coordinate (x or y).

If side% = 0 then coord% is a x coordinate, and an x coordinate is returned.

If side% = 1 then coord% is a y coordinate, and a y coordinate is returned.


FNwimp_libversion

Returns the version number (100) of the DrWimp library.

Eg. if the version of the library is 3.61 then 361 will be returned.


FNwimp_osversion

Returns the RISCOS version number (100) of the machine being used.

Eg. if the RISC OS version is 4.02 then 402 will be returned.


PROCwimp_setsysvariable(sysvar$,val$)

Sets the value of a system variable.

sysvar$ - name of system variable.

val$ - value to be set - in string form.


PROCwimp_unsetsysvariable(sysvar$)

Unsets (deletes) a system variable.

sysvar$ - name of system variable (case sensitive).


FNwimp_getsysvariable(sysvar$)

Returns, as a string, the contents of the system variable sysvar$.

Note < and > are not required in sysvar$.

sysvar$ is case-sensitive.

If designated system variable is not present a null string is returned.


FNwimp_testsysvariable(sysvar$)

Returns TRUE (-1) if designated system variable is present, or FALSE (0) if not.

Note < and > are not required in sysvar$.

sysvar$ is case-sensitive.

(Note difference from usual Dr Wimp practice of returning 1 or 0)


FNwimp_decplacesnum(number,decplaces%)

Returns, as a real number, the number formatted to the designated

number of decimal places.

number - is the number to format, can be integer or floating point.

decplaces% - is the number of decimal places required.

Rounding is to the nearest i.e. to two decimal places, 1.635 becomes 1.64 and, for negative numbers,  -1.635 becomes -1.64

(N.B. this function can suffer from rounding errors. Use the string

version FNwimp_decplacesstr if possible.)


FNwimp_decplacesstr(number,decplaces%)

Returns, as a string, the number formatted to the designated number of

decimal places.

number - is the number to format, can be integer or floating point.

decplaces% - is the number of decimal places required.

Rounding is to the nearest i.e. to two decimal places, 1.635 becomes 1.64 and, for negative numbers, -1.635 becomes -1.64


FNwimp_roundfloat(float)

Rounds the specified floating point number up or down and returns the

integer.


FNwimp_numtodecstring(number%)

Converts a number in any format to an unsigned decimal integer in string form. The output range is 0 to 4294967295 and there are no leading zeros added.

number%= number to convert.


FNwimp_numtosigneddecstring(number%)

Converts a number in any format to a signed decimal integer in string form. The output range is -2147483648 to 2147483647 and there are no leading zeros added.

number%= number to convert.


FNwimp_numtohexstring(number%,digits%,prefix%)

Converts a number in any format to a hex value in string form.

The output range (i.e. number of hex characters) is determined by the value of digits%, as below.

number%= number to convert.

If digits%=1, output range is 0 to F

If digits%=2, output range is 00 to FF

If digits%=4, output range is 0000 to FFFF

If digits%=6, output range is 000000 to FFFFFF

If digits%=8, output range is 00000000 to FFFFFFFF

(If digits% is set to <1 then digits% will be reset to 1. If digits% is set to >8 then digits% will be reset to 8. If digits% is set to 3, 5 or 7 then digits% will be reset to 4, 6 or 8, respectively.)

For each value of digits% leading zeros are added to keep the result at the shown constant string length.

If prefix% is not 0 the output string is prefixed with the extra character &.

If number% is greater than the maximum value possible for the chosen value of digits% only those bytes needed to do the conversion are used i.e. the least significant bytes of number%.



FNwimp_numtobinstring(number%,digits%,prefix%)

Converts a number in any format to a binary value in string form.

The output range (i.e. number of bits) is determined by the value of digits%, as below.

number%= number to convert.

If digits%=1, output range is 00000000 to 11111111 i.e. 18 bits.

If digits%=2, output range is 28 = 16 bits.

If digits%=3, output range is 38 = 24 bits.

If digits%=4, output range is 48 = 32 bits.

(If digits% is set to <1 then digits% will be reset to 1. If digits% is set to >4 then digits% will be reset to 4.)

For each value of digits% leading zeros are added to keep the result at the shown constant string length.

If prefix% is not 0 the output string is prefixed with the extra character %.

If number% is greater than the maximum value possible for the chosen value of digits% only those bytes needed to do the conversion are used i.e. the least significant bytes of number%





PROCwimp_hourglassoff

Turns off the hourglass.


PROCwimp_hourglasson

Turns on the hourglass.



PROCwimp_hourglasspercentage(percentage%)

Sets the percentage display on the hourglass. (If there are nested PROCwimp_hourglasson calls in operation when this call is made then the percentage value can only be further changed from  the same nesting level.)

percentage% needs to be in the range 0 to 99. If the value is outside that range the percentage display is switched off.






PROCwimp_bar(window%,icon%,length%,dir%)

Sets/adjusts the length of a bar - in OS units.

window% = handle of window containing the bar.

icon% = icon number of the bar.

length% = length of the bar in OS units.

If dir% = 0 then the bar moves horizontally keeping the height constant.

If dir% = 1 then the bar moves vertically keeping the width constant.



PROCwimp_increaseslot(bytes%)

Increases size of wimpslot by bytes% bytes. If not

enough available RAM then creates an error.



PROCwimp_quit(type%)

Used to initiate quitting action and also to re-start a wimp shutdown that has been temporarily stopped.

If type%=0 an application quit will be initiated.

If type%=1 a temporarily halted shutdown will be re-started.

In both cases, FNuser_quit() will be called with type% passed to it.

(See Section 2.27 of Manual for details.)



PROCwimp_pause(seconds)

Introduces a pause into the processing.

seconds = required pause, in seconds. Can be any real positive value.



PROCwimp_setcolour(red%,green%,blue%,background%)

Sets the current GCOL colour (for foreground or background) to the nearest possible for the current mode.

red% = amount of red in range 0-255.

green% = amount of green in range 0-255.

blue% = amount of blue in range 0-255.

If background%=0 then the foreground colour will be set, otherwise the background colour will be set.

(Best used immediately before corresponding plotting/printing action - see Section 2.33 Graphics colours.)





FNwimp_istaskrunning(taskname$)

Checks whether a task (i.e. an application, module etc.) is already running on the Wimp and returns TRUE or FALSE accordingly.

taskname$ is the name of the task - which must be exactly the same as that used by the task in the Task Display.

(For an application the task name is often, but not always, the application name without the leading !. For an application authored using Dr Wimp, the name of the task will be the the string passed in the first parameter of the FNwimp_initialise call.)


PROCwimp_starttask(command$)

Sends command$ to the CLI. Omit *.



FNwimp_measurefile(filepath$,warning%)

Returns the size in bytes needed to store a file in memory prior to using FNwimp_loadfile(), FNwimp_loaddfile(), FNwimp_loadsprites() or FNwimp_loadjpegfile().

Returns -1 if filepath$ not found.

Always use this as opposed to any other form of measurement.

filepath$ = full pathname of spritefile.

warning% - if not 0, a non-fatal warning will be given if filepath$ cannot be found.

(This function is also listed in in other sections)


FNwimp_loadfile(filepath$,handle%,warning%)

General file loader. Loads a file into a block of memory at handle%.

Returns address (handle) at which to load the next file (if any) into the same memory block. (If filepath$ cannot be found the return will be the value of handle% i.e. memory not used.)

filepath$ = full pathname of file.

warning% - if not 0, a non-fatal warning will be given if filepath$ cannot be found.

Memory must have been created after using FNwimp_measurefile to find necessary size.

(Not to be used for spritefiles/drawfiles/JPEGfiles which have their own equivalent wimp-functions.)



PROCwimp_savefile(savepath$,filehandle%,ftype%)

General file saver. Saves a file stored in a memory block into a normal Filer file. (Not to be used for sprites.)

(File in block must have been loaded using FNwimp_loadfile).

filehandle% = handle of stored file to save.

savepath$ = full pathname to save to.

ftype%=filetype required - as hex number e.g. &fff for textfile.



FNwimp_createstringblock(items%,length%,da%)

Creates a block for storing strings in. Returns a handle

to the block. (Load/read block using PROCwimp_putinstringblock and FNwimp_getfromstringblock only.)

items% = maximum number of strings to store.

length% = maximum possible length of each string.

da%=0 means create the block with DIM, otherwise create as a dynamic area.



PROCwimp_putinstringblock(block%,string$,pos%.error%)

Stores a string in a block. (The block must have been created using FNwimp_createstringblock).

block% = handle of block.

string$ = string to store.

pos% = position to store string in (ranging from 1 to maximum number of strings as passed to FNwimp_createstringblock).

error% determines action taken if pos% is outside valid range - see Manual Section 2.33

(Strings stored in this way can be read with FNwimp_getfromstringblock)


FNwimp_getfromstringblock(block%,pos%,error%)

Returns a string stored in a block by PROCwimp_putinstringblock.

block% = handle of block.

pos% = position of string in block (ranging from 1 to

maximum as passed to FNwimp_createblock).

error% determines action taken if pos% is outside valid range - see Manual Section 2.33


PROCwimp_setstringblock(block%,string$)

Sets all elements of a string block (created with FNwimp_createstringblock) to the same string value.

block% = handle of block.

string$ = string to put into each element.



FNwimp_createintegerblock(items%,da%)

Creates a block for storing integers in. Returns a handle

to the block. (Load/read block using PROCwimp_putinintegerblock and FNwimp_getfromintegerblock only.)

items% = maximum number of integers to store.

da%=0 means create the block with DIM, otherwise create as a dynamic area.



PROCwimp_putinintegerblock(block%,integer%,pos%.error%)

Stores an integer in a block. (The block must have been created using FNwimp_createintegerblock).

block% = handle of block.

integer% = integer to store.

pos% = position to store integer in (ranging from 1 to maximum number of integers as passed to FNwimp_createintegerblock).

error% determines action taken if pos% is outside valid range - see Manual Section 2.33

(Integers stored in this way can be read with FNwimp_getfromintegerblock)



FNwimp_getfromintegerblock(block%,pos%,error%)

Returns a integer stored in a block by PROCwimp_putinintegerblock.

block% = handle of block.

pos% = position of integer in block (ranging from 1 to

maximum as passed to FNwimp_createblock).

error% determines action taken if pos% is outside valid range - see Manual Section 2.33


PROCwimp_setintegerblock(block%,integer%)

Sets all elements of an integer block (created with FNwimp_createintegerblock) to the same integer value.

block% = handle of block.

integer% = integer value to put into each element.



PROCwimp_plotwindowline(window%,point1x%,point1y%,point2x%,poi-nt2y%,type%)

Plots a straight line within a window. (Intended to be used within PROCuser_redraw)

window%=handle of window to plot in.

point1x%, point1y% = work area OS coordinates of one end of required line.

point2x%, point2y% = work area OS coordinates of the other end.

If type% = 0 then a full line is drawn.

If type%= 1 then a dotted line is drawn.



PROCwimp_plotwindowrectangle(window%,bottomleftx%,bottomlefty%,-width%,height%,fill%)

Plots a rectangle within a window. (Intended to be used within PROCuser_redraw)

window%=handle of window to plot in.

bottomleftx%, bottomlefty% = work area OS coordinates of bottomleft corner of required rectangle.

width%, height% = width and height of rectangle in OS units.

If fill% = 1 then rectangle is filled.

If fill%= 0 then rectangle is an outline only.



PROCwimp_plotwindowcircle(window%,centrex%,centrey%,radius%,fill-%)

Plots a circle within a window. (Intended to be used within PROCuser_redraw)

window%=handle of window to plot in.

centrex%, centrey% = work area OS coordinates of centre of required circle.

radius% = radius of circle in OS units.

If fill% = 1 then circle is filled.

If fill%= 0 then circle is an outline only.



PROCwimp_plotwindowellipse(window%,centrex%,centrey%,semimajor-%,semiminor%,rotatedegrees,fill%)

Plots an ellipse within a window. (Intended to be used within PROCuser_redraw)

window%=handle of window to plot in.

centrex%, centrey% = work area OS coordinates of centre of required ellipse.

semimajor% = half-length of major axis in OS units.

semiminor% = half-length of minor axis in OS units.

rotatedegrees = angle of rotation of ellipse about its centre, in degrees.

If fill% = 1 then ellipse is filled.

If fill%= 0 then ellipse is an outline only.



PROCwimp_plotwindowtriangle(window%,point1x%,point1y%,point2x%-,point2y%,point3x%,point3y%,fill%)

Plots a triangle within a window. (Intended to be used within PROCuser_redraw)

window%=handle of window to plot in.

point1x%, point1y% etc. = work area OS coordinates of the three vertices of the required triangle.

If fill% = 1 then triangle is filled.

If fill%= 0 then triangle is an outline only.


FNwimp_getfreeRAM

Returns the number of bytes of free RAM available.



PROCwimp_startuserdragbox()

NOT IN DrWimp LIBRARY.

ONLY USED AS PART OF Elixir_04 for user-defined drag-boxes - see Manual Section 2.36 and 3.16.

Starts dragging of user-defined drag-box. (Intended to be used within PROCuser_mouseclick().)


2. Polling

PROCwimp_poll

This function normally provides the main loop of your application, repeatedly polling the Wimp.

During the loop operation, whenever an event occurs involving your

application eg. an icon has been clicked on, then the Wimp will inform the application via Reason Codes and your programming of the user-functions will determine the action the application takes.

If NULL%=TRUE then PROCuser_null will be called each time a null-event occurs e.g. more or less continuously.


PROCwimp_pollidle(duration,sec%)

Similar to PROCwimp_poll and can be used as an applications main loop. Its difference is that, unless a non-null event occurs, the Wimp is polled at an interval set by duration.

If NULL%=TRUE then PROCuser_null will be polled at each interval.

If sec%=0 then the duration value is interpreted as centiseconds.

If sec%=1 then the duration value is interpreted as seconds.

(duration can be any real positive number.)


PROCwimp_singlepoll

The same as PROCwimp_poll, except that the Wimp is polled once only and not in a loop. Usually called within the main Wimp poll loop.

If NULL%=TRUE then PROCuser_null will be called once.

Note however, that if this function is called within PROCuser_null, make sure NULL%=FALSE before the call is made (can be set to TRUE afterwards) otherwise recursion will occur.


PROCwimp_singlepollidle(duration,sec%)

The same as PROCwimp_pollidle, except that the Wimp is polled

once after an interval and not in a loop. Usually called within the main Wimp poll loop.

If NULL%=TRUE then PROCuser_null will be called once only after

the period set in duration.

If sec%=0 then the duration value is interpreted as centiseconds.

If sec%=1 then the duration value is interpreted as seconds.

(duration can be any real positive number.)

Note however, that if this function is called within PROCuser_null, make sure NULL%=FALSE before the call is made (can be set to TRUE afterwards) otherwise recursion will occur.



3. User

PROCuser_error

A general function providing a convenient location for application-specific good housekeeping actions which may be desirable when a fatal error occurs. This procedure might typically be used to close any open files, unset system variables, etc.

It is called only when the global error trap is brought into play - see Section 2.8



PROCuser_initialise

A general function providing a convenient location for initialisation actions. This procedure should typically contain the following:

Window and menu loading/definition; declaration of global variables;

DIMming of arrays & data blocks; anything that needs to be done before polling starts.


FNuser_quit(type%)

Called when the application is being asked to quit, either due to the user choosing to quit the application or because of a desktop shutdown.

If type%=0 then it is an application quit.

If type%=1 then it is a shutdown.

Return a 1 to continue with the quit/shutdown or return a 0 to stop it e.g. to allow the user to save any data.

(See Section 2.27 of Manual for details.)


PROCuser_redraw(window%,minx%,miny%,maxx%,maxy%,printing%,p-age%)

When this function is called, the Wimp wants you to update/redraw the specified box (at least).

The box is in the window whose handle is window% or, if printing, then it is in paper coordinates with the origin is at the bottom left of the paper.

printing% = TRUE if currently printing, FALSE otherwise.

page% = number of page currently being printed if printing%=TRUE.

minx%,miny% = bottom left co-ordinates of box in screen/paper coordinates.

maxx%,maxy% = top right co-ordinates of box in screen/paper coordinates.


FNuser_menu(window%,icon%,screenx%,screeny%)

Responds to <menu> clicks. If you want a menu to be displayed when you press <menu> over a specified window/icon or particular mouse pointer position, then this function needs to return the handle of the menu required. Otherwise return 0.

window% = handle of window.

icon% = number of icon.

screenx%, screeny% give the mouse pointer position in screen OS units.

(<select> and <adjust> clicks handled by PROCuser_mouseclick)


PROCuser_mouseclick(window%,icon%,button%,workx%,worky%)

If <select> or <adjust> has been clicked in one of your windows then this function is called. (<menu> clicks handled by FNuser_menu)

window% = handle of window clicked over.

icon% = number of the icon clicked on (or -1 if no icon).

button% = which mouse button was pressed.

Eg. 4 for <select>, 1 for <adjust>.

workx%,worky% = work area coordinates of pointer (in window%)

when the mouse button was clicked.


PROCuser_openwindow(window%,x%,y%,stack%)

If this function is called, then the window whose handle is window% has been opened with the top left of the window at x%,y% on the screen.

stack% = window handle which window% was opened behind,

or -1 for top of window stack, or -2 for bottom.


FNuser_preclosewindow(window%)

This function is called just before the window whose handle is window% is about to be closed.

Return a 1 (default value) to allow the closing action to continue, or return 0 to stop the window closing.


PROCuser_closewindow(window%)

If this function is called, then the window whose handle is window%

has just been closed.


FNuser_keypress(window%,icon%,key%)

If a key is pressed while one of your windows has the input focus, or a hotkey is pressed, then this function is called (provided icon validation string is suitably defined).

If you dont use the key press then return a 0. If you do then return a 1.

window% = handle of window with input focus.

icon% = number of icon with caret.

key% = key code. For most keys it is the ASCII number.

(See Section 2.4 of the Manual for codes of special keys - and Section 2.28 for validation strings.)


PROCuser_menuselection(menu%,item%,font$)

This function is called when the user has chosen a menu item from a menu/sub-menu.

menu% = handle of menu/sub-menu. (Will be the font menu handle if selection is from a font menu/font sub-menu.)

item% = item number (top item is 1). (Will be 0 if selection is from a font menu.)

font$=full period-separated font name.  (Will be null string except if selection is from a font menu.)



FNuser_savefiletype(window%)

Used to identify Save windows. If the window is a Save window then you return the required filetype (as  hex string. eg. FFF for a textfile). Otherwise return a null string.

window% = handle of window%


PROCuser_saveicon(window%,RETURN drag%,RETURN write%,RETURN ok%)

This function allows the three save window icons (the one to drag, the writable icon for the filename/pathname and the OK button) to have

their icon numbers set, if you want to override the defaults.

Defaults:

  drag% - 0   write% - 1   ok% - 2

window% = handle of save window.


FNuser_savedata(path$,window%)

Used to save/export data from an application.

Return a 1 if some data was saved, 2 if an error occurred or return a

0 for no data saved and no error.

path$ = full pathname of file to save data to i.e. destination file.

(Note that this must be a complete file path, not a directory.

Leafname is usually in save window writable icon.)

window% = handle of save window that file icon was dragged from.



FNuser_help(window%,icon%)

Used to return a string for interactive help when the mouse pointer is over the specified window and icon. Otherwise return a null string.

window% = handle of window (containing icon).

icon% = number of icon.

Note: the maximum allowable length of the returned string is 235 characters.


FNuser_menuhelp(menu%,item%)

Used to return a string for interactive help when the mouse pointer is over the specified menu and item. Otherwise return a null string.

menu% = handle of menu.

item% = number of item (starting from 1 at the top).

Note: the maximum allowable length of the returned string is 235 characters.



PROCuser_enteringwindow(window%)

This function is called when the pointer enters a window.

window% = handle of window.



PROCuser_leavingwindow(window%)

This function is called when the pointer leaves a window.

window% = handle of window.


FNuser_pane(window%)

If the window has a pane attached to it, then this function should

return the window handle of the pane. If the window doesnt have a

pane attached, then it should return -1.

window% = handle of window.

(See Section 2.6 for use with multiple panes.)



FNuser_loaddata(path$,window%,icon%,filetype$,workx%,worky%)

Used to load data into application. Important to return a 1 if data is loaded.

path$ = full pathname of source file offered for loading.

window% = handle of window file has been dragged to. (Will be 0 if file double-clicked rather than dragged.)

icon% = number of icon file was dragged on to. (Will be -1 if file double-clicked rather than dragged.)

filetype$ = filetype of file offered for loading. Will always be at least three characters e.g. FFF or 0AF (or 1000 if a directory, or 2000 if an application)

workx%, worky% = work area coordinates the icon was dropped at (these values are both -1 if file was loaded with a double-click rather than dragged).


PROCuser_null

This is called continuously if you set NULL%=TRUE.

So, if you are writing something like a clock, you would monitor the time here and change any windows as required.


PROCuser_menuopen(menu%,window%,icon%)

Called just before menu (not a sub-menu) is opened.

menu% = handle of menu just about to open.

window%=window which pointer is over (or -1 if not over a window).

icon% = icon which pointer is over (or -1 if not over an icon).


PROCuser_overmenuarrow(rootmenu%,rootmenuitem%,RETURN nextsubmenu%,nextsubmenunumber%,parentmenuitem%,x%,y%)

Called when pointer moves over arrow-head against a menu item,

on the way to opening a sub-menu.

rootmenu%=handle of root menu of current menu tree.

rootmenuitem%=currently selected menu item in root menu.

nextsubmenu% = handle of submenu (or could be window) about

to be opened.

(Note: RETURN means that submenu handle can be changed here, if required.)

nextsubmenunumber%=position of next sub-menu in tree i.e. first sub-menu is 1, second sub-menu is 2, etc.

parentmenuitem% = menu item number which pointer is currently moving over. (Will be same as rootmenuitem% for first sub-menu.)

x%/y% are screen OS-unit positions of pointer when over

arrow-head.


PROCuser_modechange

Called when the mode is about to be changed, but prior to the change taking place.

On mode change all open windows are re-opened, so this function is used only to set flags - which are then typically responded to in PROCwimp_openwindow().



FNuser_slider(window%,icon%)

In order to let DrWimp know that an icon is part of a slider/sliderback pair, return the slider icon number. Otherwise return -1.

window% = handle of window with slider pair in.

icon% = icon number of slider back icon.

(Always used with FNuser_sliderback as a complementary pair.)



FNuser_sliderback(window%,icon%)

In order to let DrWimp know that an icon is part of a slider/sliderback pair, return the slider-back icon number. Otherwise return -1.

window% = handle of window with slider pair in.

icon% = icon number of slider.

(Always used with FNuser_slider as a complementary pair.)




PROCuser_slidervalue(window%,slider%,pcent%,direction%)

When a slider is being dragged or has just finished being dragged, the percentage of the slider is passed to this function.

window% = handle of window with slider in.

icon% = icon number of slider.

pcent% = percentage of slider.

direction% = direction of slider (0 is horizontal, 1 is vertical)



PROCuser_declarefonts

Any fonts being used in printing must be declared in this function using PROCwimp_declarefont, PROCwimp_declarefonth and/or PROCwimp_declaredfilefonts.

(This is in case the application is used with a PostScript type

printer, which requires font declarations.)



PROCuser_print(minx%,miny%,maxx%,maxy%,page%)

Called to draw a page for printing, if PROCwimp_print was

called with user%=1.

minx%,miny% = coordinates of bottom left corner of clipping rectangle

on page in paper coordinates.

maxx%,maxy% = coordinates of top right corner of clipping rectangle on page in paper coordinates.

page% = number of page to print.


FNuser_printing(copy%,page%,totpages%,pagepos%)

Called repeatedly by DrWimp during printing so application can keep user informed of current printing status and give the option to cancel printing.

copy% = number of current copy being printed.

page% = number of current page being printed.

totpages% = total number of pages being printed.

pagepos% = current page being printed (starts at 1 each time and goes up to totpages%).

Return a 1 to cancel printing or a 0 to continue.



PROCuser_printerchange

Called when the printer settings or the current printer has changed so you can update your page measurements, current printer name, etc.


PROCuser_colourpickerrgb(red%,green%,blue%,none%)

When the colour picker window is used to select a colour (by pressing OK or None) the rgb values of the currently displayed colour are passed to this function. Requires RISCOS Version 3.50 or higher.

red% = red component of colour, in range 0-255.

green% = green component of colour, in range 0-255.

blue% = blue component of colour, in range 0-255.

If none%=0, OK was pressed in colour picker window i.e. displayed colour was selected.

If none%=1, None was pressed in colour picker window i.e. no colour selection was made.

(Note: Colour values are still passed when None is pressed.)



PROCuser_colourpickermodel(model%,value1,value2,value3,value4,non-e%)

When the colour picker window is used to select a colour (by pressing OK or None) the colour model values of the currently displayed colour are passed to this function. Requires RISCOS Version 3.50 or higher.

model%=colour model number. 0 is RGB model, 1 is CMYK model, 2 is HSV model.

value1, value2 etc. are colour component values appropriate to the model, in range 0-100% (except value1 is in range 0-359 degrees for HSV model i.e. when model%=2)

Note that value4 is only relevant for CMYK model i.e. when model%=1. In other cases value4 will be -1.

If none%=0, OK was pressed in colour picker window i.e. displayed colour was selected.

If none%=1, None was pressed in colour picker window i.e. no colour selection was made.

(Note: Colour values are still passed when None is pressed.)



PROCuser_wimpmessage(messagenumber%,block%,reasoncode%)

Dr Wimp does not use all wimp-messages. This user-function allows details of those unused wimp-messages to be passed to the !RunImage, if required.

If the global variable UNUSED% is set to TRUE then this user-function will be called whenever a wimp-message is received by the application but is not used within the DrWimp library. (UNUSED% is set to FALSE by default on application start-up.)

messagenumber% = number of the unused wimp-message received.

block%= handle of wimp-message data block, to enable user to get further information and respond if necessary.

reasoncode%= reason code passed by wimp (17, 18 or 19 in this case).

(See Section 2.30 of Manual for the list of wimp-messages that are currently used within the DrWimp library - and hence would never be passed on via this user-function.)



PROCuser_iconise(window%,RETURN text$,RETURN spritename$)

This function is called when iconising action takes place. It allows the text and/or sprite used to be customised.

window% = handle of the window where the iconising action has occurred.

text$ = text to appear beneath the iconised sprite.

spritename$ = name of the sprite to be used, without the ic_ prefix. A sprite with the full name needs to be supplied in the !Sprites/!Sprites22 files - otherwise the Wimps default sprite will be displayed.

(By default, spritename$ will be set to the application name as declared in FNwimp_initialise and text$ will be set to the title of the window being iconised. But if there is no title or the title includes the word untitled then the application name will be used as default.)

N.B. If spritename$ exceeds 7 characters it will produce an invalid iconiser sprite name - and hence the Wimps default iconiser sprite will be displayed instead.



FNuser_dragicon(window%,icon%,button%)

Used to specify which (draggable) icons are to be dragged and/or the circumstances under which they can be dragged. (See Section 2.25)

Return 1 when dragging of icon required, otherwise return 0.

window% = handle of window containing icon.

icon% = icon number of (draggable) icon.

button% =  button being used for dragging i.e. 4 for <select-drag> or 1 for <adjust-drag>

(Note: This user-function will only be activated by icons which have a button type which is draggable.)



PROCuser_seticondragbounds(startwindow%,dragicon%,dragbutton%,-startmousex%,startmousey%,RETURN boundsminx%,RETURN boundsminy%,RETURN boundsmaxx%,RETURN boundsmaxy%)

This function is called when a draggable icon (or user-defined drag-box) is about to be dragged. It allows the drag boundaries to be set.

(If this user-function is left empty, the drag boundaries will be set automatically to confine the dragged icon to the visible window that it starts in.)

startwindow% - handle of window in which the dragged icon (or user-defined drag-box) starts.

dragicon% - handle of dragged icon. (Will be -1 when used with user-defined drag-box)

dragbutton% - button being used for dragging i.e. 4 for <select-drag> or 1 for <adjust-drag>

startmousex%, startmousey% - screen OS coords of mouse pointer at start of drag.

boundsminx%, boundsminy%, boundsmaxx%, boundsmaxy% - screen OS coords of rectangle within which icon (or user-defined drag-box) can be dragged.

(Default values are limits of visible window in which drag starts - see above.)



PROCuser_draggingicon(startwindow%,dragicon%,dragbutton%,startm-ousex%,startmousey%,mousex%,mousey%,overwindow%,overicon%,dr-agboxminx%,dragboxminy%,dragboxmaxx%,dragboxmaxy%)

This function is called repeatedly whilst an icon (or user-defined drag-box) is being dragged.

startwindow% - handle of window in which the dragged icon (or user-defined drag-box) starts.

dragicon% - handle of dragged icon. (Will be -1 when used with user-defined drag-box)

dragbutton% - button being used for dragging i.e. 4 for <select-drag> or 1 for <adjust-drag>

startmousex%, startmousey% - screen OS coords of mouse pointer at start of drag.

mousex%, mousey% - screen OS coords of instantaneous mouse pointer position during drag.

overwindow% - handle of window that is currently under pointer. (May be same as startwindow%. If currently not over a window, value will be -1)

overicon% - handle of icon that is currently under pointer. (If currently not over an icon, value will be -1)

dragboxminx%, dragboxminy%, dragboxmaxx%, dragboxmaxy% - instantaneous screen OS coords of drag box rectangle.



PROCuser_endicondrag(startwindow%,dragicon%,dragbutton%,startm-ousex%,startmousey%,dragboxminx%,dragboxminy%,dragboxmaxx%,d-ragboxmaxy%,endwindow%,endicon%,endmousex%,endmousey%)

This function is called when the dragging of an icon (or user-defined drag-box) ends.

startwindow% - handle of window in which the dragged icon (or user-defined drag-box) starts.

dragicon% - handle of dragged icon. (Will be -1 when used with user-defined drag-box)

dragbutton% - button being used for dragging i.e. 4 for <select-drag> or 1 for <adjust-drag>

startmousex%, startmousey% - screen OS coords of mouse pointer at start of drag.

dragboxminx%, dragboxminy%, dragboxmaxx%, dragboxmaxy% - screen OS coords of drag box rectangle in its end-of-drag position.

endwindow% - handle of window over which the dragging ends. (May be same as startwindow%. If not over a window, value will be -1)

endicon% - handle of icon over which the dragging ends. (If not over an icon, value will be -1).

endmousex%, endmousey% - screen OS coords of mouse pointer at end of drag.



PROCuser_definedragbox()

NOT IN  SKELETON !RunImage.

ONLY USED AS PART OF Elixir_04 for user-defined drag-boxes - see Manual Section 2.36 and 3.16.

Defines size/position of required drag-box. (Called only by PROCwimp_startuserdragbox().)



PROCuser_redrawtextline()

NOT IN SKELETON !RunImage.

ONLY USED AS PART OF Elixir_01 for fast scrolling of long text lists - see Manual Section 2.36 and 3.16.

Needs to be used with PROCwimp_calcredrawlines().


PROCuser_spritegraphics()

NOT IN SKELETON !RunImage.

ONLY USED AS PART OF Elixir_03 for constructing a custom sprite - see Manual Section 2.36 and 3.16.



4. Windows

FNwimp_loadwindow(path$,window$,spritearea%)

Loads in a window from a templates file and returns a

handle for the window.

path$ = full pathname to templates file.

window$ = name of window in templates file.

spritearea% = 0 if sprites used are from wimp pool (RMA). Otherwise spritearea% is a handle to a user sprite area.



PROCwimp_openwindow(window%,centre%,stack%)

Opens a window on the screen.

window% = handle of window to open.

If centre% = 0 opens window where it was last left on the screen, or if it hasnt been opened before, then where it is positioned in the template file.

If centre% = 1 opens the window centred on the screen

(mode independent).

If centre% = 2 opens the window centred on the pointer.

stack% = window handle to open behind, or -1 for top of window stack,  -2 for bottom, -3 for current stack position, or -4 for behind backdrop i.e. hidden.


PROCwimp_openwindowat(window%,x%,y%,stack%)

Opens a window on the screen so the top left of the

window is at co-ordinates x%,y% - in OS units.

window% = handle of window to open.

stack% = window handle to open behind, or -1 for top of window stack,  -2 for bottom, -3 for current stack position, or -4 for behind backdrop i.e. hidden.



PROCwimp_redrawwindow(window%)

Causes the complete window whose handle is window% to be redrawn/updated.


PROCwimp_updatewindow(window%,minx%,miny%,maxx%,maxy%)

This procedure tells the Wimp to redraw only the part of a window which is defined by the given coordinates.

This greatly speeds up redraws where lots of graphics are used and/or the window needs regular updating as it avoids redrawing the whole window.

(Deleted sentence.)

window% = handle of window to be updated.

minx%, miny% = bottom left of box to be redrawn in work area

coordinates.

maxx%, maxy% = top right of box to be redrawn in work area coordinates.

(This function can also be used to update any area of the screen, by setting window% to -1 and then using screen OS coordinates for minx%, miny% etc.)


PROCwimp_closewindow(window%)

Closes a window (removes it from the screen).

window% = handle of window to close.


FNwimp_iswindowopen(window%)

Returns TRUE (-1) if the window is open,

otherwise returns FALSE (0).

window% = handle of window.

(Note difference from usual Dr Wimp practice of returning 1 or 0)



FNwimp_getwindowworksize(window%,side%)

Returns the size, in OS units, of a windows defined work area - irrespective of its current visible area.

window% = handle of window.

If side%=0 the width of the work area is returned.

If side%=1 the height of the work area is returned.

(Use FNwimp_getwindowvisiblesize to get current visible size.)



FNwimp_getwindowvisiblesize(window%,side%)

Returns the dimension required, in OS units, of the currently displayed size of the specified window i.e. (If window is not open then size that would be displayed is returned.)

If side% = 0 returns width. If side% = 1 returns height.

(Use FNwimp_getwindowworksize to get defined work area size. Use FNwimp_getwindowvisiblework or FNwimp_getwindowvisiblescreen to get visible window edge coordinates.)



FNwimp_getwindowvisiblework(window%,side%,end%)

Returns the work area OS coordinates of the edges of the current visible area of the window. i.e. returns take current scroll values into account.

window% = handle of window.

If side%=0 then a x coordinate will be returned.

If side%=1 then a y coordinate will be returned.

If end%=0, then the minimum coordinate will be returned, ie the left

or bottom of the visible area depending on the value of side%.

If end%=1, then the maximum coordinate will be returned, ie the right

or top of the visible area depending on the value of side%.





FNwimp_getwindowvisiblescreen(window%,side%,end%)

Returns the screen OS coordinates of the edges of the current visible area of the window.

window% = handle of window.

If side%=0 then a x coordinate will be returned.

If side%=1 then a y coordinate will be returned.

If end%=0, then the minimum coordinate will be returned, ie the left

or bottom of the visible area depending on the value of side%.

If end%=1, then the maximum coordinate will be returned, ie the right

or top of the visible area depending on the value of side%.

(Use FNwimp_getwindowvisiblesize to get current visible size.)



FNwimp_getwindowtitle(window%)

Returns a string containing the window title.

window% = handle of window.


PROCwimp_putwindowtitle(window%,title$)

Changes the window title to title$

window% = handle of window.



PROCwimp_resizewindow(window%,width%,height%)

Resizes the work area of the specified window to the specified width and height, which are in OS co-ordinates.

(The displayed size of the window will not change unless the new work area size is less than the displayed size.)



PROCwimp_resizewindowvisible(window%,width%,height%)

Resizes the visible area of the window to the specified width and height, which are in OS co-ordinates.

Note: If the window is wholly on the screen before re-sizing then it will be kept wholly on the screen after re-sizing i.e. by scrolling, if necessary.


PROCwimp_scroll(window%,side%,direction%,distance%)

Causes the window automatically to scroll vertically or horizontally a given distance in a given direction.

window% = handle of window to be scrolled.

If side%=0 then a horizontal scroll will be done.

If side%=1 then a vertical scroll will be done.

If direction%=0 then the scroll will be left or down depending on the

value of side%.

If direction%=1 then the scroll will be right or up depending on the

value of side%.

distance% = the amount to scroll the window, in OS units.

(Window does not need to be open to effect scroll.)


PROCwimp_scrollto(window%,side%,scrollpos%)

Causes the window automatically to scroll vertically or horizontally to a given position.

window% = handle of window to be scrolled.

If side%=0 then a horizontal scroll will be done.

If side%=1 then a vertical scroll will be done.

scrollpos% = the scroll position required, in OS units. (Note that vertical scroll values are normally negative.)

(Window does not need to be open to effect scroll.)


FNwimp_getscroll(window%,side%)

Returns the current scroll position (in OS units) of the window, in the given direction.

window% = handle of window.

If side%=0 then the horizontal scroll position will be returned.

If side%=1 then the vertical scroll position will be returned. (Note that vertical scroll values are normally negative.)


PROCwimp_banner(window%,delay%)

Opens window in the centre of the screen for specified

time before closing it.

window% = handle of window to open.

delay% = number of seconds to keep window on screen.


FNwimp_createwindow(vminx%,vminy%,vmaxx%,vmaxy%,wminx%,wmi-ny%,wmaxx%,wmaxy%,flags%,colourflags%,button%,title$,titleflags%,ti-tlefont%,maxind%,sarea%)

Used for creating a window within a program. The window handle is returned.

vminx%,vminy%,vmaxx%,vmaxy% = limits of opening visible window in OS screen units.

wminx%,wminy%,wmaxx%,wmaxy% = limits of work area of window

in work area OS coordinates.

flags% = number representing window flags.

colourflags% = number representing the colours of 7 items of window furniture, each in the range 0-15.

button% = work area button type.

title$ = title of window.

titleflags%= number representing titlebar flags.

titlefont%=font handle to use for title font, if relevant.

maxind% = maximum size of title if indirected.

sarea% = handle of sprite area, or 0 to use Wimp sprite area.

(See Section 2.23 of Manual for details of flags%, colourflags%, titleflags%, button%, etc.)



PROCwimp_deletewindow(window%)

Deletes a window definition, closing it if it is open. All the memory

apart from the indirected memory is reclaimed and the window handle

becomes invalid.

window% = handle of window to delete.



PROCwimp_calcredrawlines()

NOT IN DrWimp LIBRARY.

ONLY USED AS PART OF Elixir_01 for fast scrolling of long text lists - see Manual Section 2.36 and 3.16.

Needs to be used with PROCuser_redrawtextline()


PROCwimp_savewindowsettings()

NOT IN DrWimp LIBRARY.

ONLY USED AS PART OF Elixir_06 for saving window position/size/scrolls - see Manual Section 2.36 and 3.16.

Used in conjunction with PROCwimp_getandsetwindowsettings()



PROCwimp_getandsetwindowsettings()

NOT IN DrWimp LIBRARY.

ONLY USED AS PART OF Elixir_06 for retrieving and setting window position/size/scrolls - see Manual Section 2.36 and 3.16.

Used in conjunction with PROCwimp_savewindowsettings()


PROCwimp_groupwindow()

NOT IN DrWimp LIBRARY.

ONLY USED AS PART OF Elixir_07 for operations on a group of windows - see Manual Section 2.36 and 3.16.



5. Message files

FNwimp_initmessages(path$)

Reserves special blocks of memory and sets up a Message file ready for use.

Returns a message handle for file.

path$ = full pathname of messages file to use.

Gives fatal error if messages file cannot be found.


FNwimp_reinitmessages(messagefilehandle%,path$)

If, after it has been initiated (with FNwimp_initmessages, above), a messages file is altered or a different messages file is now to be used, this function allows the changed/new file to be initiated in place of the previous file. Re-initiation can be carried out as many times as required.

Returns a message handle for the changed/new file - which may be different from the previous handle. (It would be normal to assign the return to the previous handle-variable - see Section 2.9)

messagefilehandle%= handle of previous messages file.

path$ = full pathname of new/changed messages file to use.

Gives fatal error if messages file cannot be found.


FNwimp_getnumberofmessages(messagefilehandle%,token$)

Returns the number of items with the given token in the given message file.

messagefilehandle%= handle of messages file (returned from FNwimp_initmessages/FNwimp_reinitmessages above).

token$=token of interest.






FNwimp_messlookup(messagefilehandle%,token$,a$,b$)

Returns the string in a messages file for the token token$, but any parameters %0 and %1 in the returned string are replaced with a$ and b$, respectively, before returning. (See Manual Section 2.9)

messagefilehandle%= handle of required messages file (returned from FNwimp_initmessages/FNwimp_reinitmessages above).

Note that b$ is only used if a$ is not a null string i.e. if you only want 1 parameter to be substituted it must be a$ for %0.





FNwimp_createmessagemenu(messagefilehandle%,token$,title$,size%)

Creates a menu automatically from a Message file. Returns menu handle.

messagefilehandle%= handle of messages file to be used (as returned by FNwimp_initmessages/FNwimp_reinitmessages).

token$ = token for menu. Eg: if token$=MMenu then the token MMenuT will specify the title, MMenu1 the first item, MMenu2 the second etc.

If title$= then the title defined in the message file will be used, otherwise title$ will override whatever is defined in the messages file.

If size%>number of items then the menu is dynamic, ie.

the items can subsequently be increased up to size%. (If size%=0 the menu will automatically be created to accomodate just the number of items contained in the messages file.)

(All menu text is created as indirected.)

(Also shown in Menu section.)



PROCwimp_recreatemessagemenu(menu%,messagefilehandle%,token$-,title$)

Rebuilds a menu from a Message file.

menu% = handle of menu to rebuild

messagefilehandle%= handle of messages file to be used (as returned by FNwimp_initmessages/FNwimp_reinitmessages).

token$ = token for menu items. (See FNwimp_createmessagemenu()  or Manual Section 2.18)

If title$= then the title defined in the message file will be used, otherwise title$ will override whatever is defined in the messages file.

(All menu text is created as indirected.)

(Also shown in Menu section.)




6. Icons



PROCwimp_iconenable(window%,icon%,state%)

Allows an icon to be enabled or disabled (greyed out) or toggled from one state to the other.

window% = handle of window containing icon.

icon% = number of icon.

If state%=0 icon will be disabled (greyed out) and will not respond to mouse clicks.

If state%=1 icon will be enabled.

If state%=2 icon will be changed from its existing state to the other.


FNwimp_geticonenable(window%,icon%)

Returns 1 if the icon icon% in the window whose handle

is window% is enabled. Returns 0 if it is disabled(greyed out).


PROCwimp_iconselect(window%,icon%,state%)

Allows an icon to be selected or deselected or toggled from one state to the other.

Useful for selecting/deselecting/toggling radio and option icons.

window% = handle of window containing icon.

icon% = number of icon.

If state%=0 icon will be de-selected.

If state%=1 icon will be selected.

If state%=2 icon will be changed from its existing state to the other.


FNwimp_geticonselect(window%,icon%)

Returns 1 if the icon is selected, or 0 if it is not selected.

Useful for reading the state of radio and option icons.

window% = handle of window containing icon.

icon% = number of icon.



PROCwimp_puticontext(window%,icon%,text$)

If the icon is indirected then the text in the icon is replaced with text$.

(For an indirected sprite-only icon, the same function is used to change the sprite; in which case text$ is the sprite-name of the required new sprite - which must already be in the Wimp sprite pool.)

If the icon is not indirected then an error is caused.

window% = handle of window containing icon.

icon% = number of icon.

text$ = the required new text (or sprite-name). If text$ exceeds the maximum indirected length specified in the icon definition it will be truncated - which could lead to a sprite not found error with a sprite-only icon..

Note: The caret position (if present) will be preserved as far as is possible. If the caret is at the right-hand end of the current text, or if the length of the new text is shorter than the current caret index, then the caret will be placed at the right-hand end of the new text.



FNwimp_geticontext(window%,icon%)

Returns a string containing the text from the icon.

window% = handle of window containing icon.

icon% = icon number.



FNwimp_geticonsize(window%,icon%,side%)

Returns the width/height of an icon, in OS units.

window%= window handle

icon%- icon handle

If side% = 0 width of icon is returned.

If side% = 1 height of icon is returned.



FNwimp_geticonposition(window%,icon%,coord%)

Returns x/y work area OS-unit coordinates of icon sides.

window%= window handle

icon%- icon handle

If coord% = 0 minimum x coord of icon is returned.

If coord% = 1 minimum y coord of icon is returned.

If coord% = 2 maximum x coord of icon is returned.

If coord% = 3 maximum y coord of icon is returned.


PROCwimp_resizeicon(window%,icon%,minx%,miny%,maxx%,maxy%)

Resizes (and/or moves) an existing icon.

window%= window handle

icon%- icon handle

minx%=required new position of left edge of icon in work OS units.

miny%=required new position of bottom edge of icon in work OS units (probably a negative value)

maxx%=required new position of right edge of icon in work OS units.

maxy%=required new position of top edge of icon in work OS units (probably a negative value).


PROCwimp_moveicon(window%,icon%,minx%,miny%)

Moves an existing icon (without changing its size).

window%= window handle

icon%- icon handle

minx%=required new position of left edge of icon in work OS units.

miny%=required new position of bottom edge of icon in work OS units (probably a negative value).


FNwimp_iconbar(spritename$,text$,maxlen%,pos%)

Creates and places an icon on the iconbar.

spritename$ = name of sprite to put on iconbar.

text$ = text to put underneath the icon.

If text$ =  then sprite-only icon will be created and maxlen% will be ignored.

If text$ is any other string then an indirected text-plus-sprite icon will be created, with space available for a maximum of maxlen% characters (+terminator). (If maxlen% is less than length of text$ then maxlen% will be made equal to length of text$.)

If pos% = 1 then the icon will appear on the right of iconbar.

If pos% = 0 then it will appear on the left.

Returns the iconbar window handle (i.e. always -2).



PROCwimp_colouricon(window%,icon%,colour%,background%)

Sets colour of text/background/border in an icon to colour%.

window% = handle of window containing icon.

icon% = number of icon.

colour% = colour in range 0-15.

background% = 0 to change text (and border, if present) colour.

background% = 1 to change background colour (if icon is filled).

(See Section 2.33 for conditions needed for colour change in icons using outline fonts.)


PROCwimp_puticonfont(window%,icon%,fonthandle%)

Changes font of icon text to the font and size specified by fonthandle%. (Icon must have been defined as using outline fonts.)

window% = handle of window containing icon.

icon% = number of icon.

fonthandle% = handle of required font.

Note: The caret position (if present) will be preserved.





PROCwimp_iconbit(window%,icon%,bit%,state%)

Ensures a specific bit of an icons icon flags is set to the

specified state - or toggled from one state to the other.

window% = handle of window containing icon.

icon% = number of icon.

bit% = number of icon flags bit to set/unset or toggle.

If state%=0 the specified bit will be set.

If state%=1 the specified bit will be unset.

If state%=2 the specified bit will be changed from its existing state to the other.

Note that if bit% is set to 23, no action will take place. Use PROCwimp_iconhide() instead.


FNwimp_geticonbit(window%,icon%,bit%)

Returns state of a specific bit of an icons icon flags.

Return is 1 if bit is set, or 0 if unset.

window% = handle of window containing icon.

icon% = number of icon.

bit% = icon flags bit to test (0-31).


PROCwimp_putcaret(window%,icon%,index%)

Puts the caret in the icon and gives window input focus. If there is text in the icon the caret position can be placed more precisely using index%

window% =handle of window containing icon.

icon% = number of icon (or set to -1 if caret not wanted in icon)

index% = required position of caret within icon text. (If index% is set to -1 or to a value greater than the length of the current text then the caret will be placed at the right-hand end of the text.)



PROCwimp_losecaret

Removes the caret from the icon it is in - and removes input focus

from the window.


FNwimp_getcaretposition(choice%)

Returns information about current caret location/position.

If choice% = 0 handle of window with caret is returned.

If choice% = 1 handle of icon with caret is returned.

If choice% = 2 work area OS-unit x position (in window carrying caret) is returned.

If choice% = 3 work area OS-unit y position (in window carrying caret) is returned.

If choice% = 4 the position of the caret (the index) within the text of a writable icon is returned.

Return is -1 in cases where the caret is not present.



PROCwimp_puticonbartext(text$)

If the iconbar icon has indirected text underneath it then it is

replaced by text$. (The length of text$ must not exceed the iconbars defined max. indirected text length.)



PROCwimp_iconbarsprite(spritename$)

Changes the sprite used for the iconbar icon.

spritename$= name of required sprite, which must already be in Wimp sprite pool.



PROCwimp_putsliderpcent(window%,icon%,pcent)

Sets the percentage of the slider. If the icon is not a

slider then this is ignored.

window% = handle of window with slider in.

icon% = icon number of slider.

pcent = percentage to set. Can be integer or floating point number,

but must be in the range 0-100.



FNwimp_getsliderpcent(window%,icon%)

Returns the percentage of the slider. If the icon is not

a slider then 0 is returned.

The number returned is a floating point number in the

range 0-100.

window% = handle of window with slider in.

icon% = icon number of slider.


FNwimp_createicon(window%,wminx%,wminy%,wmaxx%,wmaxy%,flag-s%,esg%,button%,fcol%,bcol%,font%,text$,sprname$,sarea%,maxind%,-valid$)

Creates an icon and returns its handle (icon number).

window% = handle of window to create icon in.

wminx%,wminy%,wmaxx%,wmaxy% are bottom left and top

right corners of icon in work area OS coordinates.

flags% = number representing flags for icon.

esg% = esg number of icon. 0 for icons which arent radio buttons.

button% = button type of icon.

fcol%,bcol% = foreground and background colours of icons (if not using outline font) in desktop colours, so both in the range 0-15.

font% = handle of outline font. 0 if not using a font.

text$ = text for icon.

sprname$ = sprite name for icon.

sarea% = handle of sprite area, or 0 to use Wimp sprite area.

maxind% = if icon is indirected then maximum size.

valid$ = icon validation string.

(See Section 2.23 of Manual for details of flags%, button%, etc.)


PROCwimp_ploticon(wminx%,wminy%,wmaxx%,wmaxy%,flags%,esg%,-button%,fcol%,bcol%,font%,text$,sprname$,sarea%,maxind%,valid$)

Defines and plots an icon directly into a redraw window. (The plotting will be into the window currently being redrawn.)

wminx%,wminy%,wmaxx%,wmaxy% are bottom left and top

right corners of icon in work area OS coordinates.

flags% = number representing flags for icon.

esg% = esg number of icon. 0 for icons which arent radio buttons.

button% = button type of icon.

fcol%,bcol% = foreground and background colours of icons (if not using outline font) in desktop colours, so both in the range 0-15.

font% = handle of outline font. 0 if not using a font.

text$ = text for icon.

sprname$ = sprite name for icon.

sarea% = handle of sprite area, or 0 to use Wimp sprite area.

maxind% = if icon is indirected then maximum size.

valid$ = icon validation string.

(See Section 2.23 of Manual for details of flags%, button%, etc.)


PROCwimp_deleteicon(window%,icon%,redraw%)

Deletes an icon definition from a window.

The icon will not disappear until the next redraw - which can be forced using third parameter.

window% = handle of window containing the icon.

icon% = icon number of icon to delete.

If redraw% is 1 then the window is redrawn.

If redraw% is 0 then it isnt and the icon wont disappear immediately.


PROCwimp_iconhide(window%,icon%,state%)

Hides/shows an existing icon - and toggles between the two states.

window% = handle of window containing the icon.

icon% = icon number of icon to hide/show or toggle.

If state%=0 the icon is made to appear (show).

If state%=1 the icon is made to disappear (hide).

If state%=2 the icon is toggled between hide/show.





PROCwimp_copydraggedicon()

NOT IN DrWimp LIBRARY.

ONLY USED AS PART OF Elixir_02 for copying a dragged icon - see Manual Section 2.36 and 3.16.

Needs to be used with PROCuser_endicondrag().


PROCwimp_nudgeinteger()

NOT IN DrWimp LIBRARY.

PART OF Elixir_05 providing optional wimp-functions for managing nudger/bump icons - see Manual Section 2.36 and 3.16.

For managing a pair of nudger/bump icons using integer numbers.. (Intended to be used within PROCuser_mouseclick().)


PROCwimp_nudgereal()

NOT IN DrWimp LIBRARY.

PART OF Elixir_05 providing optional wimp-functions for managing nudger/bump icons - see Manual Section 2.36 and 3.16.

For managing a pair of nudger/bump icons using real numbers.. (Intended to be used within PROCuser_mouseclick().)


PROCwimp_group(handle%,type%,string$,state%)

NOT IN DrWimp LIBRARY.

ONLY USED AS PART OF Elixir_07 - see Manual Section 2.36 and 3.16.


7. Menus

FNwimp_createmenu(menu$,size%)

Creates a menu structure from the string menu$. Returns menu

handle.

For more information on menu$ see the manual.

If size%>number of items then the menu is dynamic, ie.

the number of menu items can be increased up to size%.

(If size%=0 the menu will automatically be created to accomodate just the number of items contained in menu$.)

(All menu text is created as indirected.)


FNwimp_createmenuarray(array$(),size%)

Creates a menu from the array supplied. Returns menu handle.

Each item of the menu is in a separate element of the array.

e.g. array$(1)=Info.

The first element, array$(0), is the menu title, and the last

must be the string END.

array$() = array holding item strings.

size% = maximum number of elements to allocate room for

(doesnt have to be the current number). (If size%=0 the menu will automatically be created to accomodate just the number of items contained in the array.)

Returns a handle to the menu.

(All menu text is created as indirected.)


FNwimp_createmessagemenu(messagefilehandle%,token$,title$,size%)

Creates a menu automatically from a Message file. Returns menu handle.

messagefilehandle%= handle of messages file to be used (as returned by FNwimp_initmessages/FNwimp_reinitmessages).

token$ = token for menu. Eg: if token$=MMenu then the token MMenuT will specify the title, MMenu1 the first item, MMenu2 the second etc.

If title$= then the title defined in the message file will be used, otherwise title$ will override whatever is defined in the messages file.

If size%>number of items then the menu is dynamic, ie. the items can subsequently be increased up to size%. (If size%=0 the menu will automatically be created to accomodate just the number of items contained in the messages file.)

(All menu text is created as indirected.)

(Also shown in Messages section.)


PROCwimp_recreatemenu(menu%,menu$)

Rebuilds a menu using the string menu$.

More items can be included than the first time as long as you dont go

over the pre-defined limit.

menu% = handle of menu to rebuild.




PROCwimp_recreatemenuarray(menu%,array$())

Rebuilds a menu using the items in the array.

The first array item (array$(0)) is the menu title, and the

last has to be the string END.

Things like ticks and dotted lines are removed.

menu% = handle of menu to rebuild

array$() = array to get items from.


PROCwimp_recreatemessagemenu(menu%,messagefilehandle%,token$-,title$)

Rebuilds a menu from a Message file.

menu% = handle of menu to rebuild

messagefilehandle%= handle of messages file to be used (as returned by FNwimp_initmessages/FNwimp_reinitmessages).

token$ = token for menu items. (See FNwimp_createmessagemenu()  or Manual Section 2.18)

If title$= then the title defined in the message file will be used, otherwise title$ will override whatever is defined in the messages file.

(All menu text is created as indirected.)

(Also shown in Messages section.)



FNwimp_createfontmenu

Creates a complete menu structure of the currently available (active) fonts.

A menu handle is returned.

(The many wimp-functions available to manipulate individual menu items cannot be applied to font menus.)


FNwimp_recreatefontmenu(fontmenu%)

Re-creates a complete menu structure of the currently available (active) fonts, for a previously created font menu.

fontmenu% = handle of previously created font menu.

The menu handle is returned (which may be a new value).

(The many wimp-functions available to manipulate individual menu items cannot be applied to font menus.)





PROCwimp_attachsubmenu(menu%,item%,submenu%)

Attaches a submenu to a menu item.

menu% = handle of menu.

item% = item number (top item is 1).

submenu% = handle of submenu or window handle.





PROCwimp_menupopup(menu%,pos%,x%,y%)

Displays the menu (or window) whose handle is menu%.

If pos%=0 then menu is displayed with its top left corner at screen coordinates x%,y%.

If pos%=1 then menu will be positioned as for an iconbar menu, as if

iconbar icon is at screen coordinate x% i.e. with left edge to the left of x% and at 96 OS units above the bottom of screen. (y% value is needed but is ignored.)

If pos%=2 then menu will be centred on screen (x%/y% values ignored but must be present)

If pos%=3 then menu will be opened slightly to the right of (and slightly above) pointer position - optimised to butt onto right edge of ptr_menu shape.

If pos%=4 then menu will be opened butting up against the right edge of  the icon over which the mouse was clicked. (Designed to be used with pop-up menu icons.)

Can also be used to open windows that close when the mouse is clicked elsewhere.



PROCwimp_menuclose

Closes the currently active menu.

Used if menu closure is required other than by normal (automatic) wimp process.



PROCwimp_menuenable(menu%,item%,state%)

Allows a menu item to be enabled/disabled(greyed out) or to be toggled between these two states.

menu% = handle of menu.

item% = item number (top item is 1).

If state% =0, the menu item will be disabled (greyed out) and will not respond to mouse clicks.

If state% =1, the menu item will be enabled.

If state% =2, the menu item will be toggled from its existing state to the other.



FNwimp_getmenuenable(menu%,item%)

Checks whether a menu item is enabled or disabled (greyed out).

menu% = handle of menu.

item% = item number (top item is 1).

Returns 1 if menu item is enabled.

Returns 0 if menu item is disabled (greyed out).



PROCwimp_putmenuitem(menu%,item%,item$)

Adds a new menu item at position item%. Any items below will be shuffled down. (menu% must have been already created with sufficient capacity to add extra items - see manual Section 2.18)

menu% = handle of menu.

item% = position of new item% (1 is first item) If item% is bigger than the current number of items+1, then it will be added to the bottom.

item$ = text of new item.


PROCwimp_removemenuitem(menu%,item%)

Removes the item from the menu. Any items below are

shuffled up. If there is only one item on the menu, then

it cannot be removed.

menu% = handle of menu.

item% = number of item to remove.



PROCwimp_putmenutext(menu%,item%,text$)

Replaces menu item text with text$.

menu% = handle of menu.

item% = number of item (Top item is 1).



FNwimp_getmenutext(menu%,item%)

Returns a string containing the text of the menu item in position item%.

menu% = handle of menu.

item% = number of item (top item is 1).


PROCwimp_putmenutitle(menu%,title$)

Changes the title of the menu.

More than 11 characters can be used.

menu% = handle of menu.

title$ = new title.



FNwimp_getmenutitle(menu%)

Returns a string containing the title of the menu.

menu% = handle of menu.



FNwimp_getmenuitem(menu%,menuitemtext$)

Returns the menu item number (top=1) of the menu item whose text matches menuitemtext$.

menu% = handle of menu to search

menuitemtext$ = text string to match (not case sensitive)

Returns 0 if no match found.


PROCwimp_menutick(menu%,item%,state%)

This function puts/removes a tick against the specified menu item - or toggles between these two states.

menu% = handle of menu.

item% = item number (top item is 1).

If state% = 0, any tick against the item will be removed.

If state% =1, a tick will be put against the item.

If state%=2, the tick will be toggled from its existing state to the other.


FNwimp_getmenutick(menu%,item%)

Returns 1 if the specified menu item is ticked, or returns 0 if it isnt.

menu% = handle of menu.

item% = number of item (top item is 1).


FNwimp_menusize(menu%)

Returns the current number of entries (items) in the menu.

menu% = handle of menu.



FNwimp_menumaxsize(menu%)

Returns the maximum number of entries (items) allowed in the menu, as determined on creation.

menu% = handle of menu.



PROCwimp_menudottedline(menu%,item%,on%)

Adds/removes a dotted line to the menu below the item.

menu% = handle of menu.

item% = number of item (top item is 1).

If on%=1 dotted line is added; if on%=0 dotted line is removed.


FNwimp_getmenudottedline(menu%,item%)

Checks whether or not a menu item has a dotted line beneath it.

menu% = handle of menu.

item% = number of item (top item is 1).

Returns a 1 if the menu item has a dooted line beneath it.

Returns a 0 if the menu item does not have a dooted line beneath it.



PROCwimp_menuitemcolour(menu%,item%,colour%,background%)

Changes the text colour of the menu item specified.

menu% = handle of menu.

item% = item number (top item is 1).

colour% = colour required (standard Wimp colours in range 0-15)

(Colours 8, 10, 11, 13, 14 and 15 are best for visibility)

If background% = 1 then the background colour is changed.

If background% = 0 then the foreground colour is changed


PROCwimp_menuwrite(menu%,item%,maxlength%,border%,valid$)

Makes the menu item writable.

menu% = handle of menu.

item% = number of item (top item is 1)

maxlength% = maximum length of text allowed to be entered.

If border%=1 a border will be placed around writable item.

If border%=0 no border will appear.

valid$ = validation string. (A default validation string Pptr_write;Knar; will always be applied - to which valid$ will be suffixed. See Section 2.5) 

(Any text already in the item will be re-inserted into the new writable item. If the existing text is longer than maxlength% then maxlength% will be increased accordingly.)



PROCwimp_group(handle%,type%,string$,state%)

NOT IN DrWimp LIBRARY.

ONLY USED AS PART OF Elixir_07 - see Manual Section 2.36 and 3.16.


FNwimp_findmenuticksstring(menu%)

NOT IN DrWimp LIBRARY.

ONLY USED AS PART OF Elixir_07 - see Manual Section 2.36 and 3.16.



FNwimp_findmenuticksnumber(menu%)

NOT IN DrWimp LIBRARY.

ONLY USED AS PART OF Elixir_07 - see Manual Section 2.36 and 3.16.



8. Sprites

FNwimp_measurefile(filepath$,warning%)

Returns the size in bytes needed to store a file in memory prior to using FNwimp_loadfile(), FNwimp_loaddfile(), FNwimp_loadsprites() or FNwimp_loadjpegfile().

Returns -1 if filepath$ not found.

Always use this as opposed to any other form of measurement.

filepath$ = full pathname of spritefile.

warning% - if not 0, a non-fatal warning will be given if filepath$ cannot be found.

(This function is also listed in in other sections)


FNwimp_loadsprites(filepath$,address%,warning%)

Loads a spritefile into a block of memory at address%.

The memory block must have already been created after using FNwimp_measurefile().

Returns the address at which to load the next file (if any) into the same memory block.

filepath$ = full pathname of spritefile.

If warning% is not 0 then a non-fatal error will be given if filepath$ cannot be found.



FNwimp_countsprites(spritearea%)

Returns the number of sprites in a sprite area.

spritearea% = handle of sprite area.



FNwimp_getspritename(spritearea%,spritenumber%)

Returns the name of a sprite in a sprite area, which has been loaded by FNwimp_loadsprites.

spritearea% = handle of sprite area.

spritenumber% = number of sprite in sprite area. First sprite is 1.


FNwimp_getspritesize(spritename$,spritearea%,side%)

Returns the width/height (in OS units) of a sprite in a sprite area, which has been loaded by FNwimp_loadsprites or is in the Wimp sprite pool.

spritename$ = name of sprite.

spritearea% = handle of sprite area containing sprite (0 means in sprite pool).

If side%=0 then returns width of sprite.

If side%=1 then returns height of sprite.


PROCwimp_savesprites(savepath$,spritearea%)

Saves the contents of a sprite area to a file. The sprites must have been loaded into the spritearea by FNwimp_loadsprites.

savepath$ = full pathname of file to be saved.

spritearea% = handle of sprite area containing sprites.



PROCwimp_rendersprite(spritename$,spritearea%,bx%,by%,minx%,min-y%,maxx%,maxy%,xscale,yscale)

Renders (plots) a sprite on the screen at the specified screen coordinates, using the clipping rectangle.

spritename$ = name of sprite to plot.

spritearea% = 0 if sprite is in Wimp sprite pool, or

spritearea% = handle of sprite area containing sprite, which has been loaded by FNwimp_loadsprites.

bx%,by% = screen coordinates (OS units) at which to put bottom left

corner of sprite.

minx%,miny% = coordinates of bottom left corner of clipping rectangle in screen coordinates (OS units).

maxx%,maxy% = coordinates of top right corner of clipping rectangle in screen coordinates (OS units).

xscale,yscale = respectively, required scaling factors in x and y directions. Values <1 reduce displayed size; values >1 increase size.

(1 meaning no change in size).







PROCwimp_renderwindowsprite(window%,spritename$,spritearea%,bx-%,by%,minx%,miny%,maxx%,maxy%,xscale,yscale)

Renders (plots) a sprite in a window at specified work area coordinates. The window must have its auto-redraw flag unset.

window% = handle of window to render sprite in.

spritename$ = name of sprite to render.

spritearea% = 0 if sprite is in Wimp sprite pool, or

spritearea% = handle of sprite area containing sprite, which has been loaded by FNwimp_loadsprites.

bx%,by% = work area coordinates (OS units) of where to put bottom left of sprite.

minx%,miny% = coordinates of bottom left corner of clipping

rectangle in screen coordinates (OS units).

maxx%,maxy% = coordinates of top right corner of clipping rectangle in screen coordinates (OS units).

(Clipping rectangle is the same as that passed to PROCuser_redraw.)

xscale,yscale = respectively, required scaling factors in x and y directions. Values <1 reduce displayed size; values >1 increase size.

(1 meaning no change in size).






FNwimp_buildsprite()

NOT IN DrWimp LIBRARY.

ONLY USED AS PART OF Elixir_03 for constructing a custom sprite - see Manual Section 2.36 and 3.16.



PROCwimp_setdrawspritegraphiccolour()

NOT IN DrWimp LIBRARY.

ONLY USED AS PART OF Elixir_03 for constructing a custom sprite - see Manual Section 2.36 and 3.16.

Intended for use in PROCuser_spritegraphics().


PROCwimp_writedrawspritetext()

NOT IN DrWimp LIBRARY.

ONLY USED AS PART OF Elixir_03 for constructing a custom sprite - see Manual Section 2.36 and 3.16.

Intended for use in PROCuser_spritegraphics().



9. Pointer

PROCwimp_pointer(pointer%,spritearea%,pointer$)

Changes mouse pointer between the default (number 1) and

the user defined pointer (number 2).

If pointer% = 0 default pointer is used.

If pointer% = 1 user defined pointer is used.

If spritearea% = 0 Wimp sprite pool is used, otherwise spritearea% is a handle to a sprite area.

pointer$ = sprite name of pointer.



PROCwimp_setpointerposition(x%,y%)

Moves the pointer to a given position on the screen - in OS units.

x%,y% = screen coordinates to move the pointer to.



FNwimp_getpointerposition(side%)

Returns the screen coordinates of the pointer, in OS units.

If side%=0 then the x coordinate is returned.

If side%=1 then the y coordinate is returned.



PROCwimp_bindpointer(window%)

Binds the mouse pointer within the given window in the same manner as a standard error message. It should be used when the window the mouse is to be bound in is opened.

The pointer is also placed inside the bound area if it was outside it.

Useful if your application uses its own error or message windows which you want to force the user to respond to.

As the pointer cannot reach any of the window control icons, your window should have a title bar at most.



PROCwimp_releasepointer

Releases the mouse pointer to roam over the whole screen after using PROCwimp_bindpointer. It should be used when the window the mouse is bound in is closed.




10. Drawfiles

PROCwimp_initdfiles

Initialises various blocks of memory ready to use with drawfiles.


FNwimp_measurefile(filepath$,warning%)

Returns the size in bytes needed to store a file in memory prior to using FNwimp_loadfile(), FNwimp_loaddfile(), FNwimp_loadsprites() or FNwimp_loadjpegfile().

Returns -1 if filepath$ not found.

Always use this as opposed to any other form of measurement.

filepath$ = full pathname of spritefile.

warning% - if not 0, a non-fatal warning will be given if filepath$ cannot be found.

(This function is also listed in in other sections)



FNwimp_loaddfile(filepath$,address%,warning%)

Loads a drawfile into a block of memory at address%.

The memory block must have already been created after using FNwimp_measurefile().

Returns the address (handle) at which to load the next file (if any) into the same memory block. (If filepath$ cannot be found the return will be the value of address% i.e. memory not used.)

filepath$ = full pathname of drawfile.

If warning% is not 0 then a non-fatal error will be given if filepath$ cannot be found.


FNwimp_getdfilesize(dfile%,side%)

Returns the width/height (in OS units) of drawfile graphic which has been loaded into memory using FNwimp_loaddfile().

dfile%= drawfile handle  

If side% = 0 returns width.

If side% = 1 returns height.

N.B. the returned dimensions are those of the overall bounding box surrounding all the drawfile objects i.e. as if all objects were grouped.



PROCwimp_savedfile(savepath$,dfile%)

Saves a drawfile stored in memory into a file.

dfile% = handle of drawfile to save (which must have been loaded into memory using FNwimp_loaddfile).

savepath$ = full pathname to save to.







PROCwimp_render(dfile%,bx%,by%,minx%,miny%,maxx%,maxy%,scale-x,scaley,origin%)

Renders (draws) a drawfile at the specified screen coordinates, using a clipping rectangle. Requires RISCOS Version 3.60 or higher.

All coordinates are in OS units.

dfile% = handle of drawfile to render (from using FNwimp_loaddfile)

bx%,by% = screen coordinates of where to put bottom left corner of

drawfile.

minx%,miny% = screen coordinates of bottom left corner of clipping rectangle.

maxx%,maxy% = screen coordinates of top right corner of clipping rectangle.

(Clipping rectangle is the same as that passed to PROCuser_redraw.)

scalex,scaley = respectively, required scaling factors in x and y directions. Values <1 reduce displayed size; values >1 increase size.

(1 meaning no change in size). Note that values less than 0 can be used, which will render the drawfile back-to-front and/or upside-down (but this will not work for JPEG objects in a drawfile).

If origin% = 0 drawfile will be rendered with bottom left corner of drawfile page at bx%/by%.

If origin% = 1 drawfile will be rendered with bottom left corner of drawfile objects overall bounding box at bx%/by%. (See Section 2.19)



PROCwimp_renderwindow(window%,dfile%,bx%,by%,minx%,miny%,ma-xx%,maxy%,scalex,scaley,origin%)

Renders (draws) a drawfile in a window at the specified work area coordinates, using a clipping rectangle. Requires RISCOS Version 3.60 or higher. The window must have its auto-redraw flag unset. All coordinates are in OS units.

window% = handle of window.

dfile% = handle of drawfile to render (from using FNwimp_loaddfile)

bx%,by% = work area coordinates of where to put bottom left corner of drawfile.

minx%,miny% = screen coordinates of bottom left corner of clipping rectangle.

maxx%,maxy% = screen coordinates of top right corner of clipping rectangle.

(Clipping rectangle is the same as that passed to PROCuser_redraw.)

scalex,scaley = respectively, required scaling factors in x and y directions. Values <1 reduce displayed size; values >1 increase size.

(1 meaning no change in size). Note that values less than 0 can be used, which will render the drawfile back-to-front and/or upside-down (but this will not work for JPEG objects in a drawfile).

If origin% = 0 drawfile will be rendered with bottom left corner of drawfile page at bx%/by%.

If origin% = 1 drawfile will be rendered with bottom left corner of drawfile objects overall bounding box at bx%/by%. (See Section 2.19)


11. Text

FNwimp_getfont(font$,sizex,sizey)

Obtains a font handle for a particular outline font at a particular point size.

font$ = name of font, period separated. eg: Trinity.Medium.

sizex = point size in horizontal direction.

sizey = point size in vertical direction.

Returns 0 if the font cannot be found.



PROCwimp_losefont(font%)

Forgets about a font i.e. closes its handle, like closing a file.

Should be called when you have finished with the font, eg. when the

application is quitting.

font% = handle of font to lose.



FNwimp_gettextsize(text$,font$,sizex,sizey,side%,scalex,scaley)

Returns the size (in OS units) of a text string as if it had been plotted in a particular outline font, using a string-specified font at specified point sizes and scaling. Returns 0 if the font cannot be found.

text$ = string to measure.

font$ = name of font, period separated, eg: Trinity.Medium.

sizex = point size in horizontal direction.

sizey = point size in vertical direction.

If side%=0 then the plotted width (length) of the text is returned.

If side%=1 then the plotted height of the text is returned.

scalex,scaley = respectively, required scaling factors in x and y directions. Values <1 reduce displayed size; values >1 increase size.

(1 meaning no change in size).



FNwimp_gettextsizeh(text$,font%,side%,scalex,scaley)

Returns the size (in OS units) of a text string as if it had been plotted in a particular outline font, using a font handle and scaling.

text$ = string to measure.

font% = handle of font.

If side%=0 then the plotted width (length) of the text is returned.

If side%=1 then the plotted height of the text is returned.

scalex,scaley = respectively, required scaling factors in x and y directions. Values <1 reduce displayed size; values >1 increase size.

(1 meaning no change in size).



PROCwimp_plottext(t$,f$,sizex,sizey,align%,x%,y%,fr%,fg%,fb%,br%,bg-%,bb%,scalex,scaley,blending%)

Plots text directly to screen, using string-specified font at specified x/y point sizes, scaled and with choice of colours and alignment.

t$ = string to plot.

f$ = name of font to use, period separated e.g. Trinity.Medium. (If font cannot be found then Trinity.Medium is automatically substituted.)

sizex = point size in horizontal direction.

sizey = point size in vertical direction.

align% = if 0, text is left-aligned at x%/y%; if 1, text is centred on x%/y%: if 2, text is right aligned to x%/y%.

x%,y% = screen coordinates (OS units) to plot the text at (y% value is bottom of text)

fr%,fg%,fb% = foreground colour red, green and blue amounts in range 0-255.

br%,bg%,bb% = background colour red, green and blue amounts in range 0-255.

scalex,scaley = respectively, required scaling factors in x and y directions. Values <1 reduce displayed size; values >1 increase size.

(1 meaning no change in size).

blending% - if any value except 0, font blending will be implemented (if Font Manager version supports this).



PROCwimp_plottexth(t$,font%,align%,x%,y%,fr%,fg%,fb%,br%,bg%,bb-%,scalex,scaley,blending%)

Plots text directly to screen, using font specified by font handle, with choices of colour, alignment and scaling.

t$ = string to plot.

font% = handle of font.

align% = if 0, text is left-aligned at x%/y%; if 1, text is centred on x%/y%: if 2, text is right aligned to x%/y%.

x%,y% = screen coordinates (OS units) to plot the text at (y% value is bottom of text)

fr%,fg%,fb% = foreground colour red, green and blue amounts in range 0-255.

br%,bg%,bb% = background colour red, green and blue amounts in range 0-255.

scalex,scaley = respectively, required scaling factors in x and y directions. Values <1 reduce displayed size; values >1 increase size.

(1 meaning no change in size).

blending% - if any value except 0, font blending will be implemented (if Font Manager version supports this).



PROCwimp_plotwindowtext(window%,t$,f$,sizex,sizey,align%,x%,y%,fr-%,fg%,fb%,br%,bg%,bb%,minx%,miny%,maxx%,maxy%,scalex,scaley,bl-ending%)

Plots text in a window, using string-specified font at specified x/y point sizes, scaled and with choice of colours and alignment.

window% = handle of window to plot in.

t$ = string to plot.

f$ = name of font to use, period separated e.g. Trinity.Medium.  (If font cannot be found then Trinity.Medium is automatically substituted.)

sizex = point size in horizontal direction.

sizey = point size in vertical direction.

align% = if 0, text is left-aligned at x%/y%; if 1, text is centred on x%/y%: if 2, text is right aligned to x%/y%.

x%,y% = work area coordinates (OS units) to plot text at. (y% value is bottom of text)

fr%,fg%,fb% = foreground colour red, green and blue amounts in the range 0-255.

br%,bg%,bb% = background colour red, green and blue amounts in the range 0-255.

minx%,miny% = coordinates (OS units) of bottom left corner of clipping rectangle.

maxx%,maxy% = coordinates (OS units) of top right corner of clipping

rectangle.

(Clipping rectangle is the same as that passed to PROCuser_redraw.)

scalex,scaley = respectively, required scaling factors in x and y directions. Values <1 reduce displayed size; values >1 increase size.

(1 meaning no change in size).

blending% - if any value except 0, font blending will be implemented (if Font Manager version supports this).





PROCwimp_plotwindowtexth(window%,t$,font%,align%,x%,y%,fr%,fg%,-fb%,br%,bg%,bb%,minx%,miny%,maxx%,maxy%,scalex,scaley,blending-%)

Plots text in a window, using font specified by font handle.

window% = handle of window to plot in.

t$ = string to plot.

font% = handle of font to use.

align% = if 0, text is left-aligned at x%/y%; if 1, text is centred on x%/y%: if 2, text is right aligned to x%/y%.

x%,y% = work area coordinates (OS units) to plot text at. (y% value is bottom of text)

fr%,fg%,fb% = foreground colour red, green and blue amounts in the range 0-255.

br%,bg%,bb% = background colour red, green and blue amounts in the range 0-255.

minx%,miny% = coordinates (OS units) of bottom left corner of clipping rectangle.

maxx%,maxy% = coordinates (OS units) of top right corner of clipping

rectangle.

(Clipping rectangle is the same as that passed to PROCuser_redraw.)

scalex,scaley = respectively, required scaling factors in x and y directions. Values <1 reduce displayed size; values >1 increase size.

(1 meaning no change in size).

blending% - if any value except 0, font blending will be implemented (if Font Manager version supports this).



PROCwimp_deskplottext(t$,align%,x%,y%,fr%,fg%,fb%,br%,bg%,bb%)

Plots text directly to screen, using the current desktop font. Requires RISC OS 3.50 or higher.

t$ = string to plot.

align% = if 0, text is left-aligned at x%/y%; if 1, text is centred on x%/y%: if 2, text is right aligned to x%/y%.

x%,y% = screen coordinates (OS units) to plot the text at. (y% value is bottom of text)

fr%,fg%,fb% = foreground colour red, green and blue amounts in range 0-255.

br%,bg%,bb% = background colour red, green and blue amounts in range 0-255.



PROCwimp_deskplotwindowtext(window%,t$,align%,x%,y%,fr%,fg%,fb-%,br%,bg%,bb%,minx%,miny%,maxx%,maxy%)

Plots text in a window, using the current desktop font.  Requires RISC OS 3.50 or higher.

window% = handle of window to plot in.

t$ = string to plot.

align% = if 0, text is left-aligned at x%/y%; if 1, text is centred on x%/y%: if 2, text is right aligned to x%/y%.

x%,y% = work coordinates (OS units) to plot the text at. (y% value is bottom of text)

fr%,fg%,fb% = foreground colour red, green and blue amounts in range 0-255.

br%,bg%,bb% = background colour red, green and blue amounts in range 0-255.

minx%,miny% = coordinates (OS units) of bottom left corner of clipping rectangle in screen coordinates.

maxx%,maxy% = coordinates (OS units) of top right corner of clipping

rectangle in screen coordinates.

(Clipping rectangle is the same as that passed to PROCuser_redraw.)






FNwimp_fontcolour(fr%,fg%,fb%,br%,bg%,bb%)

Returns control codes in a string to change the current outline font colour. Useful for using in the middle of a string of outline font text being plotted.

fr%,fg%,fb% = red, green and blue components respectively of the foreground colour, in the range 0-255.

br%,bg%,bb% = red, green and blue components respectively of the background (anti-alias) colour, in the range 0-255.





FNwimp_fontunderline(on%)

Returns control codes in a string to turn underlining on or off.

Useful for using in the middle of a string of outline font text being plotted.

If on%=0 turns underlining off.

If on%=1 turns underlining on.



FNwimp_fontchangeh(font%)

Returns control codes in a string to change the current outline font.

Useful for using in the middle of a string of outline font text being plotted.

font% = handle of font to change to.







PROCwimp_calcredrawlines()

NOT IN DrWimp LIBRARY.

ONLY USED AS PART OF Elixir_01 for fast scrolling of long text lists - see Manual Section 2.36 and 3.16.

Needs to be used with PROCuser_redrawtextline()

12. Printing

FNwimp_pdriverpresent

Checks to see if a printer driver is loaded.

Returns TRUE (-1) if a printer driver is loaded, or FALSE (0) if not.

(Note difference from usual Dr Wimp practice of returning 1 or 0)


FNwimp_getpdrivername

If a printer driver is loaded, the name of the printer driver is returned.

Check to make sure one is loaded first, with FNwimp_pdriverpresent.


PROCwimp_declarefont(font$)

Declares a font for printing. (Intended to be used within PROCuser_declarefonts)

font$ = name of font to declare, period separated e.g. Trinity.Medium.


PROCwimp_declarefonth(font%)

Declares a font for printing using font handle. (Intended to be used within PROCuser_declarefonts)

font% = handle of font to declare.


PROCwimp_declaredfilefonts(dfile%)

Declares the fonts used in a drawfile (especially) for postscript printing. (Intended to be used within PROCuser_declarefonts)

dfile% = handle of drawfile to be printed, which must have been loaded using FNwimp_loaddfile.



FNwimp_getpapersize(side%,type%)

Returns various information about the current paper size set up in loaded printer driver - in OS units.

If side%=0 then a horizontal measurement is returned.

If side%=1 then a vertical measurement is returned.

Which measurement is determined by type%.

If type%=0 then the width or height is returned.

If type%=1 then the left or bottom margin is returned.

If type%=2 then the printable width or printable height is returned.

If type%=3 then the right or top margin is returned.


FNwimp_papertoscreen(window%,coord%,side%,orient%)

Converts a paper x or y coordinate to a screen x or y coordinate - all in OS units.

window% = handle of window whose work area to use.

(A window reference is needed because paper values are assumed to map to positions in a window - Section 2.22.)

coord% = coordinate (x or y).

If side%=0 then coord% is a x coordinate, and an x coordinate is returned.

If side%=1 then coord% is a y coordinate, and a y coordinate is returned.

If orient%=0 then page is portrait.

If orient%=1 then page is landscape.



FNwimp_papertowork(coord%,side%,orient%)

Converts a paper x or y coordinate to a work area x or y coordinate - all in OS units.

(Paper values are assumed to map to positions in a window. Hence x values are the same and y values only referenced to different corner.)

coord% = coordinate (x or y).

If side%=0 then coord% is a x coordinate, and an x coordinate is returned.

If side%=1 then coord% is a y coordinate, and a y coordinate is returned.

If orient%=0 then page is portrait. If orient%=1 then page is landscape.



FNwimp_screentopaper(window%,coord%,side%,orient%)

Converts a screen x or y coordinate to a paper x or y coordinate - all

in OS units.

(A window reference is needed because paper values are assumed to map to positions in a window - Section 2.22.)

window% = handle of window whose work area to use.

coord% = coordinate (x or y).

If side%=0 then coord% is a x coordinate, and an x coordinate is returned.

If side%=1 then coord% is a y coordinate, and a y coordinate is returned.

If orient%=0 then page is portrait.

If orient%=1 then page is landscape.



FNwimp_worktopaper(coord%,side%,orient%)

Converts a work area x or y coordinate to a paper x or y coordinate -

all in OS units.

(Paper values are assumed to map to positions in a window. Hence x values are the same and y values only referenced to different corner.)

coord% = coordinate (x or y).

If side%=0 then coord% is a x coordinate, and an x coordinate is returned.

If side%=1 then coord% is a y coordinate, and a y coordinate is returned.

If orient%=0 then page is portrait. If orient%=1 then page is landscape.



PROCwimp_print(user%,window%,fpage%,lpage%,persheet%,interval%,copies%,-orient%,xscale,yscale,order%,invert%)

Initiates printing of a document.

If user%=0 PROCuser_redraw is called to draw the pages (with printing% set to TRUE and the clipping rectangle set to the page coordinates).

If user%=1 PROCuser_print is called to draw the pages, with the clipping rectangle set to the page coordinates.

window% = handle of window to redraw if user%=0.

fpage% = page number of first page to print.

lpage% = page number of last page to print.

persheet% = number of pages to fit onto the sheet of paper. Can be

1, 2 or 4. (If 2 then page is rotated sideways and reduced to 70% before applying xscale/yscale values. If 4 then page is reduced to 50% before applying xscale/yscale values.)

interval% = allows pages in a sequence to be skipped. 1 means every
page to be printed; 2 means every other page, etc. (E.g. allows odd or
even pages to be printed.)

copies% = number of copies of each page to print.

If orient%=0 then page is portrait.

If orient%=1 then page is landscape.

xscale/yscale scale the printed output in the x/y directions independently. Values <1 reduce the size, values >1 increase the size. A value of 1 means no change in size. (There is a lower limit of 0.05.)

order% applies only when persheet% is 2 or 4. If order%=0 the pages are in the normal positions on the paper sheet. If order%=1 the positions of the pages are altered.

If invert%=0 the printed output is normal; if 1 the printed output is upside-down.

(See Section 2.22 for full details.)




PROCwimp_sendfiletoprinter(filepath$)

Sends the named file directly to the currently configured printer.

Has same effect as dragging the file to the printer icon on the iconbar.

filepath$ = full pathname of file.

If delete% is not 0, the file will be deleted after being sent to the printer.

(Also listed under Section 3.1 Miscellaneous)



13. Dynamic areas

FNwimp_createdynamic(size%,maxsize%,drag%,name$)

Creates a dynamic area and returns a handle for it. (This wimp-function needs RISCOS Version 3.60 or higher.)

size% = initial size of dynamic area in bytes.

maxsize% = maximum size of dynamic area in bytes. (-1 means no limit but use of this special value is not recommended.)

If drag% = 1 the user can change the size of the area by dragging in the Task Display.

name$ is the name of the dynamic area appearing in the Task Display.

Note: Dynamic area sizes may be restricted by the OS to multiples of 4kbytes (4096 bytes). Automatic rounding up will then occur. See Section 2.20 of Manual.



FNwimp_changedynamic(darea%,absolute%,size%)

Changes the size of a dynamic area.

darea% = handle of dynamic area to be resized.

If absolute%=1 then the size in bytes given in size% is the new absolute size of the dynamic area.

If absolute%=0 then the size in bytes given in size% is the amount to change the dynamic area size by. (In this case, if size% is positive then the area will become larger, if size% is negative then the area will shrink.)

Returns a handle for the dynamic area, which may not be the same location as before.

Note the point about multiples of 4kbytes in FNwimp_createdynamic() above.



FNwimp_measuredynamic(darea%)

Returns the current size of a dynamic area in bytes.

darea% = handle of dynamic area to measure.



PROCwimp_deletedynamic(darea%)

Deletes a dynamic area.

darea% = handle of dynamic area to delete.



FNwimp_getfreeRAM

Returns the number of bytes of free RAM available.



14. Colour picker

PROCwimp_opencolourpickerrgb(dialoguetype%,red%,green%,blue%,n-one%,x%,y%)

Requires RISCOS Version 3.50 or higher. Opens the colour picker window with the initial colour set by the values of red%, green% and blue%, which are in the range 0-255.

The window will open in the RGB model (which means the set colour

values will actually be shown as percentages in the range 0-100%).

x%/y% give the screen OS-unit coordinates of the top left corner of

the opening window.

dialoguetype% determines how the window will close:

If dialoguetype%=0 the window will be closed by specific action e.g. selecting its Close icon.

If dialoguetype%=1 the window will close if the mouse is clicked outside the window.

If none%=0 the None button will be disabled.

If none%=1 the None button will be enabled and deselected.

If none%=2 the None button will be enabled and selected.

(Note: the window also closes when the OK or None button is selected.)



PROCwimp_opencolourpickermodel(model%,dialoguetype%,value1,val-ue2,value3,value4,none%,x%,y%)

Requires RISCOS Version 3.50 or higher. Opens the colour picker window with the colour model set by model% and the initial colour set by the values of value1, value2, etc.

model%=0 for RGB model, 1 for CMYK model, 2 for HSV model.

value1, value2 etc. are in range 0-100%, except that value1 is

in the range 0-359 degrees (the colour angle in HSV) when model%=2.

value4, which must always be present, is ignored unless model%=1 (CMYK model).

x%/y% are screen OS-unit coordinates of top left corner of window.

If dialoguetype%=0 the window will be closed by specific action e.g. selecting its Close icon.

If dialoguetype%=1 the window will close if the mouse is clicked outside the window.

If none%=0 the None button will be disabled.

If none%=1 the None button will be enabled and deselected.

If none%=2 the None button will be enabled and selected.

(Note: the window also closes when OK or None button is selected.)







PROCwimp_opensubmenucolourpickerrgb(red%,green%,blue%,none%, x%,y%)

Requires RISCOS Version 3.50 or higher. Opens the colour picker window as a sub-menu, with the initial colour set by the values of red%, green% and blue%,

which are in the range 0-255.

The window will open in the RGB model (which means the set colour

values will actually be shown as percentages in the range 0-100%).

x%/y% give the screen OS-unit coordinates of the top left corner of

the opening window.

If none%=0 the None button will be disabled.

If none%=1 the None button will be enabled and deselected.

If none%=2 the None button will be enabled and selected.

As with any sub-menu, the window will close if the mouse is clicked outside the window or when the mouse pointer retraces the opening route. (Note: the window also closes when the OK or None button is selected.)



PROCwimp_opensubmenucolourpickermodel(model%,value1,value2,va-lue3,value4,none%,x%,y%)

Requires RISCOS Version 3.50 or higher. Opens the colour picker window as a sub-menu, with the colour model set by model% and the initial colour set by the values of value1, value2, etc.

model%=0 for RGB model, 1 for CMYK model, 2 for HSV model.

value1, value2 etc. are in range 0-100%, except that value1 is

in the range 0-359 degrees (the colour angle in HSV) when model%=2.

value4, which must always be present, is ignored unless model%=1 (CMYK model).

x%/y% are screen OS-unit coordinates of top left corner of window.

If none%=0 the None button will be disabled.

If none%=1 the None button will be enabled and deselected.

If none%=2 the None button will be enabled and selected.

As with any sub-menu, the window will close if the mouse is clicked outside the window or when the mouse pointer retraces the opening route. (Note: the window also closes when the OK or None button is selected.)



15. JPEG files

FNwimp_measurefile(filepath$,warning%)

Returns the size in bytes needed to store a file in memory prior to using FNwimp_loadfile(), FNwimp_loaddfile(), FNwimp_loadsprites() or FNwimp_loadjpegfile().

Returns -1 if filepath$ not found.

Always use this as opposed to any other form of measurement.

filepath$ = full pathname of spritefile.

warning% - if not 0, a non-fatal warning will be given if filepath$ cannot be found.

(This function is also listed in in other sections)


FNwimp_loadjpegfile(filepath$,address%,warning%)

Loads a JPEG file into a block of memory at address%.

The memory block must have already been created after using FNwimp_measurefile().

Returns the address (handle) at which to load the next file (if any) into the same memory block. (If filepath$ cannot be found the return will be the value of address% i.e. memory not used.)

filepath$ = full pathname of JPEG file.

warning% - if not 0, a non-fatal warning will be given if filepath$ cannot be found.



FNwimp_getjpegsize(jpeghandle%,side%,dpi90%)

Returns the width/height (in OS units) of the overall bounding box surrounding a JPEG graphic which has been loaded into memory using FNwimp_loadjpegfile().

jpeghandle%= JPEG file handle.

If side% = 0 returns width.

If side% = 1 returns height.

If dpi90%=0 then the natural dimensions are returned.

If dpi90%=1 then the dimensions are those for display at 90dpi.



FNwimp_getjpegsizefile(filepath$,side%,dpi90%,warning%)

Returns the width/height (in OS units) of the overall bounding box surrounding a JPEG graphic directly from its file. (Returns 0 if filepath$ cannot be found.)

filepath$ = full JPEG file path.

If side% = 0 returns width.

If side% = 1 returns height.

If dpi90%=0 then the natural dimensions are returned.

If dpi90%=1 then the dimensions are those for display at 90dpi.

warning% - if not 0, a non-fatal warning will be given if filepath$ cannot be found.



PROCwimp_savejpeg(savepath$,jpeghandle%)

Saves a JPEG currently loaded in memory to a file. The JPEG must have been loaded into memory by FNwimp_loadjpegfile.

savepath$ = full pathname of file to be saved.

jpeghandle% = handle of memory area containing the JPEG.



PROCwimp_renderjpeg(jpeghandle%,bx%,by%,minx%,miny%,maxx%,m-axy%,scalex,scaley)

Renders (draws) a JPEG at the specified screen coordinates, using a clipping rectangle. All coordinates are in OS units.

The JPEG must already have been loaded into memory using FNwimp_loadjpegfile().

jpeghandle% = handle of JPEG

bx%,by% = screen coordinates of where to put bottom left corner of JPEG.

minx%,miny% = screen coordinates of bottom left corner of clipping rectangle.

maxx%,maxy% = screen coordinates of top right corner of clipping rectangle.

(Clipping rectangle is the same as that passed to PROCuser_redraw.)

scalex,scaley = respectively, required scaling factors in x and y directions. Values <1 reduce displayed size; values >1 increase size.

(1 meaning no change in size).



PROCwimp_renderwindowjpeg(window%,jpeghandle%,bx%,by%,minx%-,miny%,maxx%,maxy%,scalex,scaley)

Renders (draws) a JPEG in a window at the specified work area coordinates, using a clipping rectangle. The window must have its

auto-redraw flag unset. All coordinates are in OS units.

The JPEG must already have been loaded into memory using FNwimp_loadjpegfile().

window% = handle of window.

jpeghandle% = handle of JPEG

bx%,by% = work area coordinates of where to put bottom left corner of JPEG.

minx%,miny% = screen coordinates of bottom left corner of clipping rectangle.

maxx%,maxy% = screen coordinates of top right corner of clipping rectangle.

(Clipping rectangle is the same as that passed to PROCuser_redraw.)

scalex,scaley = respectively, required scaling factors in x and y directions. Values <1 reduce displayed size; values >1 increase size.

(1 meaning no change in size).



PROCwimp_renderjpegfile(jpegfilepath$,bx%,by%,minx%,miny%,maxx-%,maxy%,scalex,scaley,warning%)

Renders (draws) a JPEG directly from its file to the specified screen coordinates, using a clipping rectangle. All coordinates are in OS units.

jpegfilepath$ = fullpath of JPEG file

bx%,by% = screen coordinates of where to put bottom left corner of JPEG.

minx%,miny% = screen coordinates of bottom left corner of clipping rectangle.

maxx%,maxy% = screen coordinates of top right corner of clipping rectangle.

(Clipping rectangle is the same as that passed to PROCuser_redraw.)

scalex,scaley = respectively, required scaling factors in x and y directions. Values <1 reduce displayed size; values >1 increase size.

(1 meaning no change in size).

warning% - if not 0, a non-fatal warning will be given if jpegfilepath$ cannot be found.

(Note: This function cannot be used for printing.)



PROCwimp_renderwindowjpegfile(window%,jpegfilepath$,bx%,by%,min-x%,miny%,maxx%,maxy%,scalex,scaley,warning%)

Renders (draws) a JPEG directly from its file to a window at the specified work area coordinates, using a clipping rectangle. The window must have its auto-redraw flag unset.

All coordinates are in OS units.

window% = handle of window.

jpegfilepath$ = fullpath of JPEG file

bx%,by% = work area coordinates of where to put bottom left corner of JPEG.

minx%,miny% = screen coordinates of bottom left corner of clipping rectangle.

maxx%,maxy% = screen coordinates of top right corner of clipping rectangle.

(Clipping rectangle is the same as that passed to PROCuser_redraw.)

scalex,scaley = respectively, required scaling factors in x and y directions. Values <1 reduce displayed size; values >1 increase size.

(1 meaning no change in size).

warning% - if not 0, a non-fatal warning will be given if jpegfilepath$ cannot be found.

(Note: This function cannot be used for printing.)



16. Elixirs

PROCuser_redrawtextline(x%,y%,line%)

NOT IN SKELETON !RunImage.

ONLY USED AS PART OF Elixir_01 for fast scrolling of long text lists - see Manual Section 2.36.

Needs to be used with PROCwimp_calcredrawlines().

x% - x-position to plot text line (in screen OS units)

y% - y-position to plot text line (in screen OS units)

line% - the number of the list line to be plotted/redrawn.


PROCwimp_calcredrawlines(leftmargin%,topmargin%,totallines%,linesp-acing%)

NOT IN DrWimp LIBRARY.

ONLY USED AS PART OF Elixir_01 for fast scrolling of long text lists - see Manual Section 2.36.

Needs to be used with PROCuser_redrawtextline().

leftmargin% - horizontal margin between left edge of list window and start of list text (in OS units).

topmargin% - vertical margin between top of list window and start of list area (in OS units).

totallines% - the total number of lines in the list.

linespacing% - the vertical spacing between lines of the list (in OS units).



PROCwimp_copydraggedicon(startwindow%,dragicon%,dragboxminx%-,dragboxminy%,dragboxmaxx%,dragboxmaxy%,endwindow%,delete%)

NOT IN DrWimp LIBRARY.

ONLY USED AS PART OF Elixir_02 for copying a dragged icon - see Manual Section 2.36.

Needs to be used with PROCuser_endicondrag().

startwindow% - handle of window in which the dragged icon starts.

dragicon% - handle of dragged icon.

dragboxminx%, dragboxminy%, dragboxmaxx%, dragboxmaxy% - screen OS coords of drag box rectangle in its end-of-drag position. (Values to be carried through from the parameters of PROCuser_endicondrag() )

endwindow% -  handle of window in which the dragged icon ends. (Can only be an open window of the same application, and may be the same as startwindow%.)

delete% - if set to 0, the dragged icon will simply be copied to the end-of-drag position.

delete% - if set to 1 then dragged icon will be deleted from its original position.



FNwimp_buildsprite(spritename$,sprwidth%,sprheight%)

NOT IN DrWimp LIBRARY.

ONLY USED AS PART OF Elixir_03 for constructing a custom sprite - see Manual Section 2.36.

Returns the handle of the sprite area containing the new sprite.

spritename$ - name of sprite

sprwidth%, sprheight% - required width and height of sprite in OS units



PROCwimp_plotinsprite(spritearea%,spritename$,sprwidth%,sprheight-%)

NOT IN DrWimp LIBRARY.

ONLY USED AS PART OF Elixir_03 for constructing a custom sprite - see Manual Section 2.36.

Selects and sets up sprite ready for drawing graphics/text with VDU/PLOT-type commands. Calls PROCuser_spritegraphics() below.

(Is called once by FNwimp_buildsprite() but thereafter may be called independently if graphics/text contents of sprite are to be altered.)

spritearea% - handle of sprite area containing the named sprite, as returned by FNwimp_buildsprite().

spritename$ - name of sprite

sprwidth%, sprheight% - required width and height of sprite in OS units



PROCuser_spritegraphics(spritearea%,spritename$,sprwidth%,sprheig-ht%)

NOT IN SKELETON !RunImage.

ONLY USED AS PART OF Elixir_03 for constructing a custom sprite - see Manual Section 2.36.

Called only by PROCwimp_plotinsprite()

The required graphic/text VDU/PLOT-type commands should be placed in this user-function.

spritearea% - handle of sprite area containing the named sprite, as returned by FNwimp_buildsprite().

spritename$ - name of sprite, can be used to differentiate, if more than one sprite is being constructed.

sprwidth%, sprheight% - width and height of available sprite area, in OS units.



PROCwimp_setdrawspritegraphiccolour(colour%)

NOT IN DrWimp LIBRARY.

ONLY USED AS PART OF Elixir_03 for constructing a custom sprite - see Manual Section 2.36.

Intended for use in PROCuser_spritegraphics().

Sets foreground colour for subsequent PLOT actions.

colour% - required colour (only colours 0-15 available).



PROCwimp_writedrawspritetext(text$,fonth%,spritex%,spritey%,foregro-und%,background%)

NOT IN DrWimp LIBRARY.

ONLY USED AS PART OF Elixir_03 for constructing a custom sprite - see Manual Section 2.36.

Intended for use in PROCuser_spritegraphics().

Plots given text in an outline font at given position in anti-aliased colours (only colours 0-15 available).

text$ - required text.

fonth% - handle of required font/size i.e. must be previously declared.

spritex%, spritey% - start position of bottom left of text, with respect to bottom left corner of sprite.

foreground%, background% - required anti-aliased colours (only colours 0-15 available).



PROCuser_definedragbox(startwindow%,dragbutton%,startmousework-x%,startmouseworky%,RETURN userboxminx%,RETURN userboxminy%,RETURN userboxmaxx%,RETURN userboxmaxy%)

NOT IN  SKELETON !RunImage.

ONLY USED AS PART OF Elixir_04 for user-defined drag-boxes - see Manual Section 2.36

Defines size/position of required drag-box. (Called only by PROCwimp_startuserdragbox().)

startwindow% = handle of window where dragging was started.

dragbutton% = button used to start drag. (4 for <select>, 1 for <adjust>)

startmouseworkx%/startmouseworky% = mouse position at start of drag - in work OS units, referred to startwindow%.

userboxminx%/userboxminy%/userboxmaxx%/userboxmaxy% = edges of required drag-box - in work OS units, referred to startwondow%. (Default drag-box is a 32 OS unit square centred on mouse pointer.)



PROCwimp_startuserdragbox(startwindow%,dragbutton%,startmousew-orkx%,startmouseworky%)

NOT IN DrWimp LIBRARY.

ONLY USED AS PART OF Elixir_04 for user-defined drag-boxes - see Manual Section 2.36

Starts dragging of user-defined drag-box. (Intended to be used within PROCuser_mouseclick().)

startwindow% = handle of window where dragging is to be started.

dragbutton% = button used to start drag. (4 for <select>, 1 for <adjust>)

startmouseworkx%/startmouseworky% = mouse position at start of drag - in work OS units, referred to startwindow%.

This wimp-function also uses PROCuser_seticondragbounds(), PROCuser_draggingicon() and PROCuser_endicondrag() (all in the skeleton !RunImage) in which, in this case, the value of dragicon% will always be set to -1.



PROCwimp_nudgeinteger(window%,icon%,downicon%,upicon%,valuei-con%,increment%,lowvalue%,highvalue%)

NOT IN DrWimp LIBRARY.

PART OF Elixir_05 providing optional wimp-functions for managing nudger/bump icons - see Manual Section 2.36.

For managing a pair of nudger/bump icons using integer numbers.. (Intended to be used within PROCuser_mouseclick().)

window% = handle of window containing nudger/bump icons.

icon% = nudger/bump icon currently being clicked.

downicon% = icon number of down icon.

upicon% = icon number of up icon.

valueicon% = icon number of value icon i.e. the icon whose value is being changed.

increment% = the amount by which the value icon is to be changed.

lowvalue% = the lowest value allowable in the value icon.

highvalue% = the highest value allowable in the value icon.



PROCwimp_nudgereal(window%,icon%,downicon%,upicon%,valueicon-%,increment,shiftincrement,lowvalue,highvalue,decplaces%)

NOT IN DrWimp LIBRARY.

PART OF Elixir_05 providing optional wimp-functions for managing nudger/bump icons - see Manual Section 2.36.

For managing a pair of nudger/bump icons using real numbers.. (Intended to be used within PROCuser_mouseclick().)

window% = handle of window containing nudger/bump icons.

icon% = nudger/bump icon currently being clicked.

downicon% = icon number of down icon.

upicon% = icon number of up icon.

valueicon% = icon number of value icon i.e. the icon whose value is being changed.

increment = the amount by which the value icon is to be changed using <select> or <adjust>.

shiftincrement = the amount by which the value icon is to be changed using <shift-select> or <shift-adjust>.

lowvalue = the lowest value allowable in the value icon.

highvalue = the highest value allowable in the value icon.

decplaces% = the number of decimal places to be used for the results displayed in the value icon.


PROCwimp_savewindowsettings(window%,windowname$,savedir$)

NOT IN DrWimp LIBRARY.

ONLY USED AS PART OF Elixir_06 - see Manual Section 2.36.

Saves the current screen position/size/scrolls of a window to a text-file in a fixed format.

window% - handle of window whose state is to be saved.

windowname$ - arbitrary name of window, which will be used as leafname of saved file (prefixed with W)

savedir$ - directory path in which to locate saved file (no trailing .). If savedir$ is set to a null string then file will be saved to <Choices$Write> in a sub-directory with the same name as the application name i.e. the string which was used in the first parameter of FNwimp_initialise() when starting the application.

Used in conjunction with PROCwimp_getandsetwindowsettings()



PROCwimp_getandsetwindowsettings(window%,windowname$,savedir-$,hide%,warning%)

NOT IN DrWimp LIBRARY.

ONLY USED AS PART OF Elixir_06 - see Manual Section 2.36.

Retrieves a file saved in the format used by PROCwimp_savewindowsettings() and sets the window position/size/scrolls accordingly.

window% - handle of window whose state is to be set.

windowname$ - leafname of saved file, without the W prefix i.e. name of window as used in PROCwimp_savewindowsettings().

savedir$ - directory path where file is located (without trailing .).

If savedir$ is set to a null string then file will be looked for in <Choices$Write> in a sub-directory with the same name as the application name i.e. the string which was used in the first parameter of FNwimp_initialise() when starting the application.

hide% - if 0 then window will be opened/re-opened after its state has been changed. If any other value then window will not be opened after its state has been changed.

warning% - if any value other than 0 a warning will be given if the file cannot be found. (If set to 0 and file cannot be found then no action will take place.)



PROCwimp_group(handle%,type%,string$,state%)

NOT IN DrWimp LIBRARY.

ONLY USED AS PART OF Elixir_07 - see Manual Section 2.36.

Enables/Disables/Selects/Deselects/Hides/Shows/Toggles a group of icons in the same window - or Enables/Disables/Ticks/Unticks/Toggles a group of menu items in the same menu.

handle% is the window (or menu) handle.

type%=1 means a group of icons is to be enabled/disabled/toggled;

type%=2 means a group of menu items is to be enabled/disabled/toggled;

type%=3 means a group of icons is to be selected/de-selected/toggled.

type%=4 means a group of menu items is to be ticked/unticked/toggled;

type%=5 means a group of icons is to be shown/hidden/toggled.

string$ is a comma-separated list of the icon numbers (or menu items) to which the action is to be applied.

state%=0 means disable/de-select/untick/show the icon/menu item;

state%=1 means enable/select/tick/hide the icon/menu item;

state%=2 means toggle the current state of the icon/menu item.

(Note that state% has the same meaning as in the corresponding wimp-functions in the main DrWimp library.)


PROCwimp_groupwindow(string$,type%,centre%,state%)

NOT IN DrWimp LIBRARY.

ONLY USED AS PART OF Elixir_07 - see Manual Section 2.36.

Opens/redraws/closes a group of windows.

string$ is a comma-separated list of the window handles to which the action is to be applied.

type%=1 means a group of windows is to be opened;

type%=2 means a group of windows is to be redrawn (values of centre% & stack% ignored.);

type%=3 means a group of windows is to be closed (values of centre% & stack% ignored.).

If centre% = 0 opens windows where they were last left on the screen (or where positioned in the template files).

If centre% = 1 opens the windows centred on the screen

(mode independent).

If centre% = 2 opens the windows centred on the pointer.

stack% = window handle to open behind, or -1 for top of window stack,  -2 for bottom, -3 for current stack position, or -4 for behind backdrop i.e. hidden.

(Note that centre% and stack% have the same meaning as in PROCwimp_openwindow() in the main DrWimp library.)



FNwimp_findmenuticksstring(menu%)

NOT IN DrWimp LIBRARY.

ONLY USED AS PART OF Elixir_07 - see Manual Section 2.36.

Returns a comma-separated string of the menu items currently ticked e.g. 2,4,5 or a null string if none ticked.

menu% is menu handle.



FNwimp_findmenuticksnumber(menu%)

NOT IN DrWimp LIBRARY.

ONLY USED AS PART OF Elixir_07 - see Manual Section 2.36.

Returns a single-byte integer number representing the menu items currently ticked. If menu item X is ticked then Bit X in the returned number will be set e.g return is 52 (%110100) if menu items 2, 4 and 5 are currently ticked. Returns 0 if none ticked. (Bit 0 is not used and is always 0.)

menu% is menu handle.

(This wimp-function can only be used with menus having 31 menu items or less.)



The OLE Elixir (Elixir_08)

Details of all wimp- and user-functions for this Elixir are contained in separate documentation accompanying the Elixir files.



