From 98c1e1b27a7514317d1ddb4b45396915bc3d6262 Mon Sep 17 00:00:00 2001 From: Steve Fryatt Date: Wed, 15 Dec 2021 23:51:46 +0000 Subject: [PATCH] Create skeleton project for panes tutorial. --- .gitignore | 2 + Chapters/ch01-an-example-application.xml | 178 ++++++++++++++++++++ build-manual | 3 + panes.dtd | 12 ++ panes.xml | 42 +++++ xmldoc.xsd | 196 +++++++++++++++++++++++ 6 files changed, 433 insertions(+) create mode 100644 .gitignore create mode 100644 Chapters/ch01-an-example-application.xml create mode 100755 build-manual create mode 100644 panes.dtd create mode 100644 panes.xml create mode 100644 xmldoc.xsd diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3108cc4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +dump.xml +output diff --git a/Chapters/ch01-an-example-application.xml b/Chapters/ch01-an-example-application.xml new file mode 100644 index 0000000..e0fea58 --- /dev/null +++ b/Chapters/ch01-an-example-application.xml @@ -0,0 +1,178 @@ + + + + + + + + + + +Chapter01 +Chapter01 + +an-example-application.php +an-example-application +An Example Application + +We’ll need a simple application to add our panes to, so we start by putting one together. + +
+

Over the course of this tutorial, we’ll look at the different ways that panes can be used in Wimp applications, and the code required to make them work. Since examples almost always make things easier to follow, we’ll use a minimalist application and ... etc.

+ +

The language that we will be working in is BBC BASIC, although the concepts introduced should be easy enough to translate into other languages as required. The code will be self-contained, to avoid the distraction of using additional libraries, but I’ll be borrowing a number of the routines from my WimpLib BASIC Library.

+ +

If you find it hard to follow any of the concepts in this chapter, it might be useful to look at a more general introduction to the Wimp first. There are a number of good books available for BASIC programmers, including First Steps in Wimp Programming and Wimp Programming For All, while those favouring C may wish to read my own Wimp Programming In C tutorial elsewhere on this site.

+
+ +
+An application shell + +

To allow us to demonstrate panes, our application must be able to initialise itself, stay running while we examine what it does, and then exit on demand. A minimal structure for this can be seen in .

+ +TaskName$ = "PaneDemo" +TaskSprite$ = "application" + +ON ERROR result% = FNwimperror_program : END + +PROCinitialise + +ON ERROR Quit% = FNwimperror_program + +WHILE NOT Quit% + PROCpoll +ENDWHILE + +SYS "Wimp_CloseDown" +END + +

The code initialises a pair of global variables – TaskName$ and TaskSprite$ – which contain the application name and sprite necessary for the error handling. It then sets up an initial error handler, before calling PROCinitialise to get its interaction with the Wimp up and running.

+ +

If this goes OK, the error hander is updated to be a little less drastic than the original one, before the code drops into the standard Wimp poll loop. Finally, when Quit% becomes TRUE indicating that the program should exit, it falls out of the WHILE loop and calls Wimp_CloseDown to tidy things up.

+ +

The initialisation is carried out by PROCinitialise, which for now can be seen in .

+ +DEF PROCinitialise +LOCAL buffer_size% + +REM Set up the quit flag and global data blocks. + +Quit% = FALSE + +buffer_size% = 4000 + +DIM b% buffer_size% - 1, q% 255 + +REM Initialise with the Wimp. + +q%!0 = 0 + +SYS "Wimp_Initialise", 310, &4B534154, TaskName$, q% + +

For now, we do very little in the way of initialisation. The global Quit% is initialised to FALSE, indicating that the appliction should not exit immediately, and a couple of buffers – b% and q% – are initialised to 4000 and 256 bytes respectively. Whilst these will both be used as general purpose buffers, b% will be passed to Wimp_Poll/ while q% will mostly be used as a second parameter block by other Wimp SWI calls.

+ +

The program requires 310 as its minimum Wimp version: whilst pane code will work on RISC OS 2, 3.10 is the oldest version of the OS that it’s practical to support in modern software. This means that Wimp_Initialise requires a list of messages to be passed in R3, so we build this up in the block pointed to by q%: the only entry is zero, for Message_Quit.

+ +

Error handling is looked after by FNwimperror_program, which can be seen in .

+ +DEF FNwimperror_program +LOCAL result% + +SYS "Hourglass_Smash" + +!q% = ERR +$(q% + 4) = TaskName$ + " has suffered an internal error (" + REPORT$ + "; error code " + STR$(ERL) + ")" + CHR$(0) +SYS "Wimp_ReportError", q%, &0703, TaskName$, TaskSprite$, 1, 0 TO ,result% + +=(result% = 2) + +

In the event of an error, Hourglass_Smash is called to ensure that the hourglass is cleared, then Wimp_ReportError is used to report the problem to the user. Since this is called from ON ERROR, the expectation is that REPORT$ and ERL will have useful values.

+ +

Finally, PROCpoll is called repeatedly to handle the calls to Wimp_Poll; the code can be seen in .

