  
  
(N.B. This text-version of the Manual has been extracted directly from
the main Dr Wimp Manual, which is prepared in Impression Publisher.
Therefore some formatting anomalies are inevitable below - and
graphics do not appear, of course. It is best viewed with a display
width of 80 characters.)




                   DrWimp

          Version 3.81 (10-Aug-2003)
           

 Andrew Ayre 1995, 1996, 1997, 1999

Changes/additions by Ray Favre from 1st May 1999

Major features and updates by Guy Bartle

Manual laid out by Eddie Lord



Public Domain (Freeware)

See Conditions of Use



It is also possible to get the text version of this Manual in HTML
format, kindly organised by user Keith Wright. See details on his
web-site at:

http://www.denmarkwa.net.au/~kwright/

                                                                   



                    

...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 DrWimp library may be reproduced in part if crunching and mangling
utilities such as !BSquasher are used, otherwise it must be reproduced
in whole, complete with its opening REMs containing the Conditions of
Use and the copyright banner.

If the DrWimp library is being reproduced in full then it may be added
to the !RunImage (or similar) file, and does not have to be separate.

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:          rayfavre@argonet.co.uk

World Wide Web:     http://www.argonet.co.uk/users/rayfavre/

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.     
     


     



...Contents...

Section 1 - Introduction
     1. Prologue     1.1
     2. An overview     1.2
     3. Handles     1.4
     4. Variables & Strings     1.6
     5. On/Off bits     1.7
     6. System variables     1.8
     7. Security and post-programming actions     1.10

Section 2 - Tutorials/Guide
     Notes     2.1
     1. Getting going     2.3
     2. Menus     2.7
     3. Windows     2.11
     4. Window & icon control     2.15
     5. Doing more with menus     2.27
     6. Panes     2.31
     7. Saving data with save windows     2.35
     8. Errors & Warnings     2.39
     9. Message files     2.43
     10. Loading data     2.47
     11. Interactive help     2.49
     12. Sprite areas & Mouse pointers     2.51
     13. The redraw process     2.55
     14. Changing sprites & more on the iconbar icon     2.57
     15. Large menus, rebuilds and Font menus     2.59     
     16. Internal multitasking     2.71
     17. Bars     2.73
     18. Sliders     2.77
     19. Loading & Saving Drawfiles     2.81
     20. Rendering Drawfiles & Sprites     2.83
     21. JPEG files     2.87
     22. Validation Strings     2.89
     23. Indirection     2.91
     24. Text handling     2.93
     25. Printing     2.97
     26. Window & Icon creation     2.107
     27. Managing the quit/shutdown     2.115
     28. Dynamic Areas     2.123
     29. Colour Picker     2.127
     30. General file loading/saving to/from memory     2.131
     31. Wimp messages     2.133
     32. Inconiser     2.135
     33. Grubby tasks     2.137
     34. Bits & bobs     2.139
     35. Application memory needs     2.145     
     36. Saving time with !Fabricate     2.147
     37. Dr Wimps Elixirs     2.149
     38. Final Comments     2.153

Section 3 - Functions
     1. Misc     3.1
     2. Polling     3.8
     3. User     3.9
     4. Windows     3.16
     5. Messages     3.19
     6. Icons     3.21
     7. Menus     3.25
     8. Sprites     3.30
     9. Pointer     3.32
     10. Drawfiles     3.33
     11. Text     3.34
     12. Printing     3.37
     13. Dynamic Areas     3.40
     14. Colour picker     3.41
     15. JPEG files     3.44
     16. Elixirs      3.50

Section 4 - Index
     Index     4.1

     
     


     



...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.

 Example 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 for compression and code security.

 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

Please note that although Version 3.55 (or later) of Dr Wimp is
expected to work with RiscOS Versions earlier than 3.50, they will not
be able to use the Colour Picker wimp-functions - see Section 2.29.



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

The file DrWimp - a Basic library - does all the detailed, clever work
(and you leave it strictly alone to do that!) - and the !RunImage file
is where you add coding to control things


The DrWimp library is a collection of Basic function definitions, most
of which you can call from the !RunImage file - just as with a normal
Library. All the 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.

Some of these wimp-functions in the DrWimp library need help from you,
the programmer. When they do need this help, they call one of a number
of functions which are defined in the !RunImage file. All these
functions in the !RunImage also have lower case names, but they are
preceded by user_ . For example:

FNuser_givemesomehelp(tomato$)

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

So, in summary, the DrWimp Library holds wimp-function definitions and
the !RunImage holds user-function definitions - and the two are
inextricably linked by the fact that the user-functions are
automatically called by wimp-functions, when needed. (Further, 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.)

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. Inside !MyApp is a skeleton !RunImage file with all the
correct user-function definitions for that version and its matching
DrWimp library file - plus a !Run file and a !Sprites file.

It is therefore 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, 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 deafult 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 Dr Wimp is concerned and it is vital that you do
not change these default values in the blank !MyApp application.

To develop an application, you therefore gradually add Basic coding
(often using the wimp-functions) to one or more of the user-function
definitions in the !RunImage - 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. Theses 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.

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 parameters you have to pass and what is
returned. (!FncnPrc was written using DrWimp, of course!)



The main difference that you will probably notice when developing a
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.

(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
the data 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 eaxmple, 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.

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 the Wimp allocates memory blocks
automatically and the 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.

For instance, the wimp-function to define a simple menu is
DEFFNwimpcreatmenu(), whose parameters allow you to specify the menu
item (and title) text. This wimp-function returns the menu handle
(i.e. returns the start address of the memory block which the Wimp
automatically allocated). So you can assign the returned memory
address directly with something like:

iconbarmenu%=FNwimp_creatmenu()

and you dont need to know what the actual memory address is.

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.

Finally, you will also come across examples in this Manual where a
handle is used to read/write data in the memory block by using the
indirection operators i.e. ?, ! and $. For example:

DIM datablock% 255:REM** datablock% is the handle of the DIMmed
memory block. **

datablock%!16=92:REM** Put the value 92 into the word starting at
the address datablock%+16 **





.. 4. Variables & Strings

When using Dr Wimp, one of the first lines of the !RunImage file
should be something like:

LIBRARY <MyApp$Dir>.DrWimp

This tells the BASIC interpreter that you want to use a library
(called DrWimp here) and where it is located. After this call, the
two files (DrWimp and !RunImage) may be separate but they will work as
if all the code is in one file. Eg: you can call functions in DrWimp
from !RunImage and DrWimp calls functions (the user-functions, in
fact) in !RunImage.

More importantly, any variables or strings that are created in one of
the files and isnt localised, will be available to both files, so
either one can alter the contents of a variable etc.

This could cause problems, because you could be using a variable in
the !RunImage file, and then call a wimp-function that also uses it,
so when the function is exited, the variable will be different from
what your code expects.

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 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 follows that you must not change the values in any of the Dr
Wimp variables which have names starting with w.

The exceptions are two global variables which have been 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.16 and 2.29 respectively.

There is also a special global variable intended for use by the
programmer when using the Colour Picker - but we can safely leave that
until Section 2.29.



.. 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).

They can only be created using one of two star commands  (*Set or
*SetEval) so that their creation means using the command line (or Task
Window) or, more commonly, from a Command or Obey file. Typically,
nearly every application creates a t least one system variable in its
!Run and/or !Boot file.

System variables help in the 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.

As an example of how system variables are used, lets have a look at
the most common one - which is MyApp$Dir (already seen in the LIBRARY
line at the start of the previous Section). When the !Run file of any
application is run (e.g. by double clicking) it sets up this system
variable and assigns to it the full pathname to the corresponding
application directory.

If you want to use the value in the system variable in a file-path
definition you use the form:

<Obey$Dir>

Thus, if you have just double-clicked on your application to run it
and a file called Templates is inside your application directory,
then its full pathname could then be written as:

<Obey$Dir>.Templates.

Note that if you move you appliaction to a different location and run
it again, then Obey$Dir will faithfully record the new location i.e.
the application is transportable.

But, the same system variable is used when other applications are
started. So if, between your !Run file being run and your application
wanting to access this Templates file, another !Run file from another
application is run, the contents of Obey$Dir will change. So, in your
!Run file you must immediately set up a new, unique system variable as
a copy of that previous Obey$Dir which can be used instead.

For example, if your application is called MyApp then you would
probably use:

Set MyApp$Dir <Obey$Dir>

i.e. you have created a new (hopefully unique) system variable called
MyApp$Dir which contains the same contents as Obey$Dir


Then, for instance, you could get access to your Templates file
inside your application directory by using the file-path definition:

<MyApp$Dir>.Templates

and now it would be safe from any subsequent change to Obey$Dir


You will find that system variables tend to have stylised names (like
the ones just shown) - and there are a few styles which have special
meanings. In principle though, you could use any name, but it avoids
confusion if you follow the popular conventions - and you will see
that Dr Wimp does.

Unfortunately, a disadvantage with system variables is that their
contents cannot so easily be read from BASIC programs. Because of
this, DrWimp provides a wimp-function (FNwimp_getsysvariable) to do
this for you, and it will be described in more detail later.



System variables can also be useful for other things. For example, if
you wrote a database application then you might have to set the
maximum number of records allowed for the amount of memory that you
have allocated. The limit could be put in the !Run file instead of the
!RunImage file so non-programmers dont have to go and delve into your
code. For instance, you could have a line in your !Run file like:

Set MaxRecords 5000

Then in your !RunImage file you could read the value with something
like:

MaxAllowed% = VAL(FNwimp_getsysvariable(MaxRecords))

(Note the VAL. System Variable values are always strings, even though
the use of double-quotes is not always needed when setting them - as
with 5000 above.)



.. 7. Security and post-programming actions

If you are going to distribute a new and brilliant application that
you have slaved over for weeks, then you will probably want to reduce
the disc storage needs of the finished package - and you may also want
some security


All the utilities to do this are included with the DrWimp package. As
an example, the total size of the !RunImage + DrWimp, for a particular
Version, was 55611 bytes (54.3k). After using the supplied utilities,
the resulting (and much more secure) !RunImage was 8732 bytes (8.6k)
only.

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

1. Store your original !RunImage (source file) somewhere safe.

2. Link a copy of your !RunImage with DrWimp using !Linker. (This
eliminates all unused wimp-functions and merges the !RunImage with the
remaining wimp-functions to produce a new linked !RunImage. A useful
reduction in disc storage space and 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 !RunImage size, this process makes it very difficult to
read and alter the !RunImage. A run-time speed increase also occurs.)

4. Turn the linked and compressed !RunImage into an absolute file by
dropping it onto !MakeApp2 and saving under a different name. (Renders
the !RunImage unreadable.)

5. Compress the result further by dropping it onto !Crunch, to give
you your final !RunImage to distribute. (Further reduces the !RunImage
storage space - but not the run-time needs.)

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


     



...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.

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 (PD or commercial). There are no
conditions attached to them.

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 application !MyApp
to work on. Put it on a fresh disc or in a new hard disc directory.

We would highly recommend using !TemplEd 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 !TemplEd 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.

The Tutorials folder also 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.

