#! lua local sys, !, $, dim in riscos @ = require "wimp.toolbox" -------------- drawfile stuff --------------- local Drawfile_Load = \ (fpath) local r0,r1,r2,r3,r4 = sys (8, 17, fpath) -- OS_File if r0 ~= 1 then => nil,fpath.." not a file" end -- if local buf = dim (r4) sys (8, 16, fpath, buf, 0) -- load file into b => buf, r4 end local Drawfile_Render = \ (buf, buf_size) => \ (@, x, y) local b in @ local u, v = 1<<16, 1<<8 ![b + 256] = u ![b + 260] = 0 ![b + 264] = 0 ![b + 268] = u ![b + 272] = v*x ![b + 276] = v*y sys (0x45540, 0, buf, buf_size, b + 256, b + 28) -- DrawFile_Render end end ----------------------------------------------- local page = dofile "codex:index" local cache = { } -- storing loaded Drawfile data local where = "codex:%s" local getfile = \ (n) => where:format (page[n]) end local getpage = \ (n) local data = cache[n] if data then => data.buf, data.bufsize end -- if local b, bs = Drawfile_Load (getfile (n)) cache[n] = { buf = b, bufsize = bs } => b, bs end _ENV = @ handler[1] = \ (@) -- Wimp_RedrawWindow local Drawfile_Redraw = Drawfile_Render (getpage (@.pageno)) => @:user_redraw (Drawfile_Redraw) end handler.tbox[0xa0] = \ (@) -- Select clicked on iconbar local self_id, parent_id, parent_comp in @.obj.codex_win if 1 & (@:GetObjectState (0, self_id)) == 1 then if pageno < #page then pageno + = 1 end -- if @:winredraw (self_id) else pageno = 1 @:Show_Object (0, self_id, 0, 0, parent_id, parent_comp) end -- if end handler.tbox[0xa1] = \ (@) -- Adjust clicked on iconbar local self_id, parent_id, parent_comp in @.obj.codex_win if 1 & (@:GetObjectState (0, self_id)) == 1 then if pageno > 1 then pageno - = 1 end -- if @:winredraw (self_id) else pageno = #page @:Show_Object (0, self_id, 0, 0, parent_id, parent_comp) end -- if end handler.tbox[0xa2] = \ (@) -- Help on iconbar menu local b in @ $[b] = "filer_run codex:!Help\0" sys (0x400de, b) -- Wimp_StartTask end $[resdir] = arg[1] -- Tell the toolbox where to find res init (@, { }, { }) -- All wimp, all toolbox events signify. mask = 257 -- No null or kbd events run (@) -- This has to be last.The third line loads the library wimp.toolbox and calls it @. Lua libraries are tables. The keys in the table name values that are made available to programs that require the library, hiding the implementation details. As yet the toolbox library does not export any Drawfile stuff, so the program has to define it itself. The next section defines two functions: Drawfile_Load and Drawfile_Render. Drawfile_Load uses OS_File to find the size of the file at the given path, reserve an appropriately sized buffer, load the file into the buffer, and return the address of the buffer and its size. Drawfile_Render takes a pointer to a buffer, and its size, as arguments, and returns a function. The function's first argument is a wimp task, its second and third the coordinates of where the Drawfile is to be rendered. It stores the appropriate affine transformation in the message buffer b of its first argument, then calls the SWI Drawfile_Render. This perhaps calls for an explanatory interlude about how RiscLua sees wimp tasks.
A wimp task is a coroutine of the taskmanager. When it calls Wimp_Poll or Wimp_PollIdle the thread of execution passes out of its control to the taskmanager, and returns when those SWIs return. Information is conveyed between the two processes in CPU registers and the message buffer. The SWI Wimp_Init registers the program with the taskmanager, telling it where the message buffer is and so forth. The RiscLua library wimp.task spawns wimp tasks as copies of itself. Two special methods stand out: init which registers the wimp task with the taskmanager, and run which sets it going. The core of the latter is a loop:
local run = \ (self, idle) local poll <const> = idle and 0x400e1 or 0x400c7 local b, handler, preclosedown in self local reason, quit, action, err local when = ((not idle) and 0) or self.time or 100 while not (quit or err) do reason = sys (poll, self.mask or 0, b, when) action = handler[reason] quit, err = action and action (self) if err then self:report (err) quit = true end -- if end -- while self:closedown ( ) endWimp tasks come with an array of functions, handler, indexed by the codes returned by the taskmanager, which determine how the wimp task reacts when control returns to it. I find it convenient to adopt the convention that handlers only return a non-nil value in order to signal that the wimp task should close down. This means that if a handler is not defined for some circumstance, that does not shut the wimp task down. Another array of handlers handler.mesg responds to messages. The wimp.toolbox library extends the wimp.task library with an array handler.tbox of responders to toolbox events.
Recall that I used three numbers, &a0, &a1 and &a2 in setting up the Resource file. These appear above in the definitions of handler.tbox[0xa0], handler.tbox[0xa1] and handler.tbox[0xa2] which deal respectively with clicks of Select on the iconbar icon, Adjust on the iconbar icon and either on the Help option in the iconbar menu. There is one more handler definition, for handler[1] -- Wimp_RedrawWindow.
The statement
_ENV = @is worth explaining. This makes the table @, our wimp task, the global environment. So that any variable not previously declared as local, is looked up from, or written to, @. This is a syntactic trick making for more readable code. Without it the last four lines would read
$[@.resdir] = arg[1] @:init ({ }, { }) @.mask = 257 @:run ( )Note how the Drawfile data is cached. Once a Drawfile has been loaded there is no point in it being loaded again.