C WIMP Tutorial?
Andy Burgess (1662) 14 posts |
Hi All, I’m hoping someone can help. I’m an experienced Linux and Windows programmer, but would like to be able to code some GUI apps on RISC OS. I’ve worked through “WIMP programming for All” in BBC BASIC, and “C for Yourself” (and another one) online. On each occasion I’ve ground to a halt with the tutorials, either due to lack of disc files, or something else. After struggling a little with DeskLib (and trying to get Makefile to cooperate with me), I’ve now stumbled on the “Toolbox” through MinApp, which looks like a great starting block, but I can’t find any simple examples to ease me into using it. Can anyone please point me in the direction of a really good – and more importantly – complete tutorial so that I can be writing WIMP apps and not struggling with the WIMP interface? I have Acorn C/C++ (from RiscOSOpen) and GNU C installed on my RPCemu. Ideally I’d like to be writing in C at a higher level without having to worry about the intricacies of the SYS calls to do stuff. I know what I want to achieve, but cannot get to achieving that, cos I don’t understand the WIMP calls and feel I’ve hit brick walls (not least with Make even with the desktop tools manual)! Please Help! Andy Burgess |
patric aristide (434) 418 posts |
Sounds like http://www.drwimpc.co.uk could be something for you then. As for documentation you’ll probably want the PRMs. Some documentation can be found here on ROOL or buy the CD version on ebay for a fiver. DrWimpC also comes with some “getting started” notes though and I’m sure it’s author would be happyto offer advice. Of course there’s also comp.sys.acorn.programming. |
Steve Pampling (1551) 8172 posts |
IIRC most of the PRM files can be downloaded from the web (ROL site if memory serves) Said files probably need an update as I believe they are the same vintage as the versions I have had (paid for) for a fair few years1 1 There may be minor changes in currently available items. |
Rick Murray (539) 13851 posts |
Hi, First up, build with AMU, not Make. I, personally, like DeskLib. What problems were you experiencing? I think it is only VisualBasic that will permit you to make fully functional applications without understanding the underlying window manager. Go find the PRMs (they’re on ROLs site, Google ought to turn them up if you look for “risc os prm pdf”). Then read the first half of section three. It will be hard going, but you’re bound to go in circles until you understand how the windowing system works (ie it is co-operative multitasking, you MUST periodically yield, and build your software with this in mind). While RISC OS has libraries, I think they are less developed than other platforms because the SWI call system is quite well thought out, so you don’t need so much isolating from the bogosity of the underlying API. And…if you get stuck on a point, just ask! (^_^) |
Andy Burgess (1662) 14 posts |
Thanks all for your rapid replies. BTW I’ve written a few really BASIC apps, and understand about !Run, !Boot and !Sprites etc. The WIMP “furniture” that Windows calls “Objects” – i.e buttons, input boxes, checkboxes etc are called “icons” on RISC OS, yeah? Oh, I forgot to mention I do have a full set of physical PRMs from RISC OS 3, but not really sure how to make the most of them. I’ll have a look at “the first half of section 3” as Rick mentions. I understand the basic principals of how the Windowing system works (having worked through a lot of a BASIC tutorial and a C tutorial), but I’d really like to move away from have to use “indirection operators” – if that’s what they’re called – i.e. the %b?12 type things – by using something that takes me away from that a bit with something more human-meaningful – e.g. icon_handle→align = right. Or am I missing the point entirely? I like the idea of Desklib, but would like to see something that holds me more by the hand than investigating the source code. Having said that, I could probably cope with Desklib, if I could work out the “make” process – it’s something that’s always confused me on Linux too. I’m more used to doing: cc program and and haven’t managed to do that easily with !Makefile. I’ll have an experiment with AMU. “Dr Wimp” – Ah yes, I’d heard of that previously, but had forgotten, I’ll give it go. Cheers |
Martin Bazley (331) 379 posts |
Possibly. System calls work at a much lower level in RISC OS than perhaps you’re used to – i.e. you can’t just dump everything into a C struct because the layout is undefined, and the exact byte offets of everything really matter! Also there are a number of things which just don’t fit into C ideology, such as icon data being stored as a series of fixed 32 byte blocks after the end of the window block. There probably are libraries which let you pretend that everything is made out of structs and function calls, but I suspect I wouldn’t want to use one if I saw the translation work it did behind the scenes. RISC OS was written in assembler for programs written in assembler, and this is very much visible in most of its APIs. |
nemo (145) 2556 posts |
“Window furniture” is stuff around the side of the window – titlebar, scrollbars etc. The contents of the window can be drawn by your program and/or drawn by the WIMP. The bits drawn by the Wimp are called icons, and are frequently interactive. Uniquely, they are referred to only by number, which is simply the index of the icon in question… and they’re drawn in that order too, so Icon 1 is drawn after (and potentially on top of) Icon 0. Traditionally, you design and build your windows using a Template Editor, and load the resulting windows using the Wimp_LoadTemplate call. This results in a block of memory already containing the window and icon definitions which can be turned into a window and icons using the Wimp_CreateWindow call. Alternatively, you can build a window definition manually, Create that, then do multiple Wimp_CreateIcon calls to populate it with icons. Icons (and the window background) detect (and filter out) various kinds of mouse clicks upon them, but apart from some simple animation and 80% of the handling of radio button groups, all you get is a Wimp_Poll return of type “Click” with the window handle and icon number in question, and a button type telling you what kind of click just happened – the rest is up to you. To make life easier for C programmers (and anyone who likes to work at a higher level and hasn’t already written the necessary skeleton to hide all that low-level stuff) there are the various Toolbox widgets. These are (mostly) implemented using icons, but are presented as widgets to the user. This system is much more like the kind of GUI toolkits you’ll be used to elsewhere. As for a saner naming scheme for all those Wimp memory structures, you can cast the blocks the Wimp uses to sensibly defined C equivalents and use named fields as you’d expect. BASIC uses all that indirection (? ! etc) because BBC BASIC as standard does not have Objects. A couple of us have implemented OO versions of BASIC where you can write “block.window=myhandle: block.icon=myicon” but they’re non-standard. You’ll be better off sticking to the language you’re most familiar with (he says, having never written a RISC OS program in C). |
nemo (145) 2556 posts |
Well, you can cast such blocks to C structs as long as you define them properly. Pedantically, C compilers are theoretically allowed to insert all kinds of padding between struct fields, but in practice they are only slightly obscure about alignment, and are unlikely to be strange on ARM at all. So as long as you’re explicit about 32bit integers (the usual platform unpleasantness) and careful that you cast the right block to the right type (or if you use a union, use the correct fork/fields) then you’ll be fine. Things only get tricky when you try to go multiplatform. Which is usually unlikely in the RISC OS case. |
Rick Murray (539) 13851 posts |
As has been said, we make a specific distinction here – “furniture” is the stuff around the edges of the window (toggle size, scroll, etc) that you don’t handle directly. The buttons, writeable icons (input boxes), radio icons, etc… yes, these are all called “icons”.
Brilliant. To be honest, I think using PDFs for datasheets sucks. It is useful to have PDFs on my phone for quick reference – but for actually absorbing information, give me a book any day. I am still looking for somebody who can print the OMAP 37xx datasheet at a price that won’t kill me – all 3750 pages of it! I did contact TI, but their attitude was as lousy as usual (as you are neither an educational establishment or a company, we aren’t even going to bother reading your message (you low-life pond scum)). Well, the last four words weren’t written but I bet they were thinking it. <sigh> Okay. In a nutshell, the WIMP overlays the basic UI. Think of it as Windows 3 as related to DOS. This means the first half of book three will tell you all about the WIMP, but you may need to wander around book one. You will notice that certain parts of the OS are a hairy mess of “this is how the Beeb MOS did it”, but we tolerate these things because not only is nobody stepping up to offer to rewrite the core OS (and by necessity, kill any hope of backwards compatibility), but if they did it would end up a crappy sort of Linux-Lite. [hint: I am not a fan of Linux, I don’t see why a little digital PVR or a mobile phone need to be running a botched-about server-class OS that takes minutes to start up; plus the whole case-sensitive filenames thing is an even bigger anachronism than our OS_Byte! I actually have someplace (perhaps that Zip disc hooked to my RiscPC? that too is a stack of anachronisms!) some source that I devised to try to patch Minix2 to be case insensitive. But I decided to do something more useful instead. :-)] Your homework, therefore, is to flip through the Desktop part of book three and see how much you can absorb. In particular, make mental notes as to how it differs from the systems you are used to.
That’s pretty much essential with programs written in BASIC. Okay, you could use a library for stuff like
Argh! We don’t do OO around these parts! What you need is something like: Hehe… I’m messing with you. (^_^) There are two approaches to this problem. The most common way is to use a library that will give you a nice function (but an explicit function – you must call a function to set icon parameters, as opposed to altering “properties”).
Okay. You can cc and link. I have two ways of building Harinezumi. First up, the main code is in C and it is called “sourcecode”. Yes, original isn’t it? The assembly language part (veneers, to get rid of _kernel_swi() ) is called “assembler”. $.Coding.Projects.Harinezumi | |--- !Help |--- c | '--- sourcecode |--- h | |--- equx.h [ EQUx macros for assembler ] | |--- harinezumi.h [ function/array prototypes ] | '--- SWINames.h [ define SWIs for assembler ] |--- harikick |--- harinezumi |--- MakeFile |--- o | '--- <contents not important> |--- s | '--- assembler '--- __buildit That is to say:
Here is the MakeFile:
The cool thing here is it is easily adapted. If you wanted to build an RSS reader, simply alter the target If you want, I can post a MakeFile for a more complex project for you to compare with. You will note the
Extending this is a matter of adding objasm or cc lines (as applicable) and then adding the object file reference to the link line at the end. Both methods work, but the makefile method (via !AMU) is more flexible (with !Zap or !StrongEd will support Throwback so you can double-click on error messages to be taken to the relevant line in the source). Hope this helps. |
Steve Fryatt (216) 2105 posts |
Er, yes you can. OSLib does just this: function veneers are defined for pretty much every SWI you’re likely to need, with all the parameters typed and — where necessary — supplied with struct definitions to represent the data blocks. In fact, you really should be using OSLib for modern development: it will make your code a lot easier to read (at least it did for this refugee from BASIC) and your life a lot easier.
Again, OSLib sorts this out for you: icons are an array of structs tagged on to the end of the window struct. Very little “translation” is required, and it’s easy to use. If you understand C’s pointer/array syntax, how it works underneath is also pretty obvious. Icons are actually easy: they use fixed size blocks. Some things do get a bit hairy, such as returned data from the directory listing OS_GBPB calls where blocks are “n + string” in format. Even then it all works surprisingly well if you read the OSLib headers and realise that the developers have done most of the thinking for you already. My experience has been that it’s vastly better than doing it all by hand. |
Chris Johnson (125) 825 posts |
I would agree there. It has full support for the toolbox, and the OSLibSupport library has event, message, and error handling etc. ResEdit (and ResTest) allows toolbox based windows and Menus to be set up easily by drag and drop methods. |
Steve Fryatt (216) 2105 posts |
That’s one option; I’ve not looked at the C version, but understand it uses OSLib — a bonus in my book. Alternatively, as you say, you can use the Toolbox as this makes things a bit more event-driven and OO-ish (inasmuch as stuff on RISC OS can be). You can drive the Toolbox via Acorn’s libraries or by using OSLib. If you don’t go down these routes, then (as someone who made the transition from BASIC and Wimp Programming for All) I’d strongly suggest starting from the outset with a decent event-driven library to base your code on. You can write C like the BASIC in WPfA, but it very quickly gets ugly and hard to modularise. Desk and DeskLib are a couple of options for such a library, although I don’t think they play nicely with OSLib (which IMHO is a reason to avoid them). If you’re planning to go open source, then NetSurf is built on a GPL2’d event library — although it was still a bit tangled up in NetSurf’s legacy GUI stuff when I last poked with it, so it may not be usable elsewhere without pain. Personally I use my own “SFLib”, which is available under the EUPL (so good for GPL2 stuff as well) but seriously lacking in documentation. Whichever way you go, though — writing Wimp software for RISC OS will never be a simple as using something like Visual Studio. |
WPB (1391) 352 posts |
Hi Andy, I suspect you’ve come across these already, but here are a couple of possibly useful pointers:
Have you found the Toolbox information in the ROOL DDE? There’s a PDF all about the Toolbox, including information about a (very old) example app called !Hyper by Castle. I think !Hyper is still included in the “legacy” examples bundled with the DDE. Using the Toolbox is definitely recommended if it’s going to do everything you want it to do. Trying to combine Toolbox and older-style WIMP programming can be very difficult. |
Steve Drain (222) 1620 posts |
Please excuse me, but I think I ought to pop in here to mention Basalt. ;-) Among many other things it gives standard BASIC V an OO interface to the Toolbox. So you can do things like: 'MainWindow#3.Value="Hello World!"
If you use the facility for constants that could be: 'MainWindow#@@DisplayIcon.Value="Hello World!"
B….. textile – that @@ is a single – it tries to make a link otherwise. It can also register events and messages to be event driven. If I were not so engaged with my Pi I might have given Basalt structures by now, so if you wanted to do the Wimp the hard way you could define a window structure including icon substructures: \window.icon(3).text$="Hello World!"
I have a BASIC library that does that more or less, but awkwardly. |
Theo Markettos (89) 919 posts |
Hi Andy, You’re probably confused by everyone throwing about their favourite way of doing things. As you might have noticed, there’s more than one way to do it! On a scale from 1 to 5, here’s how ‘high level’ things are: 0. Assembler. Raw access to SWIs (the essential window system constructs), no structure support whatever. Somebody wrote a web browser in assembler (Webite). They were crazy. 1. BASIC calling SWIs with structures like q%!24 etc. Access to the same API in a way less likely to crash, but you still have to do the structure management yourself (you can do things like windowhandle%=24:q%!windowhandle%=… but it’s not much better) 2. OSLib in C: access to the raw SWIs, but using structures and types so you can’t do silly things like pass a window handle as an icon handle. But you still have to drive the SWIs. With a higher-level windowing library, OSLib is still useful for non-windowing things… some day you might really need to call PCI_HardwareAddress, but you won’t find it in a windowing library. 3. DeskLib in C: higher-level routines so you don’t have to call the SWIs yourself, it does more of the work for you (eg you don’t call Wimp_Poll to receive messages from the Wimp, but has an event system where you register things to be called on particular events). Desk is a fork with some additions, but most of the recent work seems to be on the original DeskLib. 3. DrWimp/DrWimpC: similarly higher-level routines for BASIC and C (not exactly sure how DrWimp and DeskLib compare). 4. Toolbox: further abstraction using further SWIs – a more complex event system, the provision of ‘gadgets’ composed of multiple icons, for example scrollable text list. Common windows such as a Save As dialogue are already coded. You can call Toolbox SWIs directly, but from C OSLib provides a typed veneer. I don’t know how well it works from BASIC. 5. Libraries on top of Toolbox. I don’t have much experience here. tbx (C++) is quite nice for the limited amount I’ve used it, but it’s not mainstream. I’m sure there are others. I think there are some C++ class libraries that fit somewhere in this hierarchy, but I don’t know any well enough. C++ takeup on RISC OS has been poor due to the appalling state of Acorn’s compiler (if you want to use C++, use GCC). My limited experience with C++ using tbx has been quite positive. On this scale, Win32 would be roughly equivalent to OSLib and MFC to Toolbox (level 4 or 5). But I’m not a Windows expert, so might have it wrong there. Documentation for most things is, sadly, not great. But usually there are some example programs you can look at. I don’t know if there’s an easy way of working out which apps use which libraries so you can download their sources to have a look, which is the way many people learned (when everything’s BASIC, it’s easy). Some of the ROOL apps use the Toolbox, and some apps on riscos.info use Desklib. It does help to understand what the Wimp is doing underneath you, even if you don’t have to deal with the details. There’s an automatic makefile builder thing with ROOL C (think it’s called !Make, which is not to be confused with the command line tool called ‘make’), but it’s not great. You might wish to read about writing makefiles by hand instead. The advantage of these over the type spat out by Acorn’s tools (with lots of @.o.foo everywhere) is they’re cross-platform – work on AMU, GNU make on RISC OS, GNU make on Linux, BSD make, etc etc. I normally start with a template like that in the article, and then add files etc as necessary. The same makefile works with GCC too, you just need to change the tools and their options. |
Steve Drain (222) 1620 posts |
Quite long-winded if used directly.
You did not mention the very well documented AppBasic BASIC library/system, which is based on the Toolbox. Nor Basalt, which is neither library nor direct, but a language extension. |
Andy Burgess (1662) 14 posts |
Wow! Thanks all! “Window Furniture”: Thanks for setting me straight on that. I’d misunderstood this term for a while! “DeskLib”: I’m really getting to grips with DeskLib – now I realised it has lots of information in its “!Help” files for the apps (I’d not thought about even looking at the !Help files – doh!). I think I’m going this way for the mo – with a view to possibly switching to OSLib a little later. The only issue I’ve encountered with DeskLib is that it doesn’t seem to want to open my “Messages” file (I’ve adapted Frauke Nonnenmacher’s desklib task4 for my own learning, but it doesn’t load it) – I suspect I’ve not tied something together. My app has a different name to Frauke’s, and I’m sure the !Sprites are OK and my own content in the Messages, but it must be something else I’ve missed …… Thanks all for your continuing advice! I’ve still got to read the start of PRM3! BTW How can I draw a circle in one of my window’s icons? I’ve drawn circles in Mode 5 in BBC BASIC in my dim and distant past, but am a bit confused about how to do it with DeskLib? |
Martin Bazley (331) 379 posts |
Two options:
Or I suppose you could bodge it and instead of an icon have a nested window with no furniture which just happens to be the exact same size, shape and position as an icon, which you can then isolate the redraw requests to. But really, considering doing anything with poll code 1 is letting yourself in for a world of pain. |
Rick Murray (539) 13851 posts |
[quoted text contains my highlight]
WHAT!?!?!?!?! Please consider the following picture. What you see here is a biorhythm program by Mark Hammond from 1996. The main plot window is a plain blank “we redraw it ourselves” kind of deal. The Wimp might be clueless, but it isn’t completely retarded. I think you can have icons in a user-redrawn window. However, it is more common to put the icons into a different window and then overlay this as a “pane” (windows equivalent, the menu/toolbar thingy at the top). The reason for this is the icons typically want to stay in the same place, but the actual content of the window may be subject to scrolling. I will concede that dealing with window texture is your responsibility, however typically the purpose of setting the window to “we redraw this” is because you’re displaying something else instead…
You know, there’s a part of me that would like to make something to seriously abuse this idea (how about !Calc rewritten so each button is actually a window?) just, you know, for a laugh. (^_^) |
Steve Drain (222) 1620 posts |
Could you not redirect VDU output to the sprite to draw a circle? |
Rick Murray (539) 13851 posts |
There’s a lot more they can do (like building two different things at once), but I’ve not really sussed the syntax.
It is even better:
I suspect your problem is DeskLib not knowing where to find stuff. Take a look at this:
You must pick a name for your application, let’s say “QWERTY”. Then you need to set, in the !Run file, <QWERTY$Dir> to point to where the path is; this is typically:
Depends upon the icon. Simplest way, if it is a static circle, is to create it as a sprite and then set the icon to display the sprite. If it is a circle that changes, set the icon to display a sprite, draw into the sprite, force the icon to be redrawn. Obviously this won’t be too suitable if it is something animated due to the potential for flicker.
How dim and distant past? Messing with SIN tables and such, or calling CIRCLE x,y,r ?
At the risk of a slapping from those better than myself, I tend to draw arbitrary stuff into sprites by redirecting graphics to the sprite, then just using OS_Plot (that’s in the latter fifth of PRM-1) which can do a heck of a lot of stuff. I would consider using redirect-to-sprite in a multitasking program to be a bit naughty, but if there’s a better way, it isn’t immediately obvious! |
Andy Burgess (1662) 14 posts |
Thanks for this advice. So it’d be easier to use Sprites than drawing-type stuff? Also can one display an image (JPG / PNG / GIF) to an “icon” and overlay another icon (another image, or another sprite) on top? I’m wanting to create an interactive application in RISC OS. I remember “Chaining” “Biorhythms” from the BBC Micro Welcome tape. If the source code is available for the RISC OS version of the Biorhythms program I’d love to get my hands on it, or any other graphically clever apps (especially with DeskLib). I always liked the idea of “Bio”. As to my “dim and distant past” – it was using SIN and COS type statements – I don’t think CIRCLE was available on the Beeb. As regards the Query$Dir stuff, Rick mentioned My app folder is called !MyApp, I Resource_initialise(“!MyApp”), my sprite is called !myapp and it’s set in the line that should be read from the Messages file, and in my !run file I set MyApp$dir to obey$dir, and my executable is called !RunImage. I’ve tried copying the c code from the example and changing for myApp name, and it no longer works – so it’s obviously me somewhere! |
Chris Johnson (125) 825 posts |
Yes – you can. The auto-redraw flag if set will prevent the wimp sending any redraw requests to the app. If unset, then the wimp will do what it can and then send a redraw request to the app for it to add what it needs to (not sure the order of these two actions without looking it up). |
Rick Murray (539) 13851 posts |
Depends on what you want to do, really!
No. This isn’t VisualBasic! ;-) RISC OS only understands sprites in icons. There is OS support for baseline (non-interlaced) JPEGs, but these must be plotted directly to the window. GIF, you could probably write a simple GIF decoder (I did one in 1024 bytes of assembler!) to translate the GIF to a sprite (or if very quick code, plot it directly). Don’t know about PNG.
You can plot something on top of something else. You can have one icon over the top of something else. If you want to plot something on top and have stuff show through from before, then you’re looking at direct plotting with sprites that have a transparency mask.
Um… Most applications are interactive…?!
It is written in BASIC, yes. It came with Acorn User’s *Info stuff. I don’t see a version online, and since Mark called himself “cumsoft”, you don’t wanna know what Google threw at me when looking. The licence is… amusing: This program is copyright. It may not be copied, stored or transmitted, electronicly, sexually or otherwise. No part of this program may be used in an after dinner speech or repeated verbally to others especially by a talking parrot, macaw, or minor bird, used by the BBC for a forthcoming documentary, chatted about or used as a hat without the express permission of the copyright owner. However the copyright owner is open to bribes. In such cases the copyright owner reserves the right to demand payment in unmarked five pound notes deposited in a brown paper bag in a public place. The program is supplied as it is. The user assumes all responsibility for liability, damage or loss of earnings resulting from the use of this program. If the program crashes and screws up your hard disc, hard cheese. If the program causes you to lose time or work, what a shame. If such loss results in death by suicide, the destruction of the earth or any other means, the copyright owner shall assume no guilt.
It wasn’t. I think it was introduced with the Master range. However, since the Archimedes was born back in ’86 (or was it ’87?), you could have meant drawing stuff in BASIC V.
Okey-dokey then. Application → !RunImage. Correct. In RISC OS, the “!” prefix tells the filer that the directory is actually an application (thus, when double-clicking, run the !Run file, etc). Because the directory name has a ‘!’ prefix, the sprite must match. However the application is to be known as the name without the prefix. Look at the taskmanager, you’ll see Paint and Edit and such, not !Paint and !Edit. We users tend to use ‘!’ prefixes in written stuff; I will talk about opening files in !Zap or how !AMU is better than !Make. This is because we all know that ‘!’ means an application; so it is much less of a mouthful to type ‘!’ than “the application called”. ;-) Anyway. Resource_Initialise should match the blah$Dir name… |
WPB (1391) 352 posts |
I don’t think anyone’s mentioned !Draw and the Drawfile renderer yet. (I think it’s available on ROOL RISC OS, not just ROL RISC OS – if someone knows better, please jump in and silence me!) Anyway, that allows you to render a Draw file (see the PRMs, or just examine something you save out of !Draw) onto the screen, and is readily usable in WIMP apps. There’s an example of an app that does this on this page. If you want to draw geometric shapes in a window, it’s worth looking into, and very easy to use. |