Most learning is done through experimentation. 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 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.

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,1):PROCuser_error:PROCwimp_closedown:END

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

90 PROCwimp_poll

100 END

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

The first line of the !Run file (have a look at that as well) 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 !RunImage
listing can be used with this system variable and, in effect, tells
the computer that the DrWimp library is also located within the !MyApp
application directory.

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,300,0)

and 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
300, so the skeleton !MyApp will run on RISC OS 3.00 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
withit RISC OS 3.00 or higher, but a few e.g. Colour Picker need RISC
OS 3.50 or higher. Clearly, the lower you can make it the more people
will be able to use your application.

(There is a small dilemma here: the Wimp actually needs the Wimp
Version rather than the RISC OS Version - but we are more familiar
with the latter. Using the RISC OS Version instead is not normally a
problem although there can be an inconsistentcy with RISC OS version
3.11. Dr Wimp tries to sort this out behind-the-scenes but you are
advised to use one of the main OS numbers, such as 300, 350, 370,
400.)



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, which is specifically intended for you to use for
global variable declarations, window definitions, menu definitions and
any other jobs that need or ought to be done before wimp-polling
starts.

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 !RunImage file is 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!)

The added wimp-function returns a handle for the window that contains
the iconbar icon 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 of the application. 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.14.

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. 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%


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%)

whose definition is in the !RunImage.

Moreover, whenever this call is made, the parameters in the
user-function (window% and icon%) 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). 

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%)

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%
and icon% set, respectively, to the window and icon handles over which
the keypress took place i.e. here, window% will contain the iconbar
window handle.

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.

In this iconbar case the value in icon% is irrelevant (because there
is only one icon-per-application on the iconbar - 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 combinations i.e. 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.15.) 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-fuction
call quits the application as soon as possible.

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.9 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. 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 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
!TemplEd. (At the moment, we will only be using windows which have
been designed in a window template editor - such as !TemplEd, 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 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
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 (RMA), 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 as the RMA). Our Info window uses just
one sprite (the Dr Wimp logo) and it is included in the basic !MyApp
!Sprites/!Sprite22 files - which means that it will be loaded into the
sprite pool on application start-up. Thus setting the final parmeter
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 (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 !TemplEd). You only need to know the window handle
and the icon number/handle. (You can find the icon number by loading
the Templates file into !TemplEd, opening the info window and moving
the pointer over the icon. The small !TemplEd window at the top right
of the screen will give you the icon number.)

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
!TemplEd.



Now for the Version field. 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)

Now 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.

Note that it is important not to exceed the indirected string length
set up in the icon definition - or you will lose the slabbed effect in
the info box, and if you are using RISC OS 3.5+ the desktop font may
revert back to the system font.

Check the application works as it is supposed to and then try using
the same method to change the Purpose field 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 the Wimp only allows text to be displayed in icons. 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 tutorial folder 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)



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 !TemplEd. In such cases, the icon number
passed in  PROCuser_mouseclick will be -1.



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. Finally, 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).

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

The new window main% is divided up into three sections. We will 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 !TemplEd 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 set value here). This amount is set by using !TemplEd and
changing the indirected icon size for the 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 a second step, we want to acieve the same result by
pressing <return> when the caret is in the writable icon.

The wimp-function FNwimp_geticontext reads text from icons. ie. 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 that has any, 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 (for the terminator, which is automatically added by the
Wimp). This is value is entered in the appropriate place in the
template editor.

So, making an icon indirected with a maximum value of 11 is enough for
putting 10 characters plus theterminator in that 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 have to get the
<return> key to perform the same action when it is pressed and the
caret is in the writable icon (icon number 1). Pressing the <return>
key in this situation should always act 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.22 later) which is set in the
definition of the writable icon. Briefly, the validation string can,
among other things, control which characters 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 will be displayed in the writable icon but only the
pressing of the <return> key will be notified to our task by the Wimp.

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 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 it 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 the short press in may be too quick and just produce
a flicker. You may therefore like to add the following line 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 action.



Keypress character codes

We dont need any more detail about keypresses for the tutorial but
this is a useful point to show the list of keycodes returned when the
non-alphanumeric keys on the keyboard are pressed (assuming that an
appropriate validation string is used - see Section 2.22). They are:

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 to 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 (see !TemplEd
documents inside the application and the example application)), so
clicking on one within the group de-selects any others in the same ESG
group. 

Thus, here, when the user clicks 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 choice% which
will be 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 it falling over if a user fiddles with the templates file.
In fact, this is good practice for all initial settings.

When Swap is clicked on, 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, but it
is a good 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.

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.



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.

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 functions and will often contain most of the code to control
you 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 !TemplEd, 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%) to specify which window and which of
its icons. 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 and/or you want to give it 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.



[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, and writable 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 attach the menu to the main window by altering FNuser_menu so it
looks like:

DEF FNuser_menu(window%,icon%)

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.15)

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.

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.

The last major menu function turns an item into a writable one. A
block of memory is reserved to put the text into it automatically.

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). 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.

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 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:

WHEN 2 : PROCwimp_quit(0)

in the earlier coding. 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.]     
     


     

.. 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, 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)

The pane is to be attached 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. And that is all there is
to it!

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.

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%

(Note the above use of FNuser_pane has changed for Version 3.59, to
incorporate improvements.)

Change the relevant parts in PROCuser_closewindow so when the main
window is closed both the panes close and check it all works:

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

ENDIF

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. (If you are an advanced user of DrWimp and are adding
routines to use child windows with the nested window manager
facilities, you might wish to note that your child windows should
not have the Pane option selected if you are using writable icons in
them.)



 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.
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 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, the 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,
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, as 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.

You can now drag the file icon to any filer window 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... are taken
care of by DrWimp.

We have not yet introduced PROCuser_saveicon. To make things work
automatically behind the scenes, 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
(!TemplEd, 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


Although there are no specific Dr Wimp facilities for drag-saving a
directory or application folder rather than a file, it is not
difficult to do so. Indeed the !Fabricate utility - authored with Dr
Wimp - does this. Please contact the author for information if you
want to explore this area.

Remember also that you can open windows as menus. 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.

Please note that the draggable icon in the save window is an
indirected, sprite-only icon. An error will occur if you try to use
an indirected text-plus-sprite icon here. It is hoped to remove this
small restriction in a future release of Dr Wimp.



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

     
     


     

.. 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. The first is:

PROCwimp_error(title$,error$,button%,prefix%)

This one is the most commonly used.



title$      is the title to be displayed in the error window. Usually,
the application name is used.

error$      is your rquired error/warning message itself. The text is
wordwrapped automatically.

button%     controls the default button. If it is 1 then you get an
OK button. If it is a 2 then you get a CANCEL button instead.

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

The other function is:

FNwimp_errorchoice(title$,error$,prefix%)

The parameters act in exactly the same way as for PROCwimp_error. This
function displays an error window with both an OK button and a
CANCEL button. If OK is clicked on then the function returns TRUE
(-1). If CANCEL is clicked on then it returns FALSE (0). (Note
difference from usual Dr Wimp practice of returning 1 or 0)

Perhaps the best way to look at how these two wimp-functions are used
in practice is to browse through the DrWimp library listing - in
conjunction with the information given at the end of this section.

Custom error/warning windows

Error messages have their limitations. For instance, they stop
processing from happening, so your multitasking application and all
others stop until you respond to the error window button(s).

But what if you want more than two buttons, or alternative text in
buttons? It is possible to use a window of your own to report an
error, but how can you force the user to acknowledge it? Standard
error windows grab the pointer and refuse to let it go - and you can
do the same using Dr Wimp with your own custom-built error windows.

To see this (and still using the tutorial with Temlate4) add the
following line where the other windows are loaded:

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

which will load a customised window called error. Then add this line
after WHEN 8 : in PROCuser_ mouseclick;

PROCwimp_openwindow(error%,1,-1)

and this line between the two ENDCASE statements at the end of the
same procedure:

WHEN error% : IF icon%=1 THEN PROCwimp_closewindow(error%)

Add this line just before the ENDPROC in PROCuser_openwindow;

IF window%=error% THEN PROCwimp_bindpointer(error%)

and this line just before the ENDPROC in PROCuser_closewindow:

IF window%=error% THEN PROCwimp_releasepointer

Save the changes and run !MyApp again. Clicking on the Option button
in the main window generates a home made error window which grabs the
pointer until OK is clicked.

To summarise what has been done here: opening the error window calls
PROCwimp_bindpointer, which traps the pointer inside the named window.
As the pointer cannot escape, there is no point in having any window
tools apart from a title bar. Closing the window calls
PROCwimp_releasepointer, which frees the pointer again.



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



Error traps in DrWimp listing

It may assist you in your programming and debugging to know a little
about the 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.

There are several such traps within the DrWimp library. 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 carat - 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 Messages 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 erxample, 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

Directory objects - Non-fatal warning if any of the three directory
objects functions are called  for a dir$ value which is neither a
directory nor an application. Error message title will be Message
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

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.

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).



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,1):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 PROCwimp_closedown


PROCwimp_closedown - this is, in fact, an internal wimp_function not
intended for use by the programmer (i.e. it is not in the list of
functions in Section 3). 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 wimp-function is also called by Dr Wimp
when you quit the application by normal means - so its inclusion in
the global error trap is also appropriate.)

It is also worth introducing PROCuser_error at this point. This
user-function was added in Version 3.62 and is only called in the
above 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 probably of most use to you 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: if you use this function, be very careful to get your coding
right within DEFPROCuser_error, otherwise you risk a continuous loop
of errors!     
     


     

.. 9. Message files

It is increasingly common for applications to have Message files
(nothing to do with the Wimps messaging system!). These files have
most of the text for the application in. So, for example, it can be
easily translated into another language by someone who doesnt need to
know anything about programming.

Copy the Messages file from the tutorial folder into the !MyApp
directory. Load it into !Edit and have a look at it to become familiar
with the messages file format.

Note firstly that you can put comments into a Messages 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 that the line can be
identified by. The token and the text it represents are separated by a
colon. For example:

LIB:Doctor Wimp

Thus, if we wanted to use the line of text Doctor Wimp in our
program then 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.

By using parameters, lines of text can also have strings inserted into
them at the time they are read into the application. For example:

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

which includes the parameters %0 and %1

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 sets up blocks of memory ready to
read in the lines of text. path$ is the full pathname to the Messages
file. The function returns a handle for the messages file, which is
used when reading the file with the following functions.

FNwimp_messlook0(messagefilehandle%,token$)

FNwimp_messlook1(messagefilehandle%,token$,a$)

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

From Dr Wimp Version 3.58 onwards you can use multiple messages files.
By default the maximum number of such files is 5, but this can easily
be changed - see later.



To use a messages file it must first be initialised using
FNwimp_initmessages(path$)and it is best to do this early within
PROCuser_initialise - for each messages file which is to be active
simultaneously during the application run.

For the tutorial, call the function for the Messages 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 read a line without substituting any parameter strings you would
use, for example:

FNwimp_messlook0(messages%,UTIL)

This returns the line of text FuncnPrc.