+ +DEF PROCpoll +LOCAL reason% + +SYS "Wimp_Poll", &3C01, b% TO reason% + +CASE reason% OF + WHEN 17, 18 : IF block%!16 = 0 THEN Quit% = TRUE +ENDCASE +ENDPROC + +

For now, there’s not much here: we’re only interested in Message_Quit, which has the value of zero; if this arrives, we set the Quit% to TRUE so that the program will terminate. This ensures that it can be shut down from the Task Manager.

+ +

If the application is run in this state, it will run quietly in the background with no evidence of its existence aside from an entry in the Task Manager. To do something more interesting, we’ll need to add some windows!

+
+ +
+Adding some windows + +

Before we can add a pane to our application, we’ll need a window to which it can be attached. To this end, we will create a couple of windows in a templates file: a main window and, to prove that our pane handling code doesn’t affect other windows in the application, a standard program information window.

+ + + +

To load the templates into our application, we can add some lines to PROCinitialise directly after the call to Wimp_Initialise. These can be seen in .

+ +REM Load the window templates + +DIM TemplateName% 12 + +SYS "Wimp_OpenTemplate",,"<PaneDemo$Dir>.Templates" + +PROCtemplate_load("Main", b%, buffer_size%, -1) +SYS "Wimp_CreateWindow",,b% TO MainWindow% + +PROCtemplate_load("ProgInfo", b%, buffer_size%, -1) +SYS "Wimp_CreateWindow",,b% TO InfoWindow% + +SYS "Wimp_CloseTemplate" + +

The code opens the templates file with Wimp_OpenTemplate, then loads window tenplates for the main window and program information window in turn. For each, a window is created immediately using Wimp_CreateWindow, with the handles being stored in the MainWindow% and InfoWindow% variables respectively.

+ +

The code uses PROCtemplate_load(), which puts a friendly wrapping around the Wimp_LoadTemplate SWI. Its definition can be seen in .

+ +DEF PROCtemplate_load(name$, buffer%, size%, fonts%) +LOCAL templ_size%, indir_size%, workspace% + +REM Find the size required for the template and indirected data. + +$TemplateName%=LEFT$(name$ + STRING$(12, CHR$(13)), 12) +SYS "Wimp_LoadTemplate",,,,, -1, TemplateName%, 0 TO ,templ_size%, indir_size% + +REM Return if the template won't fit in the buffer. + +IF templ_size% > size% THEN ENDPROC + +REM Claim the required indirection block. + +DIM workspace% indir_size% - 1 + +REM Load the template into the buffer. + +SYS "Wimp_LoadTemplate",,buffer%, workspace%, workspace% + indir_size%, fonts%, TemplateName%, 0 +ENDPROC + +

Taking a pointer to the larger of the two buffers that we defined in PROCinitialise, the code uses Wimp_LoadTemplate to check how much space the template definition will take, and how much space it will require to store any indirected icon definitions.

+ +

Assuming the definition will fit into the supplied buffer, DIM is used to allocate the indirected icon space, then Wimp_LoadTemplate is used again – this time to actually load the definition into memory.

+ + + + + + + + + + + + + +
+
+
+ diff --git a/build-manual b/build-manual new file mode 100755 index 0000000..5e5f725 --- /dev/null +++ b/build-manual @@ -0,0 +1,3 @@ +#!/bin/sh + +xmldoc --source panes.xml --output output/ --php static/panes/ --image images/panes/ --download files/panes/ --linkprefix panes/ --imageprefix ../../images/panes/ --downloadprefix../../files/panes/ diff --git a/panes.dtd b/panes.dtd new file mode 100644 index 0000000..3416f71 --- /dev/null +++ b/panes.dtd @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/panes.xml b/panes.xml new file mode 100644 index 0000000..e58d02b --- /dev/null +++ b/panes.xml @@ -0,0 +1,42 @@ + + + + + +Handling Panes +HomeRISC OS + +../../images/types/zip.png +../../images/compatibility/armv7.png +../../images/compatibility/iyonix.gif + + +Images +Downloads +Common +Chapters + + + + + +index.php +./ + +
+

One area of the RISC OS Wimp which appears to be shrouded in mystery is the handling of pane windows. Whilst many modern applications will have toolbars or status displays, how they’'re implemented is something that doesn’t seem to get a mention in any of the books on programming.

+ +

This guide was written after seeing the question asked many times in the forums and newsgroups. It isn’t a beginner’s guide to Wimp programming, but a more detauled look at the specific issues surrounding the handling of pane windows within applications. If you’re looking for an entry-level guide to the much larger subject of writing desktop applications, I would suggest looking ... here ...

+ +

The examples in this tutorial are written in BASIC, but the techniques are equally applicable to other languages such as C – I hope that I have managed to explain them in a way that allows them to be applied in your environment of choice.

+ +

Many thanks to all those on the ROOL Forums who have offered suggestions while I’ve worked on this guide.

+
+ + + +
+ + + +
diff --git a/xmldoc.xsd b/xmldoc.xsd new file mode 100644 index 0000000..efbdda9 --- /dev/null +++ b/xmldoc.xsd @@ -0,0 +1,196 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +