7.3 Example: A ToyText Browser

In the following we discuss a tiny ToyText browser that supports following of links in the text and going back to previously displayed pages. A ToyText hypertext is a record, where the features are the links and the fields describe pages. For an example, see *. A page consists out of head and body, where the body is a list of elements. An element is either a virtual string or a record a(ref:R Es), where R is a feature of the record and Es is a list of elements.

Figure 7.3 shows the main routine to display a ToyText page in a text widget T. The procedure Display takes a list of references Rs as input, and displays the page that is referred to by its first element.


<Definition of Display>=
proc {Display Rs}
   case Rs of nil then skip 
   [] R|Rr then 
     {T tk(delete p(0 0) 'end')}
     {Head ToyText.R.head Rr} {Body ToyText.R.body Rs}
   end       
end

Figure 7.3: Displaying a ToyText page.


Figure 7.4 shows how the head of a ToyText page is displayed, where E is the virtual string to be displayed and Rs is the list of current references without its first element. The tag HT is configured such that clicking it displays the previous page.


<Definition of Head>=
local 
   HF={New Tk.font    tkInit(family:helvetica size:18 weight:bold)}
   HT={New Tk.textTag tkInit(parent:T font:HF foreground:orange)}
in 
   proc {Head E Rs}
      {T tk(insert p(0 0) E#'\n' HT)}
      {HT tkBind(event:  '<1>' 
                 action: proc {$} {Display Rs} end)}
   end 
end

Figure 7.4: Displaying the head of a ToyText page.


Figure 7.5 shows how the body of a ToyText page is displayed, where Es is the list of elements, CT is the current tag to which inserted text is added, and Rs are the current references, including a reference to the page currently under display as first element. To display a reference element, a new tag RT is created that carries as action a procedure that displays the referred page.


<Definition of Body>=
local 
   BF={New Tk.font    tkInit(family:helvetica size:12 weight:normal)}
   BT={New Tk.textTag tkInit(parent:T font:BF)}
   proc {Do Es CT Rs}
      case Es of nil then skip 
      [] E|Er then 
         case E
         of a(ref:R Es) then 
            RT={New Tk.textTag tkInit(parent:T font:BF
                                      foreground:blue underline:true)}
         in 
            {RT tkBind(event: '<1>' 
                       action: proc {$} {Display R|Rs} end)}
            {Do Es RT Rs}
         else 
            {T tk(insert 'end' E CT)}
         end 
         {Do Er CT Rs}
      end 
   end 
in 
   proc {Body Es Rs}
      {Do Es BT Rs}
   end 
end

Figure 7.5: Displaying the body of a ToyText page.


Figure 7.6 shows the complete ToyText browser and how it looks when displaying pages.


proc {ToyBrowse ToyText Root}
   W={New Tk.toplevel tkInit}
   T={New Tk.text tkInit(parent:W width:40 height:8 bg:white wrap:word)}
   
<Definition of Head> 
   
<Definition of Body> 
   
<Definition of Display> 
in 
   {Tk.send pack(T)}
   {Display [Root]}
end 
{ToyBrowse 
<Sample ToyText> canvas}

Figure 7.6: A ToyText browser.



Christian Schulte
Version 1.4.0 (20080702)