To read a line and replace the parameter %0 with an inserted string
you would use, for example:

FNwimp_messlook1(messages%,OS,4.02)

This returns the line of text RISC OS 4.02.

To read and substitute two strings you would use, for example:

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



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

Add the following lines to PROCuser_initialise after
FNwimp_initmessages and run your application.

lib$=FNwimp_messlook0(messages%,LIB)

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

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

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

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

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

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

[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 Section2.12 where it continues from this stage.]



From Dr Wimp Version 3.62 onwards 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.

Finally, from Version 3.61, there is 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.

Message files can also be used for creating/recreating menus - see
Section 2.15 - 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 five, which is probably more than
adequate - but is easily changed if not. 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. Loading data

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 is called.

This is therefore the user-function where you add code to do the
actual loading e.g. into a block of memory or an array etc. The
parameters of FNuser_loaddata are:

path$      is the full pathname of the file that has been
dragged/double-clicked (the source file). Dont always assume that
it is something like : IDEFS::Andy.$.TextFile.

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

icon%      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 also that
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.)

If you use the information about the dragged/double-clicked file, then
you must return a 1 from this user-function. This is vital because it
is used by DrWimp to send a message to the filer or any other
application that the file came from, 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:

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

return%=0

IF ftype$=FFF THEN
     file%=OPENIN(path$)
     L%=1
     REPEAT
          A$(L%)=GET$#file%
          L%+=1
     UNTIL EOF#file%
     CLOSE#file%
     lines%=L%-1
     return%=1

ENDIF

=return%



What this does is to load a text file into an array called A$ (which
you will need to create in PROCuser_initialise). At the end, lines%=
the number of lines read in.

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.

Files can also be loaded in with double-clicks on the file. They can
be made to load in your application first, if it isn't already. The
only thing you need to add to achieve this is a line like the
following in your !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.

If you are using special files matched to your application you might
wish to use a separate filetype for them - and give it a name.
Filetypes in the range &000 to &0FF are available for this - but they
are not reserved filetypes. To give the filetype &0xx the name
TestFile put a line like the following in both your !Run file and
!Boot file:

Set File$Type_0xx TestFile

     
     


     

.. 11. 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 syatem 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. 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.

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 !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
one 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 1 : h$=This application is called MyApp 

         WHEN 2 : h$=It tests the DrWimp library

         WHEN 3 : 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 !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$

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 Messages
files to hold the text (see Sections 2.9 and 2.15 for details on using
Messages files). In particular, help text in a choice of languages can
then be easily arranged.     
     


     

.. 12. Sprite areas & Mouse pointers

In order to display/print sprites in a Wimp application they need to
be loaded into memory somewhere - as opposed to being in a file.

All the sprites we have used so far have been from a special area of
memory called the Wimp sprite pool and 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, the Wimp sprite pool is really only for sprites which are to
be used by the Filer and we may wish to display sprites in other
circumstances e.g. solely for use during the run of our application.

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.

It is worth pausing here to recap on the difference between a
spritefile and a sprite. A spritefile is the means of storing
sprites on hard- or floppy-disc etc. and each spritefile can hold one
or more sprites. The 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 the spritefile - which cause !Paint
to be loaded and the sprites are then seen in a filer-like window.

General principle

FNwimp_loadsprites does most of the work for you and must be called
(in a certain simple but strict way - see later in this section)
before the user sprites can be utilised. Passed to
FNwimp_loadsprites is a pathname to a spritefile and a pointer/handle
to the memory space (the user area handle) to load the sprites into.

The mouse pointer is, itself, simply a sprite and in Dr Wimp we can
use PROCwimp_pointer to change the mouse pointer shape by using a
different sprite for it. Briefly, you can change the pointer sprite
between the Wimps default pointer sprite held in the Wimp sprite pool
and a user sprite. The details are demonstrated below. (You can also
change the pointer shape when over an icon, independently of the
window. This is covered later below.)

Tutorial

For the tutorial, we are going to combine two aspects: the general
sprite-loading procedure and changing the mouse pointer shape. So,
start by copying 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 enter the following lines in PROCuser_initialise:

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

DIM sprites% size%

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

The first line measures the spritefile size; the second creates a
corresponding memory block - and the last line loads the file into
that block. (a% is an arbitrary variable not being used elsewhere
globally.) The second parameter of FNwimp_loadsprites is the
handle/pointer to the memory location to hold the spritefile - here,
the start address of the block we have just created.

This loading sequence is very important and we will return to it
later.

Now lets use the sprite we have just loaded.

Whenever the pointer moves in and out of one of !MyApps windows, the
functions PROCuser_enteringwindow and PROCuser_leavingwindow are
called.

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.

The first parameter of PROCwimp_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 both
the first and second parameters should be 0 to use it. If you wish to
use a user-defined user sprite instead, the the first two parameters
should be, respectively, 1 and the private sprite area handle holding
the sprite you want.

The last parameter is the name of the sprite to use and it only has
relevance for the user-defined pointer. If you are using the Wimps
default pointer, then the string will be ignored. (But you need to put
something there and a null string  is a good idea.)



Loading sprites into a user area

Leaving the tutorial for the moment, it is as well to look again at
the Dr Wimp method for loading a spritefile into a memory block
(user sprite area) which may seem a bit strange - especially the
idea of passing the handle of the user sprite area to the loading
function instead of it returning it to you. The same arrangement is
used for loading in drawfiles and other files (see later Sections) and
allows one block of memory to hold more than one file, each with their
own handles.

Things will hopefully become clearer if you look at the following
example code to load in two spritefiles, with leafnames Sprites1 and
Sprites2:

