[Jaffa Software]

WimpWorks' Advanced Features

Understanding how WimpWorks works

Andrew Flegg, 26-Feb-1999

Although WimpWorks is very flexible by default, certain effects and features can only be gained by:

  1. Understanding how a WimpWorks application is structured
  2. Rewriting parts of the system to modify their behaviour

This document attempts to address these points and, although aimed at a more "advanced" user, may be useful background to anyone programming WimpWorks (and even BASIC).

Memory Map

[Memory Map] This diagram shows two separate maps: on the left hand side is a WimpWorks program which has additional libraries added to it (such as the WimpWorks Editor itself, !WimpWorks); the right hand side shows how the memory would be structured without the additional libraries.

Along the left hand side are the BASIC pseudo-variables which contain the exact location of those points in the memory; the figures along the right hand side represent physical memory address, where known.

PAGE
This is the start of the program in memory, ie. ?PAGE = &0D (first byte of a BASIC program.

TOP
The "TOP" of the program.

LOMEM
After the top of the program comes the variable space, and LOMEM holds this value. As can be seen from the memory map, a file included with LIBRARY is considered as a block of data within the variable space, rather than as a part of the program proper.

END
This end of BASIC's used memory - above this (but below HIMEM) is unused space which will decrease as the variable space increases.

HIMEM
The end of BASIC's available memory - this is rounded to the nearest page boundary.

Stubs

Traditionally, a stub is an empty function which has little or no functionality - which will be added at a later date, however in WimpWorks, a stub is equivalent to a "hook", that is, a function which provides default functionality but can be replaced. There are two standard hooks within WWv2.18 and above - one is provided in every WimpWorks application, the other is for use within the editor only.

A hook/stub is replaced by using REDEFINE - ie. you rename the existing subroutine so that your new replacement one is found instead. So that the original could be within a library, REDEFINE searches from PAGE to END for the subroutine.

Example 1: REDEFINE("__redraw__internal", "the_old_redraw_sub", &F2)
This command would rename the first PROC__redraw_internal found to PROCthe_old_redraw_sub. This means that BASIC does now not know about PROC__redraw_internal so that when you write your own subroutine called that it thinks that this is the one and only. However, since you know the new name of the original you can extend its behaviour instead of just replacing it.

Example 2: REDEFINE("openwindow", "openwwv2__", &F2)
(Note that the subroutine names should be exactly the same length)
Now, in our application we write our own PROCopenwindow:


DEF PROCopenwindow(window%)
  VDU 7
  PROCopenwwv2__
ENDPROC

Now, whenever OPENWINDOW is called our own subroutine is called in its place which simply makes a beep before opening the window. Also, another part of the program (maybe from a WEM) could redefine our PROCopenwindow without needing to know we'd already done that. As long as the new name is unique no problems would be created. (The WEM version may wish to log all calls to OPENWINDOW before passing them on).

Onto the standard hooks: within any WWv2 application (created with v2.18 or above) the following procedure can be redefined to allow direct access to the redraw code:


REM Name:       PROC__redraw_internal
REM Purpose:    Redraws all the graphics from the linked list so that it can be
REM             called from the screen redraw or printer redraw loop...
REM Parameters: temp% - 1024 byte block used for temporary storage
REM             sx%   - horizontal scroll fiddle factor (add to window
REM                     coordinate to get screen
REM             sy%   - vertical scroll offset (as with sx%)
REM             win%  - window handle of window redrawing
REM             bbox% - 16 byte block of bounding box to redraw
REM                     on screen (x0, y0, x1, y1)

DEF PROC__redraw_internal(temp%,sx%,sy%,win%,bbox%)
   ...
ENDPROC

This procedure is called from within the redraw WHILE...ENDWHILE loop and it is within the procedure that intersections must be checked etc.

And, for a WimpWorks editor the following function can be overridden to replace the parser:


REM Name:       FN__parser
REM Purpose:    Translates a line in WWv2 "extended BASIC" into standard
REM             BASIC for execution, eg. RELEASE(mem%) -> PROCrelease(mem%)
REM Parameters: line$ - the actual line to convert
REM             temp$ - exactly the same as line$ but any string constants
REM                     have been blanked out with spaces, this means you
REM                     can search on temp$ and then apply changes to both
REM                     eg. line$ = SETICON(main, 0, "Hello world")
REM                         temp$ = SETICON(main, 0, "           ")
REM Return:     Line to include in the final source

DEF FN__parser(line$,temp$)
   ...
=line$

Conclusion

If you have any questions about the internal workings of WimpWorks please do not hesitate to contact the author.