title logo

back contents forward

Chapter 11

libraries

RiscLua comes with a simple library sytem. The libraries are held in the directory !lua.lib and are accessed using the word require . We will look at the example wimp application !Snerp which does not do very much but shows how use of libraries can simplify coding. Its !RunImage file starts with

-- load definitions -----------------------
require "wimp.events"
require "wimp.messages"
require "wimp.task"
require "wimp.ibaricon"
require "wimp.templates"
require "wimp.window"

The wimp.events library simply names the event codes used by the Wimp_Poll SWI. Similarly the wimp.messages library names wimp message numbers. The  wimp.task library returns a single function task which expects three arguments: the task name, 100 times the version number of RISC OS (310 is the default value if the argument is omitted) and a list of all the messages, apart from Quit which the task is to receive. It returns a table with entries

  b         message block
  title     title
  titleb    block holding title
  mesgb     block holding message list
  errb      error block
  pollw     block holding pollword
  taskhandle  a number
  handler   table of handler functions
            indexed by reason codes. A
            handler function is a method
            (only argument is 'self')
            which returns nil to cause
            the task to exit.
  mask      poll event mask - this needs
            explicit setting

and methods

  init         register the task with the
               window manager
  closedown    deregister the task with the
               window manager
  run          enter the polling loop
  try          protect a method so that
               errors cause task to exit
  preclosedown   run before closing task down
  report         put up a report dialog box
  messagehandler handle all messgaes except Quit
  ack            acknowledge a Dataload
                 message and jumps to a
                 continuation method, which takes
                 the filename and filetype of
                 the dataload as arguments.

The rest of the program inside !Snerp.!RunImage is in a do . . . until loop. The first line creates the task and names it.

local snerp = task("Snerp",310,{ --[[
              messages we want to receive]]
                                DataLoad;
                               })

The remainder of the program describes snerp's properties, for example

snerp.mask = 0x3933
(see PRM 3-116/7) and ends with

-- register snerp ---------
snerp:init()
-- create iconbar icon ----------------------
assert(ibaricon(snerp,"!snerp",
               "<Snerp$dir>.Templates"),
"Cannot create iconbar icon") --[[
         defines snerp.ibaricon]]

local windata =
      templates("<Snerp$dir>.Templates",{"main"})
snerp.main = createwindow(windata.main.def)

-- run it ---------------
snerp:run()

The wimp.ibaricon library returns a single function ibaricon . It expects three arguments, the task, the name of the sprite to put on the iconbar, and the name of the template file containing the info dialog box for the iconbar menu.

The wimp.templates library defines the function templates which expects two arguments, the name of the templates file, and a list of some of the window names defined there. It returns a table, indexed by those names, of window data. Each datum is a table with keys def , a pointer to a window definition block and work , a pointer to a block for indirected data.

The wimp.window library defines the function createwindow which expects as argument a pointer to a window definition block and which returns the window's handle. The use of these two libraries means that you do not need to know the details of how windows are defined.

handlers

The only parts of the program we have not described are snerp's handler functions, which describe its responses to wimp events and to messages.

-- snerp's actions
snerp.dragtoiconbar = \ (self,x,y,fname,ftype)
   self:report(fname.." dragged to Snerp icon")
   => true
 end -- function

snerp.dragtomain = \ (self,x,y,fname,ftype)
 self:report(fname.." dragged to Snerp main window")
   => true
  end -- function

snerp.ibarSelect = \ (self)
  local b,main,mainopen in self
  local r,! in swi
  if not mainopen then
     b[0] = main
     b[1],b[2],b[3],b[4] = 200,200,800,600
     b[5],b[6] = 0,0
     b[7] = -1
     r[1] = b
     !(0x400c5) -- Wimp_OpenWindow
     self.mainopen = true
   end -- if
   --     self:report "Select clicked on !Snerp icon"
   => true
  end -- function

snerp.ibarAdjust = \ (self)
   self:report "Adjust clicked on !Snerp icon"
   => true
  end -- function

snerp.mainclick = \ (self)
    self:report "Main window clicked"
    => true
   end -- function

-- define snerp's event handlers ---------------

snerp.handler[Open_Window_Request] = \ (self)
            local b in self
            local r,! in swi
            r[1] = b
            => !(0x400c5) -- Wimp_OpenWindow
            end

snerp.handler[Close_Window_Request] = \ (self)
            local b,main in self
            local r,! in swi
            r[1] = b
            !(0x400c6) -- Wimp_CloseWindow
            if b[0] == main then
               self.mainopen = false
            end -- if
            => true
            end

snerp.handler[Mouse_Click] = \ (self)
  local b,ibaricon,main,ibarAdjust,ibarSelect in self
  if b[3] == -2 and b[4] == ibaricon.handle then
   local click = {
       [1] = ibarAdjust;
       [2] = ibaricon.menuopen; -- sets snerp.lastmenu
       [4] = ibarSelect;
                 }
   local clickval = b[2]
   local action = click[clickval]
   if action then => action(self) end -- if
  end -- if
  if b[3] == main then
     => self:mainclick()
  end -- if
  => true
  end -- function

snerp.handler[Menu_Selection] = \ (self)
  local lastmenu, ibaricon in self
  local item = self.b[0]
  if lastmenu == ibaricon.menu then
    if item == 1 then
      os.execute("filer_run <Snerp$Dir>.!Help")
      => true
    end -- if
    if item == 2 then
      => nil -- exit
    end -- if
  end -- if
  => true
 end -- function

-- define snerp's message handler -------
snerp.messagehandler = \ (self)
 local b,ibaricon,main,dragtoiconbar,dragtomain in self
 local mesg = b[4]
 if mesg == DataLoad then
   if b[5] == -2 and b[6] == ibaricon.handle then
      => self:ack(dragtoiconbar,true)
   end -- if
   if b[5] == main then
      => self:ack(dragtomain,true)
   end -- if
 end -- if
 end -- function

The message handler responds to drags to the iconbar, calling dragtoiconbar and drags into the main window, calling dragtomain . The event handler responds to requests to open a window, to close a window, to mouse-clicks and to menu-selections. Note that each handler is a function of one argument, self , and returns a non-nil value unless it causes the task to quit.

back contents forward