size%=FNwimp_measurefile(\"<MyApp$Dir>.Sprites1\")

size%+=FNwimp_measurefile(\"<MyApp$Dir>.Sprites2\")

REM** Note the += above.

DIM sprites% size%

sprites1%=sprites%

sprites2%=FNwimp_loadsprites(<MyApp$Dir>.Sprites1,sprites1%)

a%=FNwimp_loadsprites(\"<MyApp$Dir>.Sprites2\",sprites2%)

This sequence first measures both the spritefiles whose paths are
shown, adding the size of the second to the first. Then DIM is used to
create a block of memory big enough to hold both files.

A handle is chosen (sprites1%) for the first spritefile and is given
the handle of the DIMmed block.i.e. the start address of the whole
block is now in sprites1%. (The name of the block can now be
forgotten.)

The final two lines load in the two spritefiles one at a time. The
first parameter of FNwimp_loadsprites is for the full path of the
sprite file to be loaded and the second parameter  is handle of the
start of the memory space to be used.

The critical point to note is that the return from this wimp-function
is the starting point within the created block for the next
spritefile to be loaded.

Thus, as you can see in the two spritefile sequence above, the return
from the first call is assigned to sprite2% - which is then
immediately used in the second call.

We thus end up with a number of sprite-files loaded into one defined
area of memory, but with discrete pointers/handles within this memory
block to each sprite-file. (Note that, because we measured the total
size of memory block needed before we created it and started the
loading action, the handle returned by the last call to
FNwimp_loadsprites cannot safely be used for anything. It is, in fact,
the address of the byte after the end of the memory block. So this
final return value is just put into an arbitrary variable and
ignored.) 

This loading sequence can be used for any number of spritefiles, or a
mixture of sprite-files, drawfiles (using FNwimp_loaddfile) or JPEGs
(using FNwimp_loadjpegfile) etc. It is not difficult but it obviously
needs to be adhered to strictly.

Finally, the number of sprites in a spritefile can be obtained with
FNwimp_countsprites, and the name of a sprite in a spritefile can be
returned with FNwimp_getspritename


(N.B. When you are familiar with the process you could alternatively
use a dynamic area for the memory block instead of DIMming. See
Section 2.28.)

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. Section 2.20 is
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 sprites can be used in icons in
the window design provided that they are loaded into a user area prior
to the window template loading. In this case, the user area handle is
put into the final parameter of FNwimp_loadwindow() - as indicated in
that earlier reference.

Sprites which have been loaded by the above process can be saved,
collectively, to a single file using PROCwimp_savesprites()


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.22.

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
which is a thin vertical red line - the caret. (R7 describes the
particular border given to the icon.)

     
     


     

.. 13. 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 the CIRCLE command to draw a circle in a window.

The Wimp asks for 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 in the template editor.

When the Wimp wants a redraw, Dr Wimp calls PROCuser_redraw()
automatically. In its parameters, the handle of the window is passed,
plus the position of the rectangle on the screen that needs to be
redrawn. The rectangle works like a graphics window created with VDU
24, so you can redraw all the window contents if you like (although
that can sometimes be a bit slow) and anything outside the rectangle
will be clipped. Alternatively you can arrange the coding so that only
the parts required are redrawn.

Sections 2.20 (Rendering Drawfiles and Sprites) and 2.23 (Text
Handling) also contain material relevant to PROCuser_redraw




The Wimp redraw process is a powerful tool in many applications - both
for display and printing - and this introductory manual cannot do it
justice. There are several mini-applications in the Examples folder
demonstrating how FNuser_redraw is used. Also, its use is covered in
detail in the charity book Dr Wimps Surgery, mentioned in Section
1.1.



     
     


     

.. 14. Changing sprites & more on the iconbar icon

Sprite-only icons

If you have an icon which holds only a sprite (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 which is set up using a template
editor.

For example, 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.)

Re-load !MyApp and the file icon in the save window will now be the
standard one for Data.

[Your !RunImage listing should now look like listing RI_08 in Tutor1
(apart from the REM lines, perhaps). This listing is not altered
further. When the tutorial is picked up again - in Section 2.17 - a
fresh !RunImage listing 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 put
text underneath the sprite on the iconbar 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 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.

But things are a little more clever than this. Firstly, 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$.
Secondly, 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.

Just a couple of pieces of practical advice here:

- 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.

Finally, dont forget that the iconbar icon has its own wimp-functions
for changing its text and its icon- PROCwimp_puticonbartext and
PROCwimp_iconbaricon respectively.

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



(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.)

     
     


     

.. 15. 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, from Version 3.60 , the ability to
create menus of the fonts loaded in your machine has been added.

Please note that from Version 3.56 Dr Wimp creates all the title and
item text in menus as indirected - and you no longer 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.

From Dr Wimp Version 3.61, 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. 

If you want to change one or two menu items to reflect something in
your application like: Save selection or Save depending in this
case on whether anything was selected or not, then use
PROCwimp_putmenutext instead, as all the attributes are then retained.

If, by recreating your menu an item is moved up or down, then its
item% item number which is passed to user-function will change
accordingly. (Remember this for the Quit item - the tip given earlier
is very useful here.) The top item is always number 1.

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, although
it could be made 0 (which would mean that more items than three cannot
be added) it makes more sense to set it as the same size as maxitems%


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

PROCwimp_recreatemenuarray(menu%,array$())



Menus from Messages 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.

From Dr Wimp Version 3.61 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. In its parameters it passes the
handle of the sub-menu/window about to be opened (in nextsubmenu%),
the menu item number of the item with the arrow-head (parentmenuitem%)
and the x/y values (in screen OS units) of the pointer position when
moving over the arrow head. (Note that the first parameter has a
RETURN in front of it. The use of this will be explained later in this
section.)

This user-function paves the way 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(RETURN nextsubmenu%, 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.

A more 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 works for cascaded sub-menus in the same way i.e.
if you have a fourth sub-menu to be opened from a third sub-menu then
PROCuser_overmenuarrow will be called with the fourth submenu handle
and the third sub-menus item number in the parameters.

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(RETURN nextsubmenu%,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
manipulate your menus very dynamically - yet very simply.



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.)

Version 3.60 of Dr Wimp added facilities 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
(from Dr Wimp Version 3.63 onwards) 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.

From Dr Wimp Version 3.63 onwards you can 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_initialisation 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 this font menu when <menu> is pressed over a particular
window, then you might code of FNuser_menu() as follows:

DEF FNuser_menu(window%,icon%)

return%=0

CASE window% OF
     WHEN main%

   FontMenu1%=FNwimp_createfontmenu(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 pressing <select> or
<adjust> then you would use PROCuser_mouseclick() and display the menu
- again, just after a re-creation call - with PROCwimp_menupopup()


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%)

return%=0

CASE window% OF

WHEN Iconbarmenu%

      FontMenu1%=FNwimp_recreatefontmenu(FontMenu1%)

      return%=FontMenu1%

WHEN main%

   FontMenu1%=FNwimp_createfontmenu(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%)

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(RETURN nextsubmenu%, 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 first 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 (from Version 3.63):

-  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)
         <etc.>

    WHEN FontMenu2%

    selectedfonthandle2%=FNwimp_getfont(font$,16)
         <etc.>

    ENDCASE

ENDIF

....

....

ENDPROC

To help take better advantage of the font menu facilities Version 3.60
also introduced a new wimp-function:

PROCwimp_puticonfont(window%,icon%,fonthandle%)

which 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.



     
     


     

.. 16. 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 used for many purposes e.g.
raytracing, calculating numbers, loading data, file finding, etc. We
are not going to show you how to write a raytracer, etc. but rather to
show you how to make operations like these multitask easily.

In Section 1.4 of this Manual we briefly introduced the special Dr
Wimp global variable NULL%. Well, here is where it can come into play.

One method of effecting multitasking is simply to set NULL% to TRUE at
some point in your programme. As soon as this happens, the Wimp poll
starts calling PROCuser_null every time that it receives a no-action
needed Reason Code from the Wimp - which means more or less
continuously. Every time PROCuser_null is called, you would need to do
a small bit of work, each time remembering where you were up to and
noting where youve reached. This can make very tangled code. The
difficulty lies in storing where you got up to, and this can require a
multitude of variables for just one operation.

A much easier method is to use PROCwimp_singlepoll. When called, it
goes through the polling loop just once. Your operation will already
be in some sort of 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.

In the tutorial !RunImage listing, change PROCuser_menuselection so it
has lines like:

CASE menu% OF

WHEN iconbarmenu% :
     CASE item% OF

       WHEN 1 : PROCchangeauthor

       ENDCASE

ENDCASE

And 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$)

NEXT L%

ENDPROC

Now run !MyApp and choose 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.

Note: PROCwimp_singlepoll acts just like PROCwimp_poll. If one of your
icons is clicked on, then PROCwimp_mouseclick is still called, and if
your application received messages, then they are acted on, and so on.

Also note that there is another function that can be used for polling;
PROCwimp_pollidle


As was said above, if you set NULL%=TRUE then every time that the Wimp
is polled and no events have occurred, PROCuser_null will be called.
But if, instead, you used the following:

PROCwimp_pollidle(30,1)

then PROCuser_null will be called only every 30 seconds.

This reduces the load on the processor and is best used for things
like clocks, etc, where you would only need to update the clock once a
second or minute. (If, instead, you had called PROCwimp_pollidle(30,0)
then PROCuser_null would have been called every 30 centi-seconds i.e.
3 times a second, roughly. The second parameter determines whether the
first parameter value is taken as seconds or centi-seconds.)

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


There is also the complement of PROCwimp_pollidle,
PROCwimp_singlepollidle, which is the same but polls the Wimp only
once instead of repeatedly.

In passing, the above addition of DEF PROCchangeauthor to our tutorial
!RunImage listing shows how straightforward it is to add a
custom-built DEFPROC/FNs to the !RunImage in the usual Basic way.
They integrate with Dr Wimp without bother and their structural
advantages are therefore still available.     
     


     

.. 17. Bars

When you format a floppy disc a horizontal 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. Again, when you open the task
display you are shown lots of bars that depict the amount of memory
something is using up.

In essence, bars can make information look much more attractive than
numbers and DrWimp makes it simple to manipulate them.

(In Dr Wimp, the difference between a bar and a slider is that the
former merely represents a value passively, whereas the latter also
allows you to set the value. See Section 2.18 for sliders.)

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.

Make a fresh copy of !MyApp. From the Tutorial folder, drag the
Template5 file into the !MyApp directory, and rename it as
Templates. 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 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 is, so load the
templates into !TemplEd by dropping the file onto !TemplEds iconbar
icon.

Open the main window by double-clicking on it in the window at the top
left. Expand the icon info window at the top right to full size and
move the pointer over the bar.

The icon info window gives the dimensions of 340x36, so the max length
is 340. Of course we could extend the icon to whatever size we want
using !TemplEd, and then using that length.

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

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 frame icon behind it.

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.

And just to finish off, alter PROCchangelength to:

DEF PROCchangelength

pcent%=0

REPEAT

      nlen=(340/100)*pcent%

       PROCwimp_bar(main%,1,nlen,0)

       PROCwimp_singlepoll

       pcent%+=2

UNTIL pcent%>100

ENDPROC



You should be able to see that it is now the basis for a multitasking
operation with the percentage done depicted by the bar. Put the
operation inside the loop, and each time round the loop calculate the
percentage done instead of incrementing it as we have done.

[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.]



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 !TemplEd window.
However, if the bar is going to be changing in size rapidly then the
part of the border at the right edge will 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.

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

     
     


     

.. 18. Sliders

(In Dr Wimp, the difference between a bar and a slider is that the
former merely represents a value passively, whereas the latter also
allows you to set the value. See Section 2.17 for bars.)

Sliders can be very useful. You see them probably most in colour
selection windows, where you can use them to choose the amounts of
red, green and blue by dragging.

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 however can be any
thickness, length or colour you like.

Look at how the sliders are constructed in the supplied templates file
if it is still not quite clear.

Copy the file Template6 from the Tutorials folder into !MyApp and
rename to Templates.

After the line where the main window is loaded in 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 user-functions.



FNuser_sliderback is used to tell the Wimp which slider back icon is
linked with which slider icon. For the top slider (loading the
templates into !TemplEd will show this), 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 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.

A slider is no good unless you can get a value for it. When a slider
is moved or dragged, PROCuser_slidervalue is called, and the
percentage of the slider concerned (and its direction, hor/vert) is
passed. So add the following lines to it:

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.

Run the application now and you will see the percentage displayed in
the box on the right.

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 work, and you can see how many sliders
can be used in many windows.

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

The 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.27 - a
fresh !RunImage listing will be started.]



The example application !Sliders shows a typical application with both
horizontal and vertical sliders. In addition it introduces
nudgers/bump icons which are often used to complement sliders/bars
by providing a means to fine-tune values set with a slider/bar. The
!Sliders listing will show that bumpicons/nudgers are simple to
implement using standard Basic statements.

The application !Sliders also demonstrates 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).     
     


     

.. 19. Loading & Saving Drawfiles

We are not going to add drawfiles to the !MyApp tutorial here as the
!DrawDisp application in the Examples folder shows how it is done in
detail. Instead we will cover some points that are important to the
process.

Firstly, it is as well to recap that - unlike sprites, where one
sprite-file can hold more than one sprite (see Section 2.12) - the
contents of a drawfile are invariably regarded as one drawing. This
drawing may consist of many individual objects (which can include
both sprite and JPEG images) but none of them can exist as an entity
outside of a drawfile. To help remember this difference, this manual
refers to a drawfile as one word but uses the hyphenated form for
sprite-file.

Drawfiles are handled in a very similar way to spritefiles (see
Section 2.12). That is, the drawfile(s) to be loaded are measured for
size and a memory block is created accordingly, giving it a handle -
which effectively points to the start of the memory block. Drawfiles
are then all loaded in sequence into this block and we end up with a
discrete handle/pointer for each drawfile within the block.

As was said before, the sequence is simple but must be adhered to
strictly.

For drawfiles, there is only one additional step: we need to call
PROCwimp_initdfiles at the start of the process. What this does is
create a few special memory blocks needed when rendering drawfiles to
the screen or when printing them.

To demonstrate the complete process, lets assume that we have three
drawfiles already waiting within the !MyApp directory. If we want to
load them for use in our application we might use the following code
in PROCuser_initialise:

PROCwimp_initdfiles :REM** Sets up some special memory blocks needed
when rendering drawfiles. **

REM** Measure file sizes. **

path1$=\"<MyApp$Dir>.Drawfile1\"

path2$=\"<MyApp$Dir>.Drawfile2\"

path3$=\"<MyApp$Dir>.Drawfile3\"

size%=0

size%+=FNwimp_measurefile(path1$)

size%+=FNwimp_measurefile(path2$)

size%+=FNwimp_measurefile(path3$)

REM** Create memory block of total size needed. **

DIM drawfiles% size%

REM** Load drawfiles into block and capture handle of each. **

REM** (Here using an array for handles - optional method. **

DIM dfilehan%(3) 

dfilehan%(1)=drawfiles%:REM** Start of block is first handle. **

dfilehan%(2)=FNwimp_loaddfile(path1$,dfilehan%(1))

dfilehan%(3)=FNwimp_loaddfile(path2$,dfilehan%(2))

d%=FNwimp_loaddfile(path3$,dfilehan%(3))

So you end up with dfilehan%(1) as the handle for the first drawfile,
dfilehan%(2) as the handle for the second, etc. The unused dummy
handle is d%. The only difference from our sprite-file example is that
here we have used an array to hold the handles - but this is not
necessary.

As before, never try to work out the sizes of the drawfiles using any
other method but FNwimp_measurefile, otherwise you may run into
trouble.

If there was only a single drawfile, the process would reduce to:

PROCwimp_initdfiles

path1$=\"<MyApp$Dir>.Drawfile1\"

size%=0

size%+=FNwimp_measurefile(path1$)

DIM drawfiles% size%

DIM dfilehan%(1)

dfilehan%(1)=drawfiles%

d%=FNwimp_loaddfile(path1$,dfilehan%(1))

You could in this case remove the dfilehan% array and just have
drawfiles% as the handle, but that is up to you to choose which you
prefer.

Drawfiles which have been loaded by the above process can be saved
individually to a file using PROCwimp_savedfile. E.g. to save the
first drawfile to a path stored in path$:

PROCwimp_savedfile(path$,dfilehan%(1))



(N.B. When you are familiar with the process you could alternatively
use a dynamic area for the memory block instead of DIMming. See
Section 2.28.)

     
     


     

.. 20. Rendering Drawfiles & Sprites

Drawfiles and sprites can be rendered (drawn!) straight onto the
screen at a specified position or into a window similarly. The latter
is usually much more useful, but is only a derivative of the former.

In both cases, the drawfile/spritefile must have previously been
loaded in one of the previously described ways - or, from Version 3.56
onwards, sprites in the Wimp sprite pool can also be rendered
directly. (From Dr Wimp Version 3.64, JPEG objects within drawfiles
are rendered and/or printed correctly.)

The wimp-functions provided for rendering drawfiles and sprites allow
scaling in the x and/or y direction, but any other required
translation e.g rotation/shearing/reversal etc. of objects needs to be
done previously in the source sprite/drawfile.

The following notes treat drawfiles first and then sprites.

Drawfiles

Within drawfiles, all the standard types of object - except one -
are duly rendered by Dr Wimp (i.e. paths, text, sprites, transformed
text, transformed sprites and, from Dr Wimp Version 3.64 onwards, JPEG
objects). The exception is the special drawfile text areas - including
text column objects. These are very complex and are not rendered.
Fortunately, they are rarely used.

PROCwimp_render renders drawfiles directly onto the screen. The screen
OS coordinates of the bottom left corner are supplied, and two pairs
of coordinates to define a clipping rectangle. Any objects lying
totally outside the clipping rectangle are not rendered.

It is complemented by PROCwimp_renderwindow which renders a drawfile
in a window, and is designed to be called inside PROCuser_redraw. For
example, with:

IF window%=main% THEN
     PROCwimp_renderwindow(main%,dfile%,dfilesize%,50,-250,
minx%,miny%,maxx%,maxy%,xscale,yscale,origin%)

ENDIF

which specifies that the bottom left corner of the rendering of dfile%
shall be at the point 50, -250 (OS work units) in the window main%




Note that in order for PROCuser_redraw to be called, a window must
have its auto-redraw flag unset in the template editor.

dfile% is the drawfile handle i.e. the memory address at which the
drawfile has been loaded

xscale and yscale are the scaling factors. They are real numeric
variables and only positive scale values can be used (i.e values
greater than 0). Values less than 1 will reduce the displayed size of
the drawfile and values greater than 1 will increase it. That is, the
value 1 represents no change i.e. the rendered drawing will be at
the same size as the source drawing. 

origin% is a flag to activate an optional feature which can be very
useful. 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


Lastly, FNwimp_getdfilesize returns the width and height of a drawfile
so a window could, for instance, be resized to the size of the
drawfile and then displayed in it. (This wimp-function returns the
sizes of the bounding box containing all the objects.)



Sprites

Rendering sprites in Dr Wimp is a very similar process to rendering
drawfiles, although sprites do not need an equivalent to the above
origin% flag.

PROCwimp_rendersprite is the sprite equivalent to PROCwimp_render and
works in exactly the same way, but instead of having a drawfile
handle, there is the sprite name and the user sprite area handle which
contains that sprite.

The wimp-function for rendering a sprite in a window is
PROCwimp_renderwindowsprite, and for finding the dimensions of a
sprite is FNwimp_getspritesize


The following is an example for rendering a sprite (assuming it has
already been loaded into a user sprite area whose handle is
spritearea%):

IF window%=main% THEN

PROCwimp_renderwindowsprite(main%,\"test\",spritearea%,50,-250,
minx%,miny%,maxx%,maxy%,xscale,yscale)

ENDIF

Pool sprites

A further option is available for rendering sprites which are in the
Wimps sprite pool.

The Wimp pool is intended for sprites which are available for common
Wimp operations. Thus, all the icons for a windows furniture will
be in this pool, as well as sprites intended for standard file  icons
e.g. Basic/Obey/Text/Draw/Paint/Help/Printers etc. files. Pointer
shapes are also found here.  (A look at the spritefiles inside
Resources:$.Resources.Wimp will show the range of sprites  typically
in the Wimp sprite pool.)

You will also 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.

If a sprite is already in this pool then you can use the
above-mentioned pair of wimp-functions  (PROCwimp_rendersprite and
PROCwimp_renderwindowsprite) to render the pool  sprite - simply by
using the sprites name in spritename$ and by setting the spritearea% 
parameter to 0. There is no need to load the sprite separately into a
user sprite area.

Similarly, the use of FNwimp_getspritesize has been extended so that
you can find the width/ height of a pool sprite by using the value 0
in its spritearea% parameter - see Section 3.8

(N.B. Although the Wimp sprite pool method offers the opportunity to
treat any  sprite this way simply by including it in an *Iconsprites
call, it does have the  major disadvantage of taking up memory space
even after the application has  been quit. In contrast, the user
sprite area method is to be much preferred in this  respect - see
Section 2.12.)

In the Examples folder there is a full application demonstrating these
rendering operations.



Possible practical problems

The most common practical problems with rendering graphics (and text)
concern getting the coordinate conversions right - always remembering
that the actual Wimp plotting/printing coordinates will need to be in
screen coordinates (or, for printing, paper coordinates) whereas
you will often need to do all your design thinking in work area
(window) coordinates. DrWimp provides all the necessary conversion
functions. Dont forget that, in windows, all visible y work area
coordintes will be negative.

By and large, if your rendering action (or printing action) appears to
produce nothing visible yet no error messages appear, then a common
problem is that the rendering is actually off-screen/off page or
outside the window (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.)

Finally, 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.


(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.)     
     


     

.. 21. JPEG files



You will not be able to use Dr Wimps JPEG facilities if your RISCOS
Version is less than 3.60

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).

(JPEG images - as with sprites - can also exist within a drawfile.
From Dr Wimp Version 3.64 onwards, JPEG objects in drawfiles are
automatically rendered/printed using Dr Wimps drawfile facilities -
see Sections 2.19 and 2.20.)

Dr Wimp has the following wimp-functions to handle JPEGs:

FNwimp_loadjpegfile(jpegfilepath$,address%)

This wimp-function is entirely similar to FNwimp_loadsprites() and
FNwimp_loaddfile() i.e. it is used to load a JPEG file into a block of
memory starting at the address address%. It is very important to use
the same procedure (see Section 2.12) as for sprite-files and
drawfiles. That is, the size of the file must firstly be measured with
FNwimp_measurefile() and then the corresponding memory block must be
created (either by using DIM or creating a dynamic area). The loading
of a JPEG file (or files) can then follow.



FNwimp_getjpegsize(jpeghandle%,side%)

FNwimp_getjpegsizefile(jpegfilepath$,side%)

These are a complementary pair which allow you to find the width and
height (in OS units) of a JPEG image. If the JPEG image is already
loaded into a memory block using FNwimp_loadjpegfile(), then the first
function is used. The second function reads the same information
directly from a JPEG file.

PROCwimp_savejpeg(savepath$,jpeghandle%)

Saves to file a JPEG which has already been loaded into memory (by
FNwimp_loadjpegfile())

PROCwimp_renderjpeg(jpeghandle%,bx%,by%,minx%,miny%,maxx%,maxy%,xs-calereal,yscalereal)

PROCwimp_renderwindowjpeg(window%,jpeghandle%,bx%,by%,minx%,miny%,-maxx%,maxy%,xscalereal,yscalereal)

The above two functions display/print a JPEG image (optionally scaled)
- either using screen OS units or window work units. The image must
already be loaded into a memory block whose handle is jpeghandle% -
returned from FNwimp_loadjpegfile(). They are entirely similar in
operation to their sprite and drawfile counterparts and reference to
Section 2.20 should be made for the detail.



PROCwimp_renderjpegfile(jpegfilepath$,bx%,by%,minx%,miny%,maxx%,ma-xy%,xscalereal,yscalereal)

PROCwimp_renderwindowjpegfile(window%,jpegfilepath$,bx%,by%,minx%,-miny%,maxx%,maxy%,xscalereal,yscalereal)

These two functions allow a JPEG file to be displayed directly i.e.
without first loading it into a memory block. However, the JPEG image
cannot be printed using these two calls. (This is a RISCOS feature,
rather than a Dr Wimp limitation.)

     
     


     

.. 22. Validation Strings

Each icon 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 vaidation string unless the icon is
made indirected.

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 !TemplEd you will see that
the validation string is R6,3. Try changing the 3 to 7 or 11.

In Section 2.12 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 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.)

     
     


     

.. 23. 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 !TemplEd


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
early in Section 2. An indirected icon can also have a validation
string - see Section2.21

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 make an icon indirected with an indirected size of,
say, 16 and then use PROCwimp_puticontext to put in a string greater
than 15 characters long (15 plus terminator equals 16), strange things
may happen - solely because you are starting to overwrite memory which
is being used for another purpose. A common effect is that if the icon
has a 3D border then it is lost. Another effect - if your desktop is
configured to use an outline font - is that the desktop text reverts
back to System font. The more you go over the limit, the messier
things get - so dont!

     
     


     

.. 24. Text Handling

You should, by now, be able to plot drawfiles and sprites in a window
(using PROCuser_redraw). With DrWimp it is also possible to plot text
in a variety of ways directly onto a window or the screen.

General principles

With 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.

Some of the wimp-functions require the name of the font to be provided
and others use the font handle instead. The font names always have
to be what is called period separated. For example:

\"Trinity.Medium\"

\"Homerton.Bold.Oblique\"

\"Corpus.Medium.Oblique\"

i.e. there are periods (full stops) between each part - conforming
with file naming, in fact.

PROCwimp_plottext is the most basic function provided, and simply
plots a string of text onto the screen at the required position. It
has rather a lot of parameters but they are straightforward i.e. the
text, the name of the font you want to use, the point size and
foreground and background colours and the screen OS units position
where you want the text to start.

PROCwimp_plotwindowtext does the same but plots the text in a window,
so it needs the window handle and the position is given in work area
OS units. (As plotting text in a window this way is simply another
form of graphics plotting, you would use this inside PROCuser_redraw,
as with PROCwimp_renderwindow and PROCwimp_renderwindowsprite.)



Font handles

Fonts can have handles, just like windows, drawfiles, sprites, etc. In
fact, the Wimp needs font handles and uses them in a way more akin to
file opening/closing. e.g. a font handle is needed before text
plotting can take place and the font ought to be closed after its
last use.

Whenever PROCwimp_plottext or PROCwimp_plotwindowtext is called, a
handle for the font is found automatically behind-the-scenes before
the string is plotted. If you are plotting many lines of text, all
this handle finding can take a lot of time - so DrWimp provides a way
of overcoming this by providing a wimp-function to find the handles
for you, plus a set of slightly different wimp-functions to plot the
text with them.



FNwimp_getfont returns a font handle when you tell it the font you
require and the point size.

You would thus normally get all the handles you require when your
application loads, in PROCuser_initialise. (0 is returned if the font
could not be found so you would have to take into account of this and
perhaps find an alternative and warn the user.)

For example:

trinity12% = FNwimp_getfont(\"Trinity.Medium\",12)

To plot text specifying the font handle, PROCwimp_plottexth and
PROCwimp_plotwindowtexth are used. Note the h on the end of the
function name to denote that those functions accept font handles
instead of fonts names and sizes.

Typically placed inside PROCuser_redraw, the following is an example
of the coding used:

IF window%=main% THEN

PROCwimp_plotwindowtexth(main%,\"Test\",trinity12%,50,50,0,0,0,
255,255,255,minx%,miny%,maxx%,maxy%)

ENDIF

Note the foreground and background colours. 0,0,0 sets the foreground
to black, and 255,255,255 sets the background to white.

Finally, when you have finished with a font, you should call
PROCwimp_losefont. For example:

PROCwimp_losefont(trinity12%)

From Dr Wimp Version 3.61 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.



Modifying the text with control codes

Not just simple strings of text can be plotted. Strings of control
code sequences can be inserted into the string 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 only apply for that line only


Checking the text size before plotting

There are two functions for finding the width and height of a string,
as if it were plotted on the screen. They are FNwimp_gettextsize and
FNwimp_gettextsizeh, with the latter using font handles instead of
font names and sizes. These wimp-functions are very useful for
positioning text accurately - particularly for vertical alignment.

Matching the desktop font

Finally, there are two functions which also plot text, both on the
screen and in windows, but they don't always plot with outline fonts.
The functions are PROCwimp_deskplottext and
PROCwimp_deskplotwindowtext and they plot using the current desktop
font - either straight to the screen or to a window, respectively.

These two functions are useful for matching the fonts displayed
directly onto the window with that used by default in icons. You
supply the string to plot, the position and the foreground and
background colours. There is an extra parameter which allows you to
choose whether to plot with the left side of the text at the
x-coordinate, or plot with the text centred on the x-coordinate. 

On pre-RISC OS 3.5 machines, only the system font can be used for
the desktop font, so that is what will be used with the above
wimp-functions. However, on RISC OS 3.5+ machines the desktop font
can be configured to be an outline font or the system font. Therefore
the above wimp-functions will then use whatever the desktop font is
configured to be.



     
     


     

.. 25. 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
Surgerycovers printing in 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!)

Either way, 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.

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. 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.

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

         x%=FNwimp_worktoscreen(print%,316,0)

         y%=FNwimp_worktoscreen(print%,-256,1)

         PROCwimp_setforegroundcolour(160,160,160)

         RECTANGLE FILL x%,y%,w%,h%

         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_setforegroundcolour(255,255,255)

         RECTANGLE FILL x%+lm%,y%+bm%,r%-lm%,t%-bm%

       ENDIF

ENDIF

which will draw in the window a small depiction of the paper in the
window with borders.

The key lines are the calls to FNwimp_worktoscreen which, as its name
says, takes a work area coordinate and translates it into a screen
coordinate. (It may be slow due to it having to find out if a printer
driver is loaded every time a bit of the window needs redrawing,
although you could optimise it to take into account the redraw
clipping rectangle passed to PROCuser_redraw.)

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. This is done in
the user-function PROCuser_declarefonts and Dr Wimp provides all the
necessary functions to make it straightforward.

Similarly, if you going to print any drawfiles that contain fonts,
then the fonts in them also need to be declared - again via a provided
wimp-function.

In the user-function PROCuser_declarefonts you must call, for each
font, either PROCwimp_declarefont if you want to supply the font name,
or PROCwimp_declarefonth if you want to give the font handle instead.
For drawfiles with fonts in them you simply call
PROCwimp_declaredfilefonts, giving the handle of the drawfile, for
each drawfile. For example:

DEF PROCuser_declarefonts
     PROCwimp_declarefont(\"Trinity.Medium\")

       PROCwimp_declarefonth(homerton18%)

       PROCwimp_declaredfilefonts(dfilehan%(1))

ENDPROC



See the section on text handling (Section 2.24) for more information
on font handles and period separated font names, and see the section
on loading drawfiles (Section 2.19) for more information on drawfile
handles.



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%,perpage%, copies%,orient%)

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. window% is ignored if printing with the user method - but a value
must be present, of course.

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.

perpage% can currently be either 1, 2, or 4. If you set it to 1 then
each page will fit on a physical A4 page. If you specify 2 then two A4
pages will be scaled to about 70%, rotated through 90 degrees, and
placed side by side on a physical A4 page. If you specify 4 then each
page will be scaled to 50% and four pages will be printed in portrait
mode on a single physical A4 page. 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.

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 perpage% 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 argument 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.

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 text is placed at the
work area coordinates 50,-100


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%,x%,y%,
0,0,0,255,255,255,minx%,miny%,maxx%,maxy%)

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%,x%,y%,
0,0,0,255,255,255,minx%,miny%,maxx%,maxy%)

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).

