WimpWorks' Advanced Features
Understanding how WimpWorks works
Although WimpWorks is very flexible by default, certain effects and features can only be gained by:
- Understanding how a WimpWorks application is structured
- 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
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.