And - after all that setting up - thats it!



Now, take a look at another example:

DEF PROCuser_redraw(window%,minx%,miny%,maxx%,maxy%, printing%,page%)

IF window%=main% THEN
     x%=50:y%=-200

       PROCwimp_setforegroundcolour(255,0,0)

       x%=FNwimp_worktoscreen(main%,x%,0)

       y%=FNwimp_worktoscreen(main%,y%,1)

       RECTANGLE FILL x%,y%,100,100

ENDIF

ENDPROC

which will draw a red square with the bottom left corner at the work
area coordinates 50,-200. Note that it differs from the previous
text-plotting case in that it is necessary to convert the work area
coordinates to screen coordinates for the rectangle plotting action.
(Had we plotted a sprite/drawfile instead we could use
PROCwimp_renderwindowsprite/dfile which would do this work-to-screen
conversion automatically.)

Now here is the modified version which will allow the square to be
printed out on a portrait page:

DEF PROCuser_redraw(window%,minx%,miny%,maxx%,maxy%, printing%,page%)

IF window%=main% THEN

      x%=50:y%=-200

       PROCwimp_setforegroundcolour(255,0,0)

       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

       RECTANGLE FILL x%,y%,100,100

ENDIF

ENDPROC

That is, when printing% is TRUE, the screen coordinates are converted
into paper coordinates - and thats all.

One thing to note is that the top left corner of the window main%
matches up with the top left corner of the paper.

(From Version 3.59 there is a wimp-function which automatically
carries out the above routine to plot/print a rectangle in a window.
However the above has been retained here as a useful explanation of
the general process.)



Now for an example of printing the page number at the bottom of each
page.

You can work out the work area coordinates and/or the page coordinates
to place the text, but 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%,x%,y%,
0,0,0,255,255,255,minx%,miny%,maxx%,maxy%)

ENDIF

ENDPROC

The text is plotted 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%,x%,y%,
0,0,0,255,255,255,minx%,miny%,maxx%,maxy%)

       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.

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 and the process is usually simpler than
in the above redraw method.

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 as OS screen units, with the origin at the bottom
left corner of the paper.

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_setforegroundcolour(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_setforegroundcolour(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.

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 five parameters set
to 1,1,1,1,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.     
     


     

.. 26. 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
!TemplEd utility (by Dick Alstein) 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 now be described
in detail.

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, from Version 3.57, 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, from Version 3.57, 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. If not
then this should be set to 0.

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%,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)

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,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). 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.

Final points

To end this section, there are a few corollary 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)

If you are deleting several icons in sequence then it is sufficient
(and more efficient) to force the redraw only with the final deletion.



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.

Finally, 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 Application memory
needs.



If you used FNwimp_createicon and/or FNwimp_createwindow in an
application using a Dr Wimp version earlier than 3.57, then you will
not be able to use exactly the same calls in an application using
Version 3.57 or later - because the flag values are not equivalent.

There is, of course, no need to change things in the old application.
However, if you want to upgrade your old application to use a Dr Wimp
version from 3.57 onwards (or simply want to copy the
FNwimp_createicon and/or FNwimp_createwindow calls from the old
application into a new one to achieve the same results) then a special
conversion utility called !FlgConv is included in the Utilities
folder.)     
     


     

.. 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 copy the file Template7
from the Tutorials folder into !MyApp and rename to Templates. Then
load the window into your tutorial !RunImage, with the handle warn% -
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 your Tutorial !RunImage:

a) Incorporate the Templates from Template7 as stated earlier in
this Section.

b) add the line:

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

to PROCuser_initialise


c) add the line:

unsaved%=FALSE

to PROCuser_initialise


d) Make DEF FNuaer_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. Dynamic Areas

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 problem with this is that the size of the block, and hence
the maximum size of data that can be loaded in is hard-wired into
the program.

One 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 this solution is therefore not ideal.

A better solution is to use a dynamic area.

Dynamic areas

A dynamic area is a block of memory, just like the example defined
above, but it can shrink and expand in size. The memory is taken from
and returned to the free application memory pool as the block changes
size, thus the only limit with the size of a dynamic area, is the
amount of memory in the machine. Another advantage is that it does not
form part of the WimpSlot, and so can be used without adjusting the
WimpSlot size.

The type of dynamic area available depends on the OS Version being
used. On versions of RISC OS 3.5 and higher, an application can create
its own, separate dynamic areas (which also appear in the Task Manager
display). These will be referred to as ADAs, for Application Dynamic
Areas - and, once created, these can then be expanded or shrunk as you
wish.

However, for RISC OS Versions lower than 3.50 (but 3.10 or higher)
dynamic areas need to be created in the Module Area (RMA) instead -
which is not as flexible as ADAs because it is shared by other
applications. This can cause problems if you are using many dynamic
areas and/or changing their sizes a lot.

The Dr Wimp dynamic area functions have therefore been written to use
both the RMA and ADAs transparently. This means you can write your
application to use dynamic areas without worrying which RISC OS
version is being used: Dr Wimp will take care of it automatically.

However, if you are using RISC OS 3.5 or higher but you are worried
how your application will fare under a lower OS version, you can force
DrWimp to create dynamic areas in the RMA, so you can see how your
application will behave on older machines.

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%,type%,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.

type% takes the value of 0 or 1. If set to 0 then Dr Wimp will
automatically choose between ADA and RMA dynamic areas according to
the OS Version being used (as explained above). It is recommended that
you should normally use 0. If set to 1 then Dr Wimp will only use the
RMA area, whatever the OS Version.

drag% and name$ only take effect if type% is set to 0 and the OS
Version is 3.50 or higher. In those circumstances these final two
parameters affect the Task Display. 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,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 area will be
created as an ADA if the application is run on a machine with OS
Version 3.50 or higher - or in the RMA otherwise. If the former then
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.

After creation in this way, you can store data in the block , such as
drawfiles, spritefiles, or anything you like. The previous examples
given for sizing and loading sprite-files (Section 2.12) and drawfiles
(Section 2.19) need only substitute a dynamic area handle for the
DIMmed handle. For example, if a sprite-file has the path path$:

size%=FNwimp_measurefile(path$)

block%=FNwimp_createdynamic(size%,size%,0,0,Sprite Files)

d%=FNwimp_loadsprites(path$,block%)



Changing size



FNwimp_changedynamic(darea%,absolute%,size%)

changes the size of an existing dynamic area. 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.

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)

In all these cases, the returned address may not be the same as for
the original dynamic area.

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 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 - to avoid wasting memory. Simply use:

PROCwimp_deletedynamic(darea%)



(Note: From Version 3.55 onwards 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.)



Final point

Dont forget, any place that uses a DIMed memory block can usually
equally well use a dynamic area.

     
     


     

.. 29. Colour picker

Please note that although Version 3.54 of Dr Wimp is expected to work
with RiscOS Versions earlier than 3.50, they will not be able to use
the Colour Picker wimp-functions described below. If you are using an
earlier RiscOS Version there is no need to change anything to
compensate for this - just dont call the Colour Picker
wimp-functions!

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 displated 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%)

and

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 work area 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%)

and

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(nextsubmenu%,parentmenuitem%,x%,y%)

CASE nextsubmenu% OF
     WHEN wSUBMENUCOLOURPICKER%
     PROCwimp_opensubmenucolourpickermodel(1,0,40,55,20,1,x%,y%)

ENDCASE

ENDPROC

Its as easy as that.

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.     
     


     

.. 30. General file loading/saving to/from memory

From Dr Wimp Version 3.58 a general file loader and saver is included
- specifically for loading files into a block of memory and for saving
a file from a previously-loaded memory block - in a similar way to
that used for Spritefiles and Drawfiles earlier. The new general
loader/saver wimp-functions can be used with any files except
Spritefiles/Drawfiles/JPEGs which have their own special facilities -
see Sections 2.12/2.19/2.21 respectively


To use these general facilities it is important to follow the same
strict, but very simple, file measuring and loading procedure shown in
the above-referenced Sprite-file and Drawfile sections. It is repeated
here in outline for convenience.

1) Measure the file(s) to be loaded - using FNwimp_measurefile(),
which is the only wimpfunction common to all types of files. If there
is more than one file, use the routine:

size%=0

size%+=FNwimp_measurefile(filepath1$)

size%+=FNwimp_measurefile(filepath2$)

size%+=FNwimp_measurefile(filepath3$)

etc.

2) Create the corresponding memory space using DIM - or
FNwimp_createdynamic(). For example:

DIM fileblock% size%

3) Load the file(s) into the memory space using
FNwimp_loadfile(filepath$,handle%), for each file - as follows:

filehandle1%=fileblock%

filehandle2%=FNwimp_loadfile(filepath1$,filehandle1%)

filehandle3%=FNwimp_loadfile(filepath2$,filehandle2%)

dummy%=FNwimp_loadfile(filepath3$,filehandle3%)

(If there is only one file then a single line such as:

dummy%=FNwimp_loadfile(filepath1$,fileblock%)

will suffice.)

Your files will then be stored one after the other in the memory
block, yet each will have its own file handle to be used for
subsequent actions.

The wimp-function PROCwimp_savefile(savepath$,handle%,ftype%) can then
be used to save any such stored file (with handle handle%) to a place
of your choice (defined by savepath$) and with a filetype given by
ftype% (which must be the hex value e.g. &fff for a textfile).

     
     


     

.. 31. Wimp messages

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

&5               DataOpen

&8               PreQuit

&A               SaveDesktop

&502          HelpRequest

&400C0          MenuWarning

&400C1          ModeChange

&400CC          WindowInf

&47700          ColourPickerColourChoice

&47702          ColourPickerCloseDialogueRequest

&80147          SetPrinter

     
     


     

.. 32. Iconiser

Iconising is the result you get on pressing a windows Close icon
whilst holding down <shift> i.e. 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.

From Dr Wimp Version 3.55 your application responds 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 text beneath it will be the name that you used for
your application in FNwimp_initialise e.g. YourApp

However, 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, the default text will be your application name as put
in FNwimp_initialise. (The default sprite name will also be the same
text, but reduced to the leftmost seven characters if it was longer
than seven.)

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. (And
note that if the application is called LongerName, the default
spritename$ will be LongerNa.)

If you do nothing then the contents of spritename$ will not change and
the Wimp will be looking for an iconiser sprite called ic_yourapp
(or ic_longerna) - 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 YourAppMain 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$=YourAppMain
          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.

It is important to note that the Wimp does not allow sprite names to
be greater than 10 characters. Hence 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 default iconiser sprite will be used instead. From Version
3.56, you will be warned if your intended sprite name is too long.



(If you use !Fabricate - see Section 2.33 - the resulting customised
skeleton application will include a rough (very!) sprite for this
purpose, 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.)



     
     


     

.. 33. Grubby tasks

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
!MakeApp2 and !Crunch in the usual way, and then change the
PROCwimp_starttask to something like:

PROCwimp_starttask(Run <MyApp$Dir>.Mono)

     
     


     

.. 34. Bits & bobs

Here are a few other useful points.

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.

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 3.53 then it will
return 353.

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 window to the supplied width and
height. The work area is set to the new values. Use
PROCwimp_resizewindowvisible to alter displayed size.

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.22). 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


Icon selected/de-selected

FNwimp_geticonselect returns 1 if the icon is selected, or 0 if it
isn't.

Graphics colours

PROCwimp_setforegroundcolour and PROCwimp_setbackgroundcolour set the
current 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.

These functions are best used immediately before the plotting/printing
action to which they are to apply. In particular, when these functions
are required in a redraw process it is essential that they are 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_setforegroundcolour and PROCwimp_setbackgroundcolour,
described in the preceding sub-section.)

Storing strings in memory blocks

Memory blocks can be used as a compact way of storing strings, if you
know the maximum length for a string.

block%=FNwimp_createblock(10,25)

Will create a block that can store 10 strings, any of which can be up
to 25 characters in length. block% is the handle to the block.

PROCwimp_putinblock(block%,\"A string\",3)

Will put the string shown into position 3 in the block, whose handle
is block%


s$=FNwimp_getfromblock(block%,3)

Will extract the string from position 3 in the block whose handle is
block%


Hourglass

PROCwimp_hourglasson and PROCwimp_hourglassoff turn the hourglass on
and off respectively. The percentage display on the hourglass can be
set using PROCwimp_hourglasspercentage


Desktop save

From Dr Wimp Version 3.54 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 start-up options

From Version 3.80, a special global string variable called
wstartupoption$ has 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 -option1 -option2 %*0

or

Run <MyApp$Dir>.!RunImage -option1 -option2 <filepath$>



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.

You can then interpret this string as you wish in your application
coding.



Buffer space

Those of you who delve may wish to know that, from Version 3.57,
attempts have been made 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 will find them very 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.

!MakeApp this converts the !RunImage to absolute code. It does not
reduce the program disc storage need - nor the WimpSlot need, but it
makes it impossible to read.

!Crunch     (best used after !Linker, !StrongBS and !MakeApp) This
reduces the disc storage need even further, but does not reduce the
run-time needs.     
     


     

.. 35. 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
- see 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 value of 192kilobytes 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 not 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 and 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 Section 2.33) - 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 well 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 !TemplEd window template editor, the
Statistics option from its iconbar 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. !TemplEds Statistics window takes
this into account.)

     
     


     

.. 36. Saving time with !Fabricate

You will find that after writing a few applications, in most if not
all you are 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. It can do all those things for
you and save boredom setting in, leaving you to get on with writing
the interesting parts.

With !Fabricate Version 2.00 (released with Dr Wimp Version 3.57) a
considerable expansion of capability has taken place - as the first
step of what is hoped to be a developing Visual DrWimp exercise.

Apart from the previous options, the user can now design and
automatically incorporate a custom iconbar menu as an alternative to
the standard 2-item menu. Also the users own window template file can
now 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 Version 2.00 automatically builds an application which
can go a lot further than before down paths that many applications
need to follow.

Instructions for using !Fabricate are in the !Help file within its
application folder.

     
     


     

.. 37. Dr Wimps Elixirs

This is a new idea, introduced with Dr Wimp Version 3.70.

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 and one
wimp-function:

PROCuser_redrawtextline(x%,y%,line%)

PROCwimp_calcredrawlines(leftmargin%,topmargin%,totallines%,
                                             linespacing%)

If you want to use the elixir then both these functions 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)

ENDPROC

In the Examples folder there is an example application called !Scroll
to demonstrate Elixir_01.

If you have an idea for an elixir please contact the Dr Wimp author.

The best ideas come from actual users!     
     


     

.. 38. 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.argonet.co.uk/users/rayfavre/

or directly from:

     Email: rayfavre@argonet.co.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.

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.

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_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$,button%,prefix%)

Reports an error using a standard error box.

title$ = title of error window.

error$ = error message.

If button%=1 then will have an OK button.

If button%=2 then will have a CANCEL button.

prefix% = 0 then the title is title$.

If prefix% = 1 then the title is prefixed by Error from .

If prefix% = 2 then the title is prefixed by Message from .



FNwimp_errorchoice(title$,error$,prefix%)

Reports an error using a standard error box.

It has both OK and CANCEL buttons.

title$ = title of error window.

error$ = error message.

If prefix% = 0 then the title is title$.

If prefix% = 1 then the title is prefixed by Error from .

If prefix% = 2 then the title is prefixed by Message from .

Returns TRUE (-1) if OK pressed. FALSE (0) if CANCEL pressed.

(Note difference from usual Dr Wimp practice of returning 1 or 0)





FNwimp_testobjectpresent(path$)

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 then a non-fatal warning will be given and
the return is a null string.



FNwimp_getdirectoryobjectname(dir$,objectnumber%)

Returns name of specified object (i.e. file/application/directory) in

specified directory.

dir$ - full pathname of directory or application

(NOTE: Will give error if dir$ is not a 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.

(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 (i.e.

file/application/directory) in specified directory. A file will

return 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

(NOTE: Will give error if dir$ is not a 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.

(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_countdirectoryobjects(dir$)

Returns number of objects (i.e. files/applications/directories) in

specified directory.

dir$ - full pathname of directory or application

(NOTE: Will give error if dir$ is not a directory or application)



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.)



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.



FNwimp_getsysvariable(sysvar$)

Returns, as a string, the contents of the system variable sysvar$.

Note < and > are not required in sysvar$.

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$.

(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.



PROCwimp_hourglassoff

Turns off the hourglass.



PROCwimp_hourglasson

Turns on the hourglass.

PROCwimp_hourglasspercentage(percentage%)

Sets the percentage display on the hourglass.

percentage% is in the range 0 to 99.



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_setforegroundcolour(red%,green%,blue%)

Sets the current GCOL foreground colour 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.

(Best used immediately before corresponding plotting/printing action -
see Section 2.33 Graphics colours.)



PROCwimp_setbackgroundcolour(red%,green%,blue%)

Sets the current GCOL background colour 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.

(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$)

Returns the size in bytes needed to store a file in memory prior to
using FNwimp_loadfile(), FNwimp_loaddfile(), FNwimp_loadsprites() or
FNwimp_loadjpegfile().

Always use this as opposed to any other form of measurement.

filepath$ = full pathname of spritefile.

(This function is also listed in in other sections)



FNwimp_loadfile(filepath$,handle%)

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.

filepath$ = full pathname of file.

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_createblock(items%,length%)

Creates a block for storing strings in. Returns a handle

to the block. (Load/read block using PROCwimp_putinblock and
FNwimp_getfromblock only.)

items% = maximum number of strings to store.

length% = maximum possible length of each string.



PROCwimp_putinblock(block%,string$,pos%)

Stores a string in a block. (The block must have been created using
FNwimp_createblock).

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_createblock).

(Strings stored in this way can be read with FNwimp_getfromblock)



FNwimp_getfromblock(block%,pos%)

Returns a string stored in a block by PROCwimp_putinblock


block% = handle of block.

pos% = position of string in block (ranging from 1 to

maximum as passed to FNwimp_createblock).



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.





2. Polling

PROCwimp_poll

This function provides the main loop of your application.

When it has exited, your application has quitted.

During the loop operation, whenever something happens to your

application eg. an icon has been clicked on, then the relevant

action will be initiated from the loop.



PROCwimp_pollidle(duration,sec%)

If NULL%=TRUE then PROCuser_null will be called at each period set by
duration (instead of every time control is passed to the application
and no event has occurred). 

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 it is called once

and not in a loop. If something happens then the relevant action will

still be taken before returning.

Useful for making loops multitask, eg: raytracing,

printing, calculating, loading in data, etc.

Note: if calling in PROCuser_null, make sure NULL%=FALSE

before this call is made (can be set to TRUE afterwards) otherwise

recursion will occur.



PROCwimp_singlepollidle(duration,sec%)

The same as PROCwimp_pollidle, except that it is called

once and not in a 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.)

If something happens then the relevant action will be taken before
returning.

Useful for incorporating delays into multitasking loops.

Note: if calling in PROCuser_null, make sure NULL%=FALSE

before this 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%)

Responds to <menu> clicks. If you want a menu to be displayed when you
press <menu> over a specified window/icon, then this function needs to
return the handle of the menu required. Otherwise return 0.

window% = handle of window.

icon% = number of icon.

(<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.22 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 for a

specified window and icon. Otherwise return a null string.

window% = handle of window (containing icon).

icon% = number of icon.



FNuser_menuhelp(menu%,item%)

Return a string to be used for interactive help for a specified menu
and item. Otherwise return a null string.

menu% = handle of menu.

item% = number of item (starting from 1 at the top).



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%,icon%)

Called just before menu (not a sub-menu) is opened.

menu% = handle of menu just about to open.

icon% = icon which pointer is over ( or -1 if not over an icon).



PROCuser_overmenuarrow(RETURNnextsubmenu%,parentmenuitem%-,x%,y%)

Called when pointer moves over arrow-head against menu item,

on way to activating sub-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.)

parentmenuitem% = menu item number which pointer is moving over.

x%/y% are screen OS-unit positions of pointer when over

arrow-head.



PROCuser_modechange

Called when the mode is changed.



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.

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.

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, both text$ and spritename$ will be set to the application
name as declared in FNwimp_initialise.)

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.



PROCuser_redrawtextline()

NOT IN SKELETON !RunImage.

ONLY USED AS PART OF Elixir_01 for fast scrolling of long text lists
- see Manual Section 2.37 and 3.16 Elixirs

Needs to be used with PROCwimp_calcredrawlines().



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, or -3 for current stack position.



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 or -3 for current stack position.



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.

The necessary code needs to be in PROCuser_redraw to enable the redraw
to be done.

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.



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%)

Return 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.



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%,maxind%,sa-rea%)

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.

maxind% = maximum size of title if indirected.

sarea% = handle of sprite area, or 0 to use Wimp sprite area.

(See Section 2.26 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.37 and 3.16 Elixirs

Needs to be used with PROCuser_redrawtextline()



5. Messages

FNwimp_initmessages(path$)

Reserves special blocks of memory and sets up a Messages file ready
for use.

Returns a message handle for file.

path$ = full pathname of messages file to use.



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.



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_messlook0(messagefilehandle%,token$)

Returns the string in the messages file for the token token$.

messagefilehandle%= handle of required messages file (returned from
FNwimp_initmessages/FNwimp_reinitmessages above).



FNwimp_messlook1(messagefilehandle%,token$,a$)

Returns the string in the messages file for the token token$, but any
parameters %0 in the string are replaced with a$ before returning.

messagefilehandle%= handle of required messages file (returned from
FNwimp_initmessages/FNwimp_reinitmessages above).



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

Returns the string in the messages file for the token token$, but any
parameters %0 and %1 are replaced with a$ and b$, respectively,
before returning.

messagefilehandle%= handle of required messages file (returned from
FNwimp_initmessages/FNwimp_reinitmessages above).



FNwimp_createmessagemenu(messagefilehandle%,token$,title$,size%)

Creates a menu automatically from a Messages file.

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 Messages 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.15 for use of token$)

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) - the length of which
should not exceed the maximum indirected length specified in the icon
definition.



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.



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.



PROCwimp_iconbit(window%,icon%,bit%,state%)

Ensures a specific bit of an icons icon flags is set to the

specified state.

window% = handle of window containing icon.

icon% = number of icon.

bit% = number of icon flags bit to change.

state% =1 to set bit, or 0 to unset bit.



PROCwimp_putcaret(window%,icon%)

Puts the caret in the icon and gives window input focus.

window% =handle of window containing icon.

icon% = number of icon (or set to -1 if caret not wanted in icon)



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.26 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.



7. Menus

FNwimp_createmenu(menu$,size%)

Creates a menu structure from the string menu$. The menu

handle is returned.

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.

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 Messages file.

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 Messages 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.15 for use of token$)

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.15)

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%)

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.

(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.)





8. Sprites

FNwimp_measurefile(filepath$)

Returns the size in bytes needed to store a file in memory prior to
using FNwimp_loadfile(), FNwimp_loaddfile(), FNwimp_loadsprites() or
FNwimp_loadjpegfile().

Always use this as opposed to any other form of measurement.

filepath$ = full pathname of spritefile.

(This function is also listed in in other sections)



FNwimp_loadsprites(filepath$,address%)

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.



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).








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$)

Returns the size in bytes needed to store a file in memory prior to
using FNwimp_loadfile(), FNwimp_loaddfile(), FNwimp_loadsprites() or
FNwimp_loadjpegfile().

Always use this as opposed to any other form of measurement.

filepath$ = full pathname of spritefile.

(This function is also listed in in other sections)



FNwimp_loaddfile(filepath$,address%)

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.

filepath$ = full pathname of drawfile.



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. 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).

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.20)



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. 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).

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.20)



11. Text

FNwimp_getfont(font$,size%)

Obtains a font handle for a particular outline font at a particular
point size.

font$ = name of font, period separated. eg: Trinity.Medium.

size% = point size of font.

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$,size%,side%)

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.

text$ = string to measure.

font$ = name of font, period separated, eg: Trinity.Medium.

size% = point size 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.



FNwimp_gettextsizeh(text$,font%,side%)

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.

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.



PROCwimp_plottext(t$,f$,s%,x%,y%,fr%,fg%,fb%,br%,bg%,bb%)

Plots text directly to screen, using string-specified font.

t$ = string to plot.

f$ = name of font period spaced eg: Trinity.Medium

s% = point size of font.

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_plottexth(t$,font%,x%,y%,fr%,fg%,fb%,br%,bg%,bb%)

Plots text directly to screen, using font specified by font handle.

t$ = string to plot.

font% = handle of font.

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_plotwindowtext(window%,t$,f$,s%,x%,y%,fr%,fg%,fb%,br%,-bg%,bb%,minx%,miny%,maxx%,maxy%)

Plots text in a window, using string-specified font.

window% = handle of window to plot in.

t$ = string to plot.

f$ = name of font to use, period separated, eg: Trinity.Medium.

s% = point size of font.

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.)



PROCwimp_plotwindowtexth(window%,t$,font%,x%,y%,fr%,fg%,fb%,br-%,bg%,bb%,minx%,miny%,maxx%,maxy%)

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.

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.)



PROCwimp_deskplottext(t$,c%,x%,y%,fr%,fg%,fb%,br%,bg%,bb%)

Plots text directly to screen, using the current desktop font

(always the System Font on pre-RISC OS 3.50).

t$ = string to plot.

If c%=1 then text is horizontally centred around x%.

If c%=0 then left side of text is placed at x%.

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$,c%,x%,y%,fr%,fg%,fb%,br-%,bg%,bb%,minx%,miny%,maxx%,maxy%)

Plots text in a window, using the current desktop font

(always the System Font on pre-RISC OS 3.50). 

window% = handle of window to plot in.

t$ = string to plot.

If c%=1 then text is horizontally centred around x%.

If c%=0 then left side of text is placed at x%.

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.





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 - from which screen coords are calculated.)

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.)

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%,perpage%,copies%,o-rient%)

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.

perpage% = number of A4 pages to fit onto a physical A4 page. Can be

1, 2 or 4.

copies% = number of copies of the document to print.

If orient%=0 then page is portrait.

If orient%=1 then page is landscape.



13. Dynamic areas

FNwimp_createdynamic(size%,maxsize%,type%,drag%,name$)

Creates a dynamic area and returns a handle for it.

size% = initial size of dynamic area in bytes.

maxsize% = maximum size of dynamic area in bytes. Only of relevance if
type%=0 and OS is 3.50 or higher. (-1 means no limit but use of this
special value is not recommended.)

If type%=0 (the recommended setting) then Dr Wimp will automatically
locate the dynamic area according to the OS Version the application is
running under. (A specific dynamic area if OS 3.5 or higher; in the
RMA otherwise.)

If type%=1 then the dynamic area will be created in the RMA.

If type%=0 and OS is 3.50 or higher, then drag% and name$ are taken
into account. Then, if drag% = 1 the user can change the size of the
area by dragging in the Task Display; and 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.28 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.



14. Colour picker

PROCwimp_opencolourpickerrgb(dialoguetype%,red%,green%,blue%,n-one%,x%,y%)

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%)

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%)

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%)

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$)

Returns the size in bytes needed to store a file in memory prior to
using FNwimp_loadfile(), FNwimp_loaddfile(), FNwimp_loadsprites() or
FNwimp_loadjpegfile().

Always use this as opposed to any other form of measurement.

filepath$ = full pathname of spritefile.

(This function is also listed in in other sections)



FNwimp_loadjpegfile(filepath$,address%)

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.

filepath$ = full pathname of JPEG file.



FNwimp_getjpegsize(jpeghandle%,side%)

Returns the width/height (in OS units) of 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.

N.B. the returned dimensions are those of the overall bounding box
surrounding the graphic.



FNwimp_getjpegsizefile(filepath$,side%)

Returns the width/height (in OS units) of a JPEG graphic directly from
its file.

filepath$ = full JPEG file path.

If side% = 0 returns width.

If side% = 1 returns height.

N.B. the returned dimensions are those of the overall bounding box
surrounding the graphic.



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)

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).

(Note: This function cannot be used for printing.)

PROCwimp_renderwindowjpegfile(window%,jpegfilepath$,bx%,by%,min-x%,miny%,maxx%,maxy%,scalex,scaley)

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).

(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.37 and 3.16 Elixirs

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.37 and 3.16 Elixirs

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).

     
     


     

