Amiga Machine Language (Chapter 7)

Innen: amigaspirit.hu - pegasos.hu Wiki
A lap korábbi változatát látod, amilyen Chain-Q (vitalap | szerkesztései) 2009. május 25., 13:36-kor történt szerkesztése után volt. (intial import as separate page)
(eltér) ← Régebbi változat | Aktuális változat (eltér) | Újabb változat→ (eltér)
Ugrás a navigációhozUgrás a kereséshez
   Chapter 7.
     ----------
     7.Working With Intuition.
     -------------------------
       Now that you've learned so much about machine language,lets look
       at the special features of the Amiga.Lets look at the operating
       system Intuition that is in charge of windows,screens,the mouse
       and lots of other things.Beforetaking a look at these beautiful   
       features,theres some bad news.
       First,though,lets here the good news.Since Intuition has so many
       functions,it allows you to be very creative in programming your
       ideas.The disadvantage is that the flexibility means that you have
       to use a lot of parameters,and that makes for a lot of tedious
       work.
       However,this is no grounds for panic.Once you've built up the
       necessary routines,the programming and experimentation becomes
       increasingly interesting.Before you try out new program variations
       you should save your source code to disk,because Intuition gets
       fairly upset about bad parameters and often responds by crashing
       the system.
       Now lets get to work.To start working with Intuition,you need the 
       Intuition library.You can load it with the OpenLibrary function
       from the EXEC library.Heres the subroutine that takes care of
       initialization.
       openlib   =-408
       execbase  = 4
       run:
              bsr     openint         ;load intuition library
              ...
       openint:                       ;*initialize and open system
              move.l  execbase,a6     ;exec base address 
              lea     intname,a1      ;name of intuition library
              jsr     openlib(a6)     ;open intuition
              move.l  d0,intbase      ;save intuition base address
              rts
       intname: dc.b "intuition.library",0
              align
       intbase: dc.l 0                ;base address of intuition
       When your program is finished,you need to close the screens,the
       window and the library.To do this,use the CloseLibrary function
       from the EXEC library.It has an offset of -414.
       Heres the subroutine:
       closelibrary  =-414
              ...
       closeint:                        ;*close intuition
              move.l  execbase,a6       ;exec base address in A6
              move.l  intbase,a1        ;intuition base address in A1
              jsr     closelibrary(a6)  ;close intuition
              rts                       ;done
       Now that you've got that taken care of,you can finally start
       working with Intuition.
     7.1.Open Screen.
     ----------------
       Intuition is a graphics operating system.For this reason,you'll be
       working with the screen.Its even more interesting to work with
       several screens at the same time.However,you only have one monitor
       on the Amiga.
       You can open as many screens as you like (at least,as long as
       theres some memory available).You can open a window,display menus
       and do I/O's there.The individual screens are fully independant.
       You can work with all of them simultaneously on the monitor.
       You can move individual screens forward and back to your hearts
       content.You can also press the left <Amiga> key and then an "m"to
       return to the workbench screen after getting into the different
       screens.
       You want to begin programming Intuition by setting up a screen.You
       have already loaded the Intuition library,so you can use the Open-
       Screen function.
       Wait a minute!What should the screen look like,where should it go,
       and what form should it have?You need to look at the options for
       the form of the screen you have available.
       The input to the screen is in the form of a table that has 13
       entries.Lets take a look at the parameters that you need for our
       screen.
       You'll start the table with the label "screen_defs"which must be
       at an even address:
              align
       screen_defs:                 ;The screen table begins here
       The first bit of information that the screen needs is the position
       and size.Lets have it start in the upper left corner and fill the
       entire screen.You'll use the positions X=0 and Y=0,the width 320
       and the height 200.This means that your screen is the maximum
       size.
       x_pos:     dc.w   0        ;X-Position
       y_pos:     dc.w   0        ;Y-Position
       width:     dc.w   320      ;width
       height:    dc.w   200      ;height
       Next you need to decide which colors should be displayed.That
       depends on the number of bitplanes,on the depth.Lets choose two.  
       That means you have 2^2 (4) colours available.Lets choose two,
       since four colours is usually plenty.
       depth:     dc.w   2        ;number of bitplanes
       Next you need to choose the colour of the title line and the
       function symbols.Give the number of the colour register:
       detail_pen:  dc.b   0      ;colour of text,etc...
       Now for the colour of the text background:
       block_pen    dc.b   1      ;background colour
       Make sure that these two inputs fit in a byte.The colours are
       normally the following (if the standard values have'nt been
       changed).You'll notice that the number of colours depends on the
       number of bit maps.
           Pen        Colour
        ---------------------------------------------------------
            0         Background (blue)
            1         White
         for two bit planes
            2         Black
            3         Red
         for three bit planes
            4         Blue
            5         Violet
            6         Turquoise
            7         White
         for four bit planes
            8         Black
            9         Red
           10         Green
           11         Brown
           12         Blue
           13         Blue
           14         Green
           15         Green
       The next word contains the bits that describe the appearance of
       the screen.The bits are:
       Bit    Value    Name             Meaning
       ---------------------------------------------------------------  
        1       2      GENLOCK_VIDEO    
        2       4      INTERLACE        Puts the screen in Interlace
                                        mode.The resolution and thus the 
                                        maximum screen size are doubled.
        6     $40      PFBA
        7     $80      EXTRA_HALFBRITE
        8     $100     GENLOCL_AUDIO
       10     $400     DBLPF            Divides the screen into a border
       and                              character area.
       11     $800     HOLDNMODIFY      Turns on Hold-and-Modify mode.
       13     $2000    VP_HIDE
       14     $4000    SPRITES          Allows sprites to be used.
       15     $8000    MODE_640         Turns on the highest resolution  
                                        graphics for the screen(640x400).
       Choose the value two (normal) for your example screen:
       view_modes:  dc.w   2         ;representation mode
       The following word is constructed in such away that each bit as
       its own meaning.Use this to set what sort of screen it is.Choose
       15 so the screen is a "Custom screen",which allows you all of the 
       options.
       screen_type:  dc.w  15      ;screen type:custom screen
       Next theres a pointer to the character set to be used for all
       output to the screen.If you don't want to install your own
       character set,just put a zero here,and the standard character set 
       is used.
       font:   dc.l  0         ;character set:standard
       Next theres a pointer to the text thats used as the name of the
       screen.The text ends with a zero,just like window names must. 
       title:  dc.l  name      ;pointer to title text
       Next comes a long word that defines the gadgets.These gadgets
       represent the functions,like "Bring forward",that can be accessed 
       via a mouse click in the screen.The long word in this table is a
       pointer to a list which specifies the gadgets.These aren't the
       system gadgets.However,you're only using system gadgets here,so
       put a zero here.
       gadgets:  dc.l  0        ;no gadgets
       Finally theres a long word that you only need if you want to use
       the special bitmap just for your screen.Since this isn't the case,
       just put a zero here.
       bitmap:  dc.l  0         ;no bitmap
       Thats it for the list entries that you need to define the screen. 
       You still need the text for the name of the screen.Enter the
       following:
       sname:   dc.b  'Our Screen',0    ;screen title
       Heres a quick overview of the list:
              align
       screen_defs:                  ;*The screen ta
       x_pos:        dc.w  0         ;X-position
       y_pos:        dc.w  0         ;Y-position
       width:        dc.w  320       ;width
       height:       dc.w  200       ;height
       depth:        dc.w  2         ;number of bitplanes
       detail_pen:   dc.b  0         ;colour of the text,etc...
       block_pen:    dc.b  1         ;background colour
       view_modes:   dc.w  2         ;representation mode
       screen_type:  dc.w  15        ;screen type:custom screen
       font:         dc.l  0         ;character set:standard
       title:        dc.l  sname     ;pointer to title text
       gadgets:      dc.l  0         ;no gadgets
       bitmap:       dc.l  0         ;no bit map
       sname:        dc.b  'Our Screen',0  ;screen title
       Once you've decided on the parameters,its very easy to open the
       screen.You need Intuitions OpenScreen function.Its offset is -198 
       and it only needs one parameter,the address of the parameter
       table.The program fragment looks like this:
       openscreen =-198
              bsr     openint            ;open intuition
              bsr     scropen            ;open screen
              ...
       scropen:                          ;*open screen
              move.l  intbase,a6         ;intuition base address in A6
              lea     screen_defs,a0     ;pointer to table
              jsr     openscreen(a6)     ;and open
              move.l  d0,screenhd        ;save screen handle
              rts                        ;return to main program
              ...
       screen_defs:                      ;table info follows
       Now the Amigas Workbench screen is covered by your screen.Now you 
       can do what you want with it until the program is done.Afterwards,
       the screen must be closed again,so that you can see the Workbench 
       screen again.
       Use the CloseScreen function (offset -66) to do this.The only
       parameter it needs is the pointer to the screen structure you got 
       back from the OpenScreen function.
       closescreen =-66
              ...
       scrclose:                         ;* close screen
              move.l  intbase,a6         ;intuition base address in A6
              move.l  screenhd,a0        ;screen handle in A0
              jsr     closescreen(a6)    ;clos screen
              rts                        ;done
       The long word that OpenScreen returned to you is a pointer to a
       screen structure that contains all the needed data about the
       screen.Besides the data which was given,there is a pointer in the 
       screen area for individual bit planes,etc...
       The form of this structure is fairly complicated and contains some
       data that you can't use.Several of the parameters are interesting,
       however.Heres a selection of usable parameters:
       No    Name              Function
       ------------------------------------------------------------------
       0     (NextScreen.L)    Pointer to next screen.
       4     (FirstWindow)     Pointer to first window structure
       8     (LeftEdge.W)      
       $A    (TopEdge.W)       Position of screen
       $C    (Width.W)         Width
       $E    (Height.W)        Height
       $10   (MouseY.W)
       $12   (MouseX.W)        Mouse position in the screen
       $14   (Flags.W)         Screen flags
       $16   (Title.L)         Pointer to title text
       $1A   (DefaultTitle)    Pointer to normal title
       $28   (Font.L)          Pointer to character set
       $C0   (Plane0.L)        Pointer to bitplane 0
       $C4   (Plane1.L)        Pointer to bitplane 1
       $C8   (Plane2.L)        Pointer to bitplane 2
       $CC   (Plane3.L)        Pointer to bitplane 3
       An example of an application for the plane pointer is writing and 
       using your own character routine.Next you want to move the address
       of the plane into an address register as follows:
              move.l  screenhd,a5        ;screen pointer in A5
              move.l  $c0(a5),a5         ;bitplane 0-pointer in A5
       If you want to try this,do the following:
              move.l  screenhd,a5        ;screen pointer in A5
              move.l  $c0(a5),a5         ;bitplane 0-pointer in A5
              move    #$20,d0            ;Counter D0=$20
       lop1:
              move    d0,(a5)            ;write counter bits in picture
              add.l   #80,a5             ;address+80,next line
              dbra    d0,lop1            ;continue until D0 < 0
       This program draws a white,square pattern that corresponds to the 
       bit pattern for the numbers $20 to 0.This isn't a particularly
       useful program,but it shows how easy it is to write from a machine
       language program directly to the screen.If you change the offset
       in the second line to $C4,the pattern is read.
       You can move the entire screen with the normal technique of moving
       the mouse pointer into the upper border and moving it up and down 
       with the left mouse key depressed.You can do the same with a
       program.
       Lets move the screen without the mouse.Use the joystick for
       demonstration purposes.Put the joystick in port two.As you saw in
       the chapter on the hardware register,you can read memory location 
       $DFF00C to find information about the joystick.You can find the
       direction the screen should be moved here.
       Moving the screen requires another Intuition function.You use the 
       MoveScreen function which as an offset of -162 and needs three
       parameters to do this.The parameters are:
       In A0   the pointer to the screen structure that you got back in
               D0 when you opened the screen.(You saved it in "screenhd")
       In D1   the desired movement in the Y-direction,the vertical
               direction.
       In D0   the horizontal movement in the X-direction.The varient
               doesn't work so you can only move the screen vertically.
       Insert the following lines in your program:
       MoveScreen =-162
              ...
       scrmove:                          ;*move screen D0 to the right
                                         ;and D1 down
              move.l  intbase,a6         ;intuition base address in A6
              move.l  screenhd,a0        ;screen handle in A0
              clr.l   d0                 ;no horizontal movement
              jsr     movescreen(a6)     ;move screen
              rts                        ;done
       Now your looking at a complete program that goes through the
       following steps:
       1.  Opens the Intuition library
       2.  Opens the screen
       3.  Moves the screen in the direction specified by the joystick in
           port two
       4.  Closes the screen when the fire button is hit
       5.  Closes the Intuition library
       6.  Ends
       Here is the complete program including the subroutines,so you'll
       have it all in one spot:
       ;** Demo program to open and move a screen **
       movescreen   =-162
       openscreen   =-198
       closescreen  =-66
       closelibrary =-414
       openlib      =-408                ;open library
       execbase     = 4                  ;exec base address
       joy2         =$dff00c             ;joystick 2 data
       fire         =$bfe001             ;firebutton 2:bit 7
       run:
              bsr     openint            ;open intuition
              bsr     scropen            ;open screen
              move    joy2,d6            ;save joystick info
       loop:
              tst.b   fire               ;test fire button
              bpl     ende               ;pressed down:done
              move    joy2,d0            ;basic info in D0
              sub     d6,d0              ;subtract new data
              cmp     #$0100,d0          ;up?
              bne     noup               ;no
              move.l  #-1,d1             ;dy=-1 direction y
              bsr     scrmove            ;move up
              bra     loop
       noup:
              cmp     #$0001,d0          ;down?
              bne     loop               ;no
              move.l  #1,d1              ;dy=1
              bsr     scrmove            ;move down
              bra     loop
       ende:
              bsr     scrclose           ;close screen
              bsr     closeint           ;close intuition
              rts                        ;done!
       openint:                          ;*initialize and open system
              move.l  execbase,a6        ;exec base address
              lea     intname,a1         ;name of intuition library
              jsr     openlib(a6)        ;open intuition
              move.l  d0,intbase         ;save intuition base address
              rts
       closeint:                         ;*close intuition
              move.l  execbase,a6        ;exec base address in A6
              move.l  intbase,a1         ;intuition base address in A1
              jsr     closelibrary(a6)   ;close intuition
              rts                        ;done
       scropen:                          ;*open screen
              move.l  intbase,a6         ;intuition base address in A6
              lea     screen_defs,a0     ;pointer to table
              jsr     openscreen(a6)     ;open
              move.l  d0,screenhd        ;save screen handle
              rts                        ;return to main program
       scrclose:                         ;*close screen
              move.l  intbase,a6         ;intuition base address in A6
              move.l  screenhd,a0        ;screen handle in A0
              jsr     closescreen(a6)    ;close screen
              rts                        ;done
       scrmove:                          ;move screen D0 right/D1 down
              move.l  intbase,a6         ;intuition base address in A6
              move.l  screenhd,a0        ;screen handle in A0
              clr.l   d0                 ;no horizontal movement
              jsr     movescreen(a6)     ;and move
              rts                        ;done
              align
       screen_defs:                      ;*screen table begins here
       x_pos:         dc.w  0            ;X-position
       y_pos:         dc.w  0            ;Y-position
       width:         dc.w  320          ;width
       height:        dc.w  200          ;height
       depth:         dc.w  2            ;number of bitplanes
       detail_pen:    dc.b  1            ;Text colour=white
       block_pen:     dc.b  3            ;background colour=red
       view_modes:    dc.w  2            ;representation mode
       screen_type    dc.w  15           ;screen type:custom screen
       font:          dc.l  0            ;standard character set
       title:         dc.l  sname        ;pointer to title text
       gadgets:       dc.l  0            ;no gadgets
       bitmap:        dc.l  0            ;no bit map
       intbase:       dc.l  0            ;base address of intuition
       screenhd:      dc.l  0            ;screen handle
       intname:       dc.b  'intuition.library',0
              align
       sname:         dc.b  'Our Screen',0   ;Screen title
              align
              end
       From this example,you can see how easy scrolling actually is.     
       Another easy thing to do is to use the DisplayBeep function.It as 
       an offset -96;the only parameter it needs is the screen pointer
       that you stored in the "screenhd"memory block.This function covers
       the screen with an orange colour for a short while.The screen is  
       not changed.The beep function can be used as follows:
       DisplayBeep: =-96
              ...
              move.l  intbase,a6         ;intuition base address in A6
              move.l  screenhd,a0        ;screen pointer in A0
              jsr     displaybeep(a6)    ;light up screen
       If you put a zero instead of a screen pointer in A0,the whole
       screen blinks.
       Good,now you have your own screen that you can move up and down.  
       What good is it if you can't put anything on it?Lets open a window
       on the screen!
     7.2.Open Window.
     ----------------
       As you saw in the chapter on program initialization,its easy to
       open a window with the DOS library.You can't use this method on
       your own screen however.You need to use another method that can
       open any window on any screen.
       Intuition has a function called OpenWindow which handles this sort
       of work.It has an offset of -204 and needs only one parameter,a
       pointer to a window definition table.This pointer goes in register
       A0.
       This table is very similar to the one used to define the screen.  
       The first four values specify the X-and Y-positions,the width,and
       the height of the window to be opened.Heres an example:
              align
       window_defs:
                      dc.w  10           ;x-position
                      dc.w  20           ;y-position
                      dc.w  300          ;width
                      dc.w  150          ;height
       Next come two bytes that define the colour of the letters on the  
       background:
                      dc.b  1            ;white letter colour
                      dc.b  3            ;on a red background
       The next long word contains the IDCMP flags in its bits.The bits  
       determine the circumstances under which Intuition sends a message 
       to the program.The bits have the following meanings:
       Bit  Value     Name             Meaning
       -----------------------------------------------------------------
        0   $000001   SIZEVERIFY
        1   $000002   NEWSIZE          Window size changed
        2   $000004   REFRESHWINDOW
        3   $000008   MOUSEBUTTONS     Mouse key hit
        4   $000010   MOUSEMOVE        Mouse moved
        5   $000020   GADGETDOWN       A special gadget chosen
        6   $000040   GADGETUP         Same as above
        7   $000080   REQSET
        8   $000100   MENUPICK         A menu item chosen
        9   $000200   CLOSEWINDOW      A window closed
       10   $000400   RAWKEY           A key pressed
       11   $000800   REQVERIFY
       12   $001000   REQCLEAR
       13   $002000   MENUVERIFY
       14   $004000   NEWPREFS         Preferences modified
       15   $008000   DISKINSERTED     A disk put in
       16   $010000   DISKREMOVED      A disk taken out
       17   $020000   WBENCHMESSAGE
       18   $040000   ACTIVEWINDOW     A window activated
       19   $080000   INACTIVEWINDOW   A window deactivated
       20   $100000   DELTAMOVE        Report relative mouse movement
       If you want your first window to respond only by clicking on the
       close symbol,write the following:
           dc.l  $200   ;IDCMP flags:CLOSEWINDOW
       Next comes a long word whose bits determine the windows type.You  
       can use this to construct a window to your exact specifications.  
       This is quite different from windows opened with the DOS function.
       The bits mean:
       Bit  Value     Name             Meaning
       ------------------------------------------------------------------
        0   $0000001  WINDOWSIZING     Window size is changeable
        1   $0000002  WINDOWDRAG       Window is moveable
        2   $0000004  WINDOWDEPTH      Window covering is posible
        3   $0000008  WINDOWCLOSE      Window close symbol
        4   $0000010  SIZEBRIGHT
        5   $0000020  SIZEBOTTOM
        6   $0000040  SIMPLE_REFRESH   New drawing manuel
        7   $0000080  SUPER_BITMAP     Save the windows contents
        8   $0000100  BACKDROP         Move window back
        9   $0000200  REPORTMOUSE      Report mouse co-ordinates
       10   $0000400  GIMMEZEROZERO
       11   $0000800  BORDERLESS       Window without border
       12   $0001000  ACTIVATE         Window active
       13   $0002000  WINDOWACTIVATE
       14   $0004000  INREQUEST
       15   $0008000  MENUSTATE
       16   $0010000  RMBTRAP          Right mouse key:no menu
       17   $0020000  NOCAREREFRESH    No refresh message
       24   $1000000  WINDOWREFRESH
       25   $2000000  WBENCHWINDOW
       To refresh is to rebuild the window contents when necessary,for
       instance when the windows size is changed.If none of the refresh
       bits are set,you're in Smart-Refresh-Mode.In this case,Intuition
       takes care of refreshing the window.This is the easiest method.
       If you choose the value $100F as the type for your example window,
       the window is active once its opened,and it has all the system
       gadgets:
            dc.l   $100F       ;ACTIVATE and all gadgets
       The next long word in the list allows you to use your own gadgets
       in the window.This long word is a pointer to the structure of a
       your gadget.Since you don't want this,just put a zero here.
            dc.l   0           ;first gadget:no gadgets of our own
       The next long word is a pointer to a graphics structure so you can
       design your own symbol for checking menu points.Put a zero here.
       You'll use the standard sign:
            dc.l   windowname  ;pointer to window name
       The next long word is a pointer to the screen structure that you
       got back after calling the OpenScreen function.The easiest way to
       do this is to save the pointer to this location in the buffer:
       screenhd:   dc.l 0   ;screen pointer
       The next long word is a pointer to a bit map if you want one of
       your own for the window.Since you don't want one,put a zero here.
               dc.l  0        ;no bit map of our own
       Next come four values that set the maximum and minimum width and  
       height of the window:
               dc.w  150      ;smallest width
               dc.w  50       ;smallest height
               dc.w  320      ;maximum width
               dc.w  200      ;maximum height
       The last value in the list is the screen type of the screen the
       window is located in.Put a 15 here.You're using our screen as a   
       custom screen:
               dc.w  15       ;screen type:custom screen
       Heres a quick overview of the whole list:
           align
       window_prefs:
                     dc.w   10           ;X-position
                     dc.w   20           ;Y-position
                     dc.w   300          ;width
                     dc.w   150          ;height
                     dc.b   1            ;white print colour
                     dc.b   3            ;on red background
                     dc.l   $200         ;IDCMP flags:CLOSEWINDOW
                     dc.l   $100f        ;ACTIVATE and all gadgets
                     dc.l   0            ;first gadget:no gadgets of
                                         ;our own
                     dc.l   0            ;checkmark:standard
                     dc.l   windowname   ;pointer to window name
       screenhd:     dc.l   0            ;screen pointer
                     dc.l   0            ;no bitmap of our own
                     dc.w   150          ;smallest width
                     dc.w   50           ;smallest height
                     dc.w   320          ;maximum width
                     dc.w   200          ;maximum height
                     dc.w   15           ;screen type:custom screen

       ;and here comes the window name:
       windowname:   dc.b   'Our Window',0
           align
       Insert these lines in the program you listed above.Here are two   
       subroutines for opening and closing the window:
       openwindow  =-204
       closewindow =-72
              ...
       windopen:
              move.l  intbase,a6        ;intuition base address in A6
              lea     windowdef,a0      ;pointer to window definition
              jsr     openwindow(a6)    ;open window
              move.l  d0,windowhd       ;save window handle
              rts
       windclose:
              move.l  intbase,a6        ;intuition base address in A6
              move.l  windowhd,a0       ;window handle
              jsr     closewindow(a6)   ;close window
              rts
              ...
       windowhd:      dc.l   0          ;window handle
       Now you can insert a "bsr windowopen"after the "bsr scropen"and a 
       "bsr windclose"before the "bsr scrclose"command.Once you've
       started the program,move the window around in the screen.You'll
       find that you can't move the window out of the screen with the
       mouse. 
       The window in the example has the close gadget in the upper left
       corner.Normally if you click it,the window is closed.Try clicking
       it.You'll find that nothing happens.
       The display of this and all other gadgets,as well as other events
       must be programmed in,since Intuition doesn't know which action
       causes which event.We'll take a look at how to handle this in the 
       next chapter.
     7.3.Requesters.
     ---------------
       If you only have one disk drive,you've certainly seen the Amiga   
       message,"Please insert xxx in unit 0",a lot.This window is another
       that has two fields for clicking.This sort of message with a
       choice of options is called a requester.                          
       You want to take a look at how to program a requester.First,you
       need a window for the requester to appear in.You opened a window
       of this sort in the example program.
       To display a requester,use the Intuition function AutoRequest
       (offset -348).It takes care of drawing and managing the requester.
       This function needs the following parameters:
       In A0   The pointer to the window structure that you put in
               "windowhd".
       In A1   A pointer to the text structure that should stand over the 
               choice buttons.
       In A2   Same as above for the text of the left button.
       In A3   Same as above for the right button.
       In D0   The IDCMP flag which lets you know what event should go
               with the clicking of the left button.
       In D1   Same as above for the right button.
       In D2   The width of the whole requester.
       In D3   The height of the requester.
       Insert the following lines in your program:
       autorequest =-348
              ...
       request:
              move.l  windowhd,a0       ;pointer to window structure
              lea     btext,a1          
              lea     ltext,a2          ;pointer to text structure
              lea     rtext,a3        
              move.l  #0,d0             ;left activates by clicking
              move.l  #0,d1             ;right activates by clicking
              move.l  #180,d2           ;width and
              move.l  #80,d3            ;height of requester
              move.l  intbase,a6        ;intuition base address
              jsr     autorequest(a6)   ;display requester
              rts
       The flags passed in D0 and D1 offer some interesting posibilites. 
       The system messages that tells you to enter a particular disk are 
       overlooked when the DISKINSERTED flag is similar.Putting a disk in
       brings about the same responce as clicking the "Retry"button.
       Whats new is the use of a text structure.Use three of them.Text   
       structures are lists that contain entries for the text that you
       need. 
       These lists begin with two bytes that are used to define the
       colour.The first byte is the colour of the text.The second is for
       the background colour.Here this doesn't have any meaning.
       btext:
              dc.b    2                 ;black text colour
              dc.b    0                 ;background colour
       The next byte specifies the character mode.A zero means that the
       text is output normally.A four means the text is output inverted.
              dc.b    0                 ;normal text representation
       The next entries are words.For this reason the addresses must be
       even,so you need to either insert another byte or use the "align" 
       pseudo-op.The following words are the X-and Y-position of the text
       relative to the upper left corner of the requester.
              dc.w    10                ;X-position
              dc.w    5                 ;Y-position relative to upper
                                        ;left corner
       Next,theres a pointer to the character set that is used.Put a zero
       here to use the standard set.
              dc.l    0                 ;standard character set
       Next you need to give the address of the text that should be
       output.This text must be closed with a null byte.
              dc.l    text              ;pointer to text
       You need a long word at the end of the list that is either a
       pointer to another text or a zero if no more text is needed.
              dc.l    0                 ;no more text
       Here are the three text structures that you need for the example:
       btext:                           ;text structure for the title
              dc.b    0,1               ;colour
              dc.b    0                 ;mode
              align
              dc.w    10,10             ;text position
              dc.l    0                 ;standard font
              dc.l    bodytxt           ;pointer to text
              dc.l    0                 ;no more text
       bodytxt:
              dc.b    "Requester Text",0
              align
       ltext:                           ;text structure of left button
              dc.b    0,1               ;colour
              dc.b    0                 ;mode
              align 
              dc.w    5,3               ;text position
              dc.l    0                 ;standard font
              dc.l    lefttext          ;pointer to text
              dc.l    0                 ;no more text
       lefttext:
              dc.b    "left",0
              align
       rtext:
              dc.b    0,1               ;colour
              dc.b    0                 ;mode
              align
              dc.w    5,3               ;text position
              dc.l    0                 ;standard font
              dc.l    righttext         ;pointer to text
              dc.l    0                 ;no more text
       righttext:
              dc.b    "right",0
              align
       After calling the requester,D0 contains the information about
       which of the buttons were pressed,and in which button the event
       took place.If D0 is zero,it was the right button.If it is one,it
       was the left button.
     7.4.Event Handling.
     -------------------
       Pretend you've opened a window that as a close symbol,and you want
       the program to react to this symbol being clicked.You need a
       signal from Intuition that lets you know that an event as taken
       place.The signal is called a message.
       The IDCMP flag of the window specifies which events should cause
       Intuition to send a message.By setting the bits for WINDOWCLOSE,  
       you can allow a message to be sent when the close symbol is
       clicked.
       To get the message,you can use the EXEC function GetMsg (offset
       -372).It needs the source address of the event as a parameter.Here
       the source is the User port (which doesn't have anything to do
       with the User port on old Commodore computors).
       The User port contains a table which has entrieswhich specify the
       events that have taken place and related things like mouse
       position and time.
       How do you find the User port?Use the pointer to the window
       structure that you got back from the OpenWindow function and
       stored in the "windowhd"memory block.
       This pointer points to the window structure of this window.This
       structure consists of a number of entries.Some are copies of the
       parameters from our window definition table.We won't cover all the
       entries,because most won't be interesting to you.You're more
       interested in the pointer to the User port.Its in the window
       structure.
       You can find this in the long word that begins in the 86th byte of
       the structure.You can get this long word with the following lines
       of code:
              move.l  windowhd,a0       ;pointer to structure in A0
              move.l  86(a0),a0         ;user port pointer in A0
       You can call the GetMsg function with this pointer in A0 by using 
       the following lines of code in your program:
       GetMsg  = -372
              ...
              move.l  windowhd,a0       ;pointer to structure in A0
              move.l  86(a0),a0         ;user port pointer in A0
              move.l  execbase,a6       ;exec base address in A6
              jsr     getmsg(a6)        ;get message
       This function returns a value in the D0 register.This value is a  
       pointer to another structure,the Intuition Message Structure.If
       theres a zero in D0,no event as taken place.
       The long word that starts at the 20th byte in this structure
       contains the information about which event took place.Evaluating
       the information is easy,since the bits of this long word have the 
       same meaning as the IDCMP flag that you described when you looked 
       at opening windows.
       Put the lines above after "loop"and then insert the following:
              move.l  d0,a0             ;message pointer in A0
              move.l  20(a0),d6         ;save event in D6
              tst.l   d0                ;did the event take place?
              bne     end               ;yes!
       Now you can end this program by clicking the close symbol.This way
       you can find out if an event as taken place.You can use D6 to
       determine what event took place.In the example,D6 contains the
       number $00000200,which means that the close symbol was clicked.
       To see if this works with other events,change the $200 IDCMP flag
       to $10200 in the window definition table.When you've assembled and
       started this version,take the disk out of the drive-the program
       terminates.
       The IDCMP flags that you've got now cause the clicking of the
       close symbol and the taking out of the disk (DISKREMOVED) to be
       reported.If you want to find out which of the events took place,  
       you can look in D6.It has a $200 in it if the window is closed,a  
       $10000 if the disk was removed.
     7.5.Menu Programming.
     ---------------------
       Now lets look at one of Intuitions more interesting capabillities:
       menu programming.By using menus,you can make your programs very
       user friendly.
       There are a lot of ways for you to use menus.You can make menu
       points unusable,output sub-menus,choose the type of menu entries  
       (allow text or pictures to be output),etc..To have lots of options
       you need some parameters.
       Lets produce a menu with the SetMenuStrip function (offset -264)
       of Intuition.The function only needs two parameters,a pointer to
       the menu structure of the window to be drawn and a pointer to the 
       window structure of the window in which the menu is to function.  
       Each window can have its own menu that is active when the window
       is activated.
       Heres the subroutine to set up the menu:
       SetMenuStrip =-264
              ...
       setmenu:                         ;* Initialize a menu
              move.l  intbase,a6        ;intuition base address in A6
              move.l  windowhd,a0       ;pointer to window structure
              lea     menu,a1           ;pointer to menu structure
              jsr     setmenustrip(a6)  ;call function
              rts
       Heres a routine to erase the menu:
       ClearMenuStrip =-54
              ...
       clearmenu:
              move.l  intbase,a6        ;intuition base address in A6
              move.l  windowhd,a0       ;pointer to window structure
              jsr     clearmenustrip(a6)
              rts
       You've already got the pointer to the window structure.Lets look
       at the menu structure you need for the menu.You need to build a
       structure like this for each menu--for each menu title that
       appears when you press the right mouse key.
       This structure is a table with the following form:
       First there is a long word that points to the menu structure of
       the next menu.If the current menu is the last one,a zero goes
       here.
              align
       menu:
              dc.l    menu1             ;pointer to the next menu
       Next come two words which contain tha X- and Y-position of the
       menu title:
              dc.w    20                ;X-position
              dc.w    0                 ;Y-position
       Next,use two words to store the menu titles width and height in
       pixels:
              dc.w    50                ;width
              dc.w    10                ;height of menu title
       The next word contains the flag bit that determines whether the
       menu is available or not.An unavailable menu either as grey
       entries or they are drawn weakly.If the flag bit,bit 0,is set the 
       menu is available.Otherwise,it is not.
              dc.w    1                 ;menu available
       Now comes a long word which functions as a pointer to the text
       which is used as the menu title.Make sure the length isn't larger 
       than the width entry allows!Otherwise unpleasent things will
       happen.
              dc.l    menutext          ;pointer to title text
       Next comes a long word which functions as a pointer to the
       structure of the first menu entry of this menu.Each menu entry
       needs its own structure. 
              dc.l    menuitem01        ;pointer to the first menu item
       The last entries in the table are four words that are reserved for
       internal functions.They must be here.
              dc.w    0,0,0,0           ;reserved words
       Thats the structure of the first menu.This structures first long
       word points to the next structure which has the same form.The
       pointer is set to zero in the last menu.
       You still need the structure of the menu entries.These structure
       tables have the following form:
       They start with a pointer to the next menu item.This pointer is
       set to zero for the last entry.
              align
       menuitem01:
              dc.l    menuitem02        ;pointer to next menu item
       Next comes the four words:the X- and Y-position,the width and the 
       height of the box the menu entry goes in.The size becomes obvious 
       when the item is chosen by having the right mouse key clicked on
       it.Then the box becomes visible.As you can see,the next word is   
       determined in the flags.First lets set the position and size of
       the menu point,though:
              dc.w    0                 ;X-position of entry
              dc.w    0                 ;Y-position
              dc.w    90                ;width in pixels
              dc.w    10                ;height in pixels
       The position entries are relative to the upper left corner of the 
       menu that is pulled down.
       The following word was described above:it contains flags for
       entries to this menu item.There are several interesting variations
       possible.The following flag bits are contained in this word:
       Bit   Value   Name          Meaning When Set
       ------------------------------------------------------------------
        0    $0001   CHECKIT       Point is checked when chosen
        1    $0002   ITEMTEXT      Text menu item
        2    $0004   COMMSEQ       Choice can be made with keys as well
        3    $0008   MENUTOGGLE    Check turned on and off
        4    $0010   ITEMENABLED   Menu item available
        6    $0040   HIGHCOMP      Item inverted when chosen
        7    $0080   HIGHBOX       Iten framed when chosen
        8    $0100   CHECKED       Item is checked
       Heres a description of the bits:
       Name           Description
       ------------------------------------------------------------------
       CHECKIT        If this bit is set,a check or a user-defined
                      drawing is put in front of the text when the item  
                      is chosen.The text should begin with two blanks.
       
       ITEMTEXT       The menu item is a normal text if this bit is set. 
                      Otherwise a drawing is output.
       COMMSEQ        By setting this bit and entering a character,this  
                      menu point can be chosen by pressing the right
                      <Amiga> key and the key that was input.The input   
                      character is then displayed in the menu with the
                      Amiga symbol.There needs to be space available for 
                      this.
       MENUTOGGLE     If this bit is set and checking is allowed (bit 0),
                      the second time this point is chosen the check is
                      erased,the next time it is displayed again,etc...
       ITEMENABLED    Erasing this bit makes the menu item available.
       HIGHCOMP       If this bit is set,the box you've defined is
                      inverted when this menu item is chosen by the mouse
                      pointer.
       HIGHBOX        In this mode,the box is framed whin its chosen.
       The two previous bits determine the mode of the chosen menu item. 
       The following combinations are possible:
       HIGHIMAGE      If both bits are cleared,choosing the bit causes a 
                      self-defined drawing to be output.
       HIGHNONE       When both bits are set,there isn't any reaction to 
                      choosing this item.
       CHECKED        This bit can be set by either the program or
                      Intuition.It lets you know if the menu text has a
                      check next to it or not.You can use this to find
                      out if the item was checked by testing but eight.If
                      its set,the item was checked.You can also use it to
                      cause the item to be checked.
       You're choosing the mode CHECKIT,ITEMTEXT,COMMSEQ,MENUTOGGLE,ITEM-
       ENABLED and HIGHBOX for the example:
             dc.w    $10011111         ;mode flag
       Lets get back to the structure of the menu items.After the flag
       word,there is a long word whose flag bits determine whether this  
       menu point can be turn off another one.Set this to zero:
             dc.l    0                 ;no connection
       Now comes the pointer to the structure of the text that should be 
       displayed.If the ITEMTEXT bit isn't set,this pointer must point to
       the structure of the drawing.If nothing should be shown,you can
       set this to zero.Use a text in the example and write the
       following:
             dc.l    menu01text        ;pointer to menu text structure
       The following long word only has a meaning if the HIGHIMAGE flag
       is set.Then this long word points to the text or the drawing that 
       should be displayed when the menu items box is clicked.Otherwise  
       the long word is ignored,so insert a zero:
             dc.l    0                 ;no drawing when clicked
       The next entry is a byte that is used for input of keyboard
       characters,which together with the right <Amiga> key can be used
       to choose the menu item.This only works if the COMMSEQ bit is set.
       Place a character here:
             dc.b    'A'               ;choose item using <Amiga>/'A'
       Since the next item is a long word,you need an "align"peudo-op
       here.Next comes the long word that points to the menu item
       structure or a submenu.The submenu is automatically shown when
       this menu item is clicked.You can't nest them any deeper,however, 
       so this long word is ignored for submenus.
       If you don't want a submenu to this item,put a zero here:
         align
             dc.l    0                 ;no submenu
       The next and final long word is written to by Intuition if you
       choose several menu itens.In this case,the menu number of the next
       menu item chosen goes here:
             dc.l    0                 ;preparation
       Thats the structure for a menu item.You still need the text
       structure for the text of the item.This isn't complicated,but it
       makes you get into fine details about the form of the menu.You've 
       already learned about this text structure when you looked at
       requesters,so we'll skip an explanation.
       Heres the complete structure of an example menu.You can use two
       menus,each with two subpoints.The second menu point of the left
       menu has a submenu with two entries.You ought to type this program
       in,so that you can experiment with it.You can also use this
       example to evaluate the clicked menu item.
       ;**Complete menu structure foe example menu **
       menu:
              dc.l menu1         ;no next menu
              dc.w 10,30         ;X/Y
              dc.w 50,10         ;width/height
              dc.w 1             ;menu enabled
              dc.l menuname      ;menu title
              dc.l menuitem01    ;menu entry
       menuname:
              dc.b "Menu 1",0    ;first menu name
          align
       menu1:
              dc.l 0             ;no further menu
              dc.w 80,0          ;see above
              dc.w 50,10
              dc.w 1
              dc.l menuname1
              dc.l menuitem11
              dc.w 0,0,0,0
       menuname1:
              dc.b "Menu 2",0    ;second menu name
          align
       menuitem01:               ;first menu item
              dc.l menuitem02    ;pointer to next entry
              dc.w 0,0           ;X/Y
              dc.w 130,12        ;width/height
              dc.w $9f           ;flags
              dc.l 0             ;exclude
              dc.l text01        ;pointer to text structure
              dc.l 0             ;select fill
              dc.b "1"           ;command
          align
              dc.l 0             ;subitem:none
              dc.w 0             ;next select:no
       text01:
              dc.b 0,1           ;colours
              dc.b 0             ;mode:overwrite
          align
              dc.w 5,3           ;X/Y position
              dc.l 0             ;standard character set
              dc.l text01txt     ;pointer to text
              dc.l 0             ;no more text
       text01txt:
              dc.b "Point 0.1",0
          align
       menuitem02:               ;second menu item
              dc.l 0
              dc.w 0,10
              dc.w 130,12
              dc.w $57
              dc.l 0
              dc.l text02
              dc.l 0
              dc.b "2"           ;activate with <Amiga>/'2'
          align
              dc.l 0
              dc.w 0
       text02:
              dc.b 0,1
              dc.b 0
          align
              dc.w 5,3
              dc.l 0
              dc.l text02txt
              dc.l 0
       text02txt:
              dc.b "Point 0.2",0
          align
       menuitem11:               ;first menu point of the second menu
              dc.l menuitem12    ;pointer to second menu point
              dc.w 0,0
              dc.w 90,12
              dc.w $52
              dc.l 0 
              dc.l text11
              dc.l 0
              dc.b 0
          align
              dc.l 0
              dc.w 0
       text11:
              dc.b 0,1
              dc.b 0
          align
              dc.w 5,3
              dc.l 0
              dc.l text11txt
              dc.l 0
       text11txt:
              dc.b "Point 1.1",0
          align
       menuitem12:               ;second menu item of second menu
              dc.l 0             ;no more items
              dc.w 0,10
              dc.w 90,12
              dc.w $92
              dc.l 0
              dc.l text12
              dc.l 0
              dc.b 0
          align
              dc.l submenu0      ;pointer to submenu
              dc.w 0
       text12:
              dc.b 0,1
              dc.b 0
          align
              dc.w 5,3
              dc.l 0
              dc.l text12txt
              dc.l 0
       text12txt:
              dc.b "Point 1.2",0
          align
       submenu0:                 ;first point of submenu
              dc.l submenu1      ;pointer to next point
              dc.w 80,5
              dc.w 90,12
              dc.w $52
              dc.l 0
              dc.l texts0
              dc.l 0
              dc.b 0
          align
              dc.l 0
              dc.w 0
       texts0:
              dc.b 0,1
              dc.b 0
          align
              dc.w 5,3
              dc.l 0,texts0txt,0
       texts0txt:
              dc.b "S Point 1",0
          align
       submenu1:                 ;submenu,second item
              dc.l 0
              dc.w 80,15
              dc.w 90,12
              dc.w $52
              dc.l 0
              dc.l texts1
              dc.l 0
              dc.b 0
          align
              dc.l 0
              dc.w 0
       texts1:
              dc.b 0,1
              dc.b 0
          align
              dc.w 5,3
              dc.l 0
              dc.l texts1txt
              dc.l 0
       texts1txt:
              dc.b "S Point 2",0
          align
       The menu items in this example have the following properties as a 
       result of their flags:
     Menu 1;
       The first item,"Point 0.1",can be chosen using the right <Amiga>
       key and the "1" key.This point alternates between checked and not 
       checked,which can easily be used to check out the key function.If
       the item is checked and you hit both keys,the check disappears and
       vice versa.The box at this point is framed when the mouse pointer 
       clicks on it.
       The second item,"Point 0.2",can be chosen using the right <Amiga> 
       key and the "2"key.This item is checked the first time it is
       chosen.However,in contrast to the item above,it can't be erased.  
       The box of this item is inverted when clicked.
     Menu 2;
       These two points can't be chosen using keys.The box of the upper  
       item is inverted when clicked on:the lower one is framed.When you 
       click the second item,"Point 1.2",a submenu with two entries is
       displayed.
       Experiment with this structure a little bit.Change some values and
       see what happens.As you can see,menu programming isn't as bad as
       you thought,and it offers a lot of options (but you'll have to do
       lots of typing!).
       When you've done experimenting,you'll want to produce your own
       program with menus.How does the program find whether a menu item
       in a menu has been clicked on?
       You already looked at one way to find out the menus state.You can
       test the CHECKED bit in the flag word of a menu item.If this is
       set,the user clicked on this item with the mouse.
       This only works if checking is allowed for the item being tested. 
       You could allow all the menu items to be checked,but this still
       isn't a good solution--it requires testing all the flag bits of
       all the menus one after the other.That makes very boring
       programming.
       You've already learned about finding about events from Intuition. 
       You've moved the message about which event took place into D6,and 
       you can look at it to find out what happend.
       If you set the eight bit,the MENUPICK bit,of the IDCMP flag long
       word in the window definition,the choice of the menu point is
       reported.Put the following lines in your loop in the main program.
       loop:
              move.l  execbase,a6      ;exec base address in A6
              move.l  windowhd,a0      ;window structure pointer
              move.l  86(a0),a0        ;user point pointer in A0
              jsr     getmsg(a6)       ;get message
              tst,l   d0               ;whay happend?
              beq     loop             ;nothing happend
              move.l  d0,a0            ;message pointer in A0
              move.l  $14(a0),d6       ;event in D6
       If the program makes it out of the loop,an event as taken place.  
       You have the events flag in the D6 register.You can evaluate the  
       event using CMP or BTST to find out which flag bits are set.You
       can then execute the function corresponding to the set bit.You can
       use lines like the following ones:
              cmp     #$200,d6         ;WINDOWCLOSE?
              beq     ende             ;yes:program end
       These lines terminate the program when the window is closed.
       If the user chose a menu item,there is a $100 in the D6 register.
       You now need to determine which item it was.
       You can find this information in a word that comes right after the
       long word with the event flags in the message structure.Write:
              move    $18(a0),d7
       You now have the code for the clicked menu item in the D7
       register.If the user just pressed the right key and let it go
       without choosing a menu item,you'll find a $FFFF here.This word
       doesn't contain just one,but three pieces of information:
         Which menu was the item chosen from?
         Which menu item?
         Which submenu?
       The information is divided in three bit groups.The division is as 
       follows:
       Bits  0-4   Menu title number
       Bits  5-10  Menu item number
       Bits 11-15  Submenu item number
       The numbering begins with zero-ie the first menu point of the
       first menu has the numbers 0 and 0.
       
       To try this out insert the following lines:
              move    d7,d6            ;move code into D6
              lsr     #8,d7            ;shift right 11 times
              lsr     #3,d7            ;submenu item now in D7
              clr.l   d5
              roxr    #1,d6            ;bit 0 in X-flag
              roxl    #1,d5            ;menu number now in D5
              and.l   #$7f,d6          ;issolate lower bits
              cmp     #$7f,d6          ;no menu item?
              beq     loop             ;no:continue
              lsr     #4,d6            ;else menu item in D6
              ende
       By making a test run with AssemPro,you can easily see if this
       works right-just look at the registers after the program is over.

       If you,for example,want to write a program with four menus with 10
       menu items each,this sort of method is too much work-there are 44 
       tables.For this reason,lets look at a short program that takes
       care of the necessary structure table itself.
       The menu structure is built very simply-it doesn't offer submenus 
       or the option of choosing items via the keyboard.If you want these
       extras,you can still use this program,but you'll have to use MOVE 
       commands to insert the desired flags and pointers.
       The input that this program needs is a list of the menu names and 
       the items in each menu.The addresses of the menu texts go in a
       table with the following simple form:
             dc.l   Menu title 1
             dc.l   Point1,Point2,Point3,...,0
             dc.l   Menu title 2
             dc.l   Point1,Point2,Point3,...,0
             dc.l   Menu title 3 oder 0
       This program is set up in such a way that up to four menus can lie
       next to each other (in normal screen resolution),which is often
       plenty.The table above ends by putting a zero instead of a pointer
       to the nxt menu title.As you can see,its pretty simple.
       This program is inserted in your big program right behind the
       "setmenu"label.After the "bsr setmenu"command is executed,the menu
       structure is built and initialized at the same time.You don't need
       to change the rest of the program,it'll be shorter that way.
       Heres the program fragment for the complete "setmenu"routine:
       setmenu:                        ;*initialize menu structure
              lea     mentab,a0        ;pointer to text pointer in A0
              lea     menu,a1          ;pointer to menu field in A1
              move    #10,d1           ;horizontal menu position=10

       menuloop:
              clr.l   d2               ;vertical menu position=0
              move.l  a1,a2            ;save address of pointer
              tst.l   (a0)             ;another menu there?
              beq     setmenu1         ;no:quit
              clr.l   (a1)+            ;"no more menus"preperations
              move    d1,(a1)+         ;set X-position
              add.l   #70,d1           ;and increment
              move.l  #50,(a1)+        ;Y-position and width
              move.l  #$a0001,(a1)+    ;height and flag
              move.l  (a0)+,(a1)+      ;menu title
              lea     12(a1),a3
              move.l  a3,(a1)+         ;pointer to menu item
              clr.l   (a1)+            ;reserved words
              clr.l   (a1)+
       itemloop:
              tst.l   (a0)             ;last entry?
              beq     menuend          ;yes:menu done
              lea     54(a1),a3
              move.l  a3,(a1)+         ;pointer to next item
              move.l  d2,(a1)+         ;X- and Y-positions
              add     #10,d2           ;Y-position+10
              move.l  #$5a000a,(A1)+   ;WIDTH/HEIGHT
              move    #$52,(a1)+       ;flag:normal
              clr.l   (a1)+            ;no connection
              lea     16(a1),a3
              move.l  a3,(a1)+         ;text structure pointer
              clr.l   (a1)+            ;no fill structure
              clr.l   (a1)+            ;no command,no submenu
              clr.l   (a1)+            ;and no continuation
              move    #$1,(a1)+        ;set text structure:colour
              clr.l   (a1)+            ;mode 0
              move.l  #$50003,(a1)+    ;X- and Y-position
              clr.l   (a1)+            ;standard character set
              move.l  (a0)+,(a1)+      ;text pointer
              clr.l   (a1)+            ;no continuation
              bra     itemloop         ;next item...
       menuend:                        ;eventual transfer to next menu
              clr.l   -54(a1)          ;erase pointer to next item
              tst.l   (a0)+            ;increment table pointer
              tst.l   (a0)             ;another menu there?
              beq     setmenu1         ;no:done
              move.l  a1,(a2)          ;pointer to next menu
              bra     menuloop         ;and continue
       setmenu1:                       ;*initialize menu (like before)
              move.l  intbase,a6       ;intuition base address in A6
              move,l  windowhd,a0      ;window structure in A0
              lea     menu,a1          ;pointer to menu structure
              jsr     setmenustrip(a6)
              rts
       You need three things yet for this program:the memory to be used
       for the structure,the table of text pointers and the text.Heres an
       example:
       mentab:
              dc.l menu1               ;first menu title
              dc.l mp11,mp12,mp13      ;menu items
              dc.l 0                   ;end of menu 1
              dc.l menu2               ;second menu title
              dc.l mp21,mp22,mp23      ;menu items
              dc.l 0                   ;end of menu 2
              dc,l 0                   ;you're out of menus!
       ;** Menu Text **
       menu1: dc.b "Menu 1",0
       mp11:  dc.b "Point11",0
       mp12:  dc.b "Point12",0
       mp13:  dc.b "Point13",0
       menu2: dc.b "Menu 2",0
       mp21:  dc.b "Point21",0
       mp22:  dc.b "Point22",0
       mp23:  dc.b "Point23",0
           align
       ;** Storage space for menu structure **
       menu:  blk.w 500
       Make sure that the memory area reserved for the menu structure is 
       big enough and change the entry "blk.w 500"to the calculated
       value. 
       If you use this program,and want to build some special features
       into the menu (for instance key commands),you can make entries in
       the menu structure table while the program is running.You can find
       the word (or byte or long word) that interests you in the table as
       follows:
       For example,to find the keyboard command byte of the second entry
       in the first menu,calculate as follows:
       Address = Start_address+Menu*30+(entry-1)*54+26
       which in the example comes to:
       Address = menu+30+54+26
               = menu+110
       The 26 is the distance from the beginning of the MenuItem
       structure to the desired byte,the command byte.In this way,you can
       calculate the addresses and use MOVE commands to modify the menu
       to fit your wishes.By the way,in the example above,the correspond-
       ing flag bit must be set as well,so that the keyboard command is  
       recognized.
       Now lets get back to the window.Its nice to have a window that you
       can change and close,but you really want to be able to output text
       in a window!
     7.6.Text Output.
     ----------------
       Its very easy to use Intuition's text output function.Use the
       PrintIText function (offset -216).It needs four parameters.
       In A0    A pointer to the RastPort of the window.You can find this
                in the window structure.
       In A1    A pointer to the text structure of the text that should
                be output.
       In D0    The X-position.
       In D1    The Y-position of the text in the window.
       Its very easy to enter the X- and Y-positions.You've already used 
       the text structure twice (for requesters and menus).
       Whats new is accessing the windows RastPort.The RastPort is a
       structure that describes the window.The address is needed by
       several Intuition functions.
       The pointer to the RastPort starts at the 50th byte in the window 
       structure.You can access it as follows:

           move.l  windowhd,a0           ;address of window structure
           move.l  50(a0),a0             ;RastPort address in A0
       Now you've got the address of the RastPort.Lets write a routine
       that prints a text.The X- and Y-positions are in D0 and D1
       respectively and the address of the text structure in A1 before
       the routine is called:
       PrintIText = -216
              ...
       print:
              move.l  intbase,a6       ;intuition base address in A6
              move.l  windowhd,a0      ;address of window structure
              move.l  50(a0),a0        ;rastport address in A0
              jsr     printitext(a6)   ;call function
              rts
       You can try out this routine by using the requesters text that is 
       still in a structure of the program.Write the following lines
       before the "loop"label:
              lea     btext,a1         ;pointer to text structure in A1
              move.l  #10,d0           ;X-position
              move.l  #30,d1           ;Y-position of text
              bsr     print            ;output text
       Start the program and the text appears in the middle of the window
       If this doesn't happen,check the colour of the text in the text   
       structure.Its probably zero.Just change it to three,and the text  
       appears in red the next time you start the program.
     7.7.Images.
     -----------
       An image is a drawing that goes in a rectangular field and is
       defined bitwise.The disk symbol of the Intuition screen and the   
       system gadgets in the screen and window borders are examples of
       such Images.
       The rectangle that the drawing goes in can be arbitrarily large,  
       but each pixel in the rectangle needs its own bit,so programming  
       screen-sized Images isn't advisable.You'll stick to an Image that 
       requires about 32x16 bits-an Image thats about 3x1cm.
       You can make all sorts of images as you've seen looking at window 
       gadgets.There is an Intuition functionthat draws an Image:It is
       the DrawImage function (offset -114) and it needs 4 parameters:
       In A0   The address of the rastport image is drawn in.You've
               already learned how to access this address in the section 
               on the text function.
       In A1   The structure address of the image to be drawn.
       In D0   The relative X-position
       In D1   The relative Y-position of the drawing.
       Lets draw this picture in your window.It justs takes a simple
       routine.You just need to put the address of the image structure in
       A1 and the position of the image in D0 and D1 before you call it.
       DrawImage =-114
              ...
       draw:                           ;*draw image
              move.l  intbase,a6       ;intuition base address in A6
              move.l  windowhd,a0      ;pointer to window structure
              move.l  50(a0),a0        ;now,rastport address in A0
              jsr     drawimage(a6)    ;draw image
              rts
       Now you need the structure of the image.The structure contains
       nine entries which have the following meanings:
       The first two entries are words which specify the distance in the 
       X- and Y-direction from the co-ordinates that were given to tell  
       where the image should be drawn.You'll just put two zeros here:
       image:
              dc.w  0,0                ;X- and Y-position
       Next come two words which specify the width and height of the
       image in pixels.Lets draw a 32x13 point image.Enter: 
              dc.w  32,13              ;width and height of image
       The next word in the list specifies the number of planes in the
       drawing.If its a simple image that only uses two colours,just
       enter a one.For more colours,you'll need a correspondingly bigger 
       number.When more colurs are worked with,the bit pattern of the
       image must have more data.Lets just have one bit plane:
              dc.w  1                  ;one bitplane:2^1=2 colours
       Next comes a long word that points to the data of the image:
              dc.l  imgdata            ;pointer to image data
       The next two bytes are very interesting.The first byte,the
       PlanePick byte,tells which plane of the window or screen the image
       data should be written in.Since you only have one plane,you need
       to enter the bit plane of the window.This information is found in
       the bits of the byte-bit0 stands for plane 0,bit 1 for plane 1,etc
       ..You also define the colour of the image with this input.If you
       enter a two,every set bit of your image represents a red point.
              dc.b  2                  ;drawing red:plane 1
       The second byte,the PlaneOnOff byte,is an interesting enhancement.
       Each bit of the window bit plane corresponds to a whole number
       here.The only bytes that are interesting though are the ones that
       are cleared in the PlanePick byte.If the bit is set in PlaneOnOff,
       evert bit of the image in the corresponding plane is set.Otherwise
       they are cleared.To make sure that each bit of the image that
       isn't set appears white,enter a one.All the bits of the image that
       aren't set,are set in Plane 1 and appear white.
              dc.b  1                  ;background:white
       The last entry of the structure is a lobg word that points to
       another image.You don't need this,so set the long word to zero:
              dc.l  0                  ;no more images
       Heres a quick overview of the image structure:
      
       image:
              dc.w  0,0                ;X- and Y-positions
              dc.w  32,13              ;width and height of image
              dc.w  1                  ;one bitplane:2^1=2 colours
              dc.l  imgdata            ;pointer to image data
              dc.b  2                  ;drawing red:plane 1
              dc.b  1                  ;background:white
              dc.l  0                  ;no more images
       Now lets produce the image data.Each image row uses a word,long
       word,or several of these represent the pattern.The set points of
       the image correspond to the set bits.This is repeated as often as 
       the height of the image requires.The data on each line must begin 
       on a word border,on a even address.
       For the example,its easy to decide on the data,since you're going 
       32 points across-that corresponds to exacty one long word.Its
       easiest to program the image using the binary representation of
       the data.
       Lets use,as an example,an image that represents a switch in "OFF" 
       mode.This form is chosen for a good reason,so you should type it
       in.In the chapter on gadgets thats coming up,we'll show you how to
       turn the switch on.Here is the example data for the switch image:
       imgdata:   ;Data for switch in "OFF" mode
          dc.l    %00000000000000000000000000000000
          dc.l    %00000000000000000000111000000000
          dc.l    %00011101110111000001111100000000
          dc.l    %00010101000100000001111100000000
          dc.l    %00010101100110000001111000000000
          dc.l    %00011101000100000011100000000000
          dc.l    %00000000000000000111000000000000
          dc.l    %00000000000000001110000000000000
          dc.l    %00000000000111111111100000000000
          dc.l    %00000000001111111111110000000000
          dc.l    %00000000001111111111110000000000
          dc.l    %00000000000110000001100000000000
          dc.l    %00000000000000000000000000000000
       Once you've typed in this data,you can experiment with displaying
       it on the screen.Enter the following lines before the "loop"label:
           move.l  image,a1           ;pointer to image structure
           move    #30,d0             ;X-postion in window
           move    #50,d1             ;Y-position
           bsr     draw               ;draw image
       How do you like the image on the screen?You'll run into this
       switch again when we talk about putting the switch in the "ON"    
       state when discussing gadgets.You need to look at other methods of
       drawing in the window first,though.
     7.8.Borders.
     ------------
       A border is a collection of lines that are connected.They can be
       of any length or at any angle.Intuition lets you draw borders to
       do things like put frames around windows and screens.They are used
       to put borders around pictures or text,especially for use with
       string gadgets.We'll talk about that later,though.
       Its easy to draw borders.Just use the Intuition function
       DrawBorder (offset -108) which needs four parameters:
       In A0   The rastport address of the output medium the lines should
               be drawn in.Use your window.
       In A1   The address of the border structure.We'll look at the form
               of this structure shortly.
       In D0   The relative X-co-ordinate which is used with the X- and Y
               co-ordinate list to calulate the actual line co-ordinates.
       In D1   The relative Y-co-ordinates.Relative,here too,means that
               this is relative to the upper left corner of the screen.
       Lets write a short routine that is called with three parameters.  
       The structure address in A1 and the X and Y co-ordinates are in D0
       and D1 respectively when the routine is called.The border is drawn
       in the window whose structure address is in "windowhd".
       DrawBorder =-108
              ...
       borderdraw:                     ;* draw several lines
              move.l  inbase,a6        ;intuition base address in A6
              move.l  windowhd,a0      ;pointer to window structure
              move.l  50(a0),a0        ;now rastport address in A0
              jsr     drawborder(a6)   ;draw lines
              rts
       Now lets look at the border structure.The list needs the eight
       following parameters:
       First,you need two words for the vertical and horizontal distance 
       from the co-ordinates given in the function call.To avoid losing  
       sight of some of the many distance entries,put two zeros here:
       border:
              dc.w  0                  ;horizontal distance
              dc.w  0                  ;vertical distance
       Next come two bytes that determine the colour.Use a red frame:
              dc.b  3                  ;red frame
              dc.b  0                  ;background (unused)
       As you can see,the background colour isn't used.You have two modes
       to choose between for drawing the lines.The following mode
       determines the mode that is used.If it is zero,each line is drawn
       in the colour chosen,no matter what was done before.This is the
       JAM1 mode.The other mode is the XOR mode which ignores both colour
       entries.In this mode,all the points that lie under the line have
       their colour value inverted.As a result,a white point becomes
       black,and a blue one becomes red.That is mode two.Lets use the
       JAM1 mode for the example:
              dc.b  0                  ;mode:JAM1 (2=XOR)
       The next entry specifies how many co-ordinate pairs there are in
       the list.Since this word must be on an even address,you need to
       use the "align"peudo-op first.Then enter the number of pairs.     
       Remember that you need three points to draw two lines:beginning,  
       corner and end point.To draw a rectangular frame,you need five
       pairs:
              dc.b  5                  ;5 X,Y pairs used together
       The next item is a pointer to the co-ordinate table that contains
       a list of points to be connected:
              dc.l  coord              ;pointer to cordinate table
       The border structures final entry is a long word that can point to
       another border structure.If you don't have any more structures to
       be pointed to,just enter a zero here.The pointer is useful for
       connecting two independant border structures-for example,to
       produce a two coloured frame that really stands out.You don't need
       this pointer in the example,though:
              dc.l  0                  ;no more structures
       Thats the border structure.Now lets look at the co-ordinate list.
       For the example,it consists of five pairs of numbers which
       represent a rectangle.I recommend entering these values,because
       you'll use them in example programs further down the line.
       coord:                          ;coordinates for rectangle frame
              dc.w  -2,-2
              dc.w  80,-2
              dc.w  80,9
              dc.w  -2,9
              dc.w  -2,-2
       Heres a quick overview of the border structure:
       border:
              dc.w  0                  ;horizontal distance
              dc.w  0                  ;vertical distance
              dc.b  3                  ;red frame
              dc.b  0                  ;background (unused)
              dc.b  0                  ;mode:JAM1 (2=XOR)
              dc.b  5                  ;5 X,Y pairs used together
              dc.l  coord              ;pointer to cordinate table
              dc.l  0                  ;no more structures
       coord:                          ;coordinates for rectangle frame
              dc.w  -2,-2
              dc.w  80,-2
              dc.w  80,9
              dc.w  -2,9
              dc.w  -2,-2
       Once you've typed this in,you can try the whole thing out.Type the
       following lines before the "loop"label in the program:
              lea     border,a1        ;address of the border structure
              move    #20,d0           ;X base position
              move    #80,d1           ;Y base position
              bsr     drawborder       ;draw frame
       As you can see,using enough X and Y co-ordinates,you can draw the 
       Eiffel tower.Thats enough about simple drawings.You want to put
       some life into your drawings and text.Lets manipulate them with
       the mouse!
     7.9.Gadgets.
     ------------
       We already talked a bit about gadgets when you looked at screen
       construction.Looking at system gadgets like the window close
       symbol,you can activate by clicking and causes a program function 
       to be executed.
       You can make your own gadgets as well.Intuition allows you a lot
       of interesting possibilities.
       
       There are four types of gadgets:
       Boolean gadgets are used in Yes/No situations.You can click and
       activate it (Yes) or deactivate it (No).
       String gadgets are used to accept input of text of a specified
       length.

       Integer gadgets are a special sort of string gadgets which accept
       the input of a decimal number.Intuition converts the value into a 
       long word and sends it to the program.
       Proportional gadgets let you choose an analog value with the mouse
       You can move these around with the mouse.
     7.9.1.Boolean Gadgets.
     ----------------------
       Lets start with the simplest type,the boolean gadget.an example of
       this sort of gadget is the close symbol of the window.The only
       status it differenciates between are clicked and not clicked.Lets 
       develop a gadget of this type step by step.The flags and other    
       parameters are similar for the other gadgets.
       Each gadget needs a structure containing fifteen entries.There is
       a pointer to this structure in window,screen or requester that the
       gadget is to appear in.Theres always a long word available for
       this purpose.Up to this point,you've just put a zero there.If
       there is an address of a gadget structure there,the gadget or
       gadgets are displayed when the window is opened.
       A gadget structure as the following entries:
       The first long word is a pointer to the next gadget to be
       installed.The gadgets are displayed in a row,like pearls on a
       string.This pointer is the first gadget in this linked list of
       gadgets.If you just want one gadget in your window,put a zero
       here:
      
       gadget1:
              dc.l  0                  ;no more gadgets
       The next two words determine the position of the gadget in the
       window.There are several ways to determine the position.Use flags 
       to access the various possibilities.Lets start with a gadget that 
       stays in one spot:
              dc.w  40                 ;X and
              dc.w  50                 ;Y position of the gadget
       The next two words determine the size of the gadgets Hit box.This 
       box isn't the visible size of the gadget (that depends on the
       image data).It is the size of the rectangle that Intuition should 
       watch.If the mouse pointer is moved into this box and the left
       button pressed,the gadget is activated.Clicking on parts of the
       gadget that are outside this box have no effect!
              dc.w  32                 ;width and
              dc.w  13                 ;height of the hit box
       Next comes the word whose bits determine the properties of the
       gadget.Bits 0 and 1 determine what should happen when this objects
       hit box is clicked on.The meanings of the various values of these
       bits go as follows:
       Bit 0   1   Value   Name          Meaning
       ------------------------------------------------------------------
        0      0     0     GADGHCOMP     The gadget inverted
        0      1     1     GADGHBOX      The gadget framed
        1      0     2     GADGHIMAGE    Another image appears
        1      1     3     GADGHNONE     No reaction
       Bit 2 determines whether the gadget should consist of a drawing or
       a border.If it is set(Value+4),it is treated as an image;otherwise
       its treated like a border.
       The next bit determines if the gadget should appear in the upper
       or lower border of the frame.If it is set(Value+8).the position is
       relative to the lower border;otherwise it is relative to the upper
       border.The next bit as the same meaning for the horizontal
       position.If set(Value+$10),it is a relative positioning.Otherwise,
       it is an absolute positioning.
       Notice that when you define a gadget to be relative,you must have
       a negative value in the position input in the first word of the
       structure.Since the desired position isn't under,but its over this
       position!
       In this way,you can choose either absolute or relative positioning
       of the gadget.An example of a gadget that is positioned absolutely
       is the system gadget,close window.An example of a relative gadget 
       is the symbol for changing the size.
       The width and height of the gadgets hit box can also be relative
       to the window size.Specify this by using bit 5 for width (Value +
       $20)and bit 6 for the height (Value +$40).A set bit mens a
       relative size.
       Bit 7 (Value+$80)makes the object active as soon as the window is
       opened.
       Bit 8 (Value+$100)determines whether the gadget can be used or not
       If this bit is set,the gadget can't be activated.
       For the example,you'll use absolute positioning and size,the
       inverted appearance for the activated gadget,and the
       representation of the object as an image.That means you must use
       the value four:
             dc.w  4              ;flags:image,invert
       Next comes a word whose bits are used as flags.This flag is called
       the Activation Flag.It determines the functions of the gadget.The 
       bits,their values and meanings follow:
       Bit   Value   Name            Meaning
       ------------------------------------------------------------------
        0     1      RELVERIFY       Causes the gadget to be activated
                                     only when the left mouse key is let
                                     loose over the gadget.
        1     2      GADGIMMEDIATE   Lets the gadget be active as soon as
                                     there is a click.
        2     4      ENDGADGET       Lets you choose to end this choice
                                     and have it disappear if this is a  
                                     requester gadget.
        3     8      FOLLOWMOUSE     Lets the gadget know the mouse
                                     position at regular intervals from
                                     the time it is selected until the
                                     time it is deselected.You can use
                                     this to move the gadget with the
                                     mouse when you want to change the
                                     gadget position.
        4     $10    RIGHTBORDER     This makes sure thay when borders
                                     are used that the page is adjusted
                                     to the size of the gadget so that it
                                     fits in the border.
        5     $20    LEFTBORDER
        6     $40    TOPBORDER
        7     $80    BOTTOMBORDER
        8     $100   TOGGLESELECT    Allows the objects state to change  
                                     every time it is clicked.If
                                     activated,it becomes deactivated and
                                     vice versa.
        9     $200   STRINGCENTRE    For a string gadget,these two bits  
                                     determine whether the string should 
                                     appear centred or right justified.If
                                     neither is set,the string is output 
                                     left justified.
        10    $400   STRINGRIGHT
        11    $800   LONGINT         Turns a string gadget into a Integer
                                     gadget (explanation later).
        12    $1000  ALTKEYMAP       Causes another ketboard placement to
                                     be in effect for string gadget input
       Thats it for the activation flags.Lets choose the TOGGLESELECT and
       GADGETIMMEDIATED flags for example:
            dc.w  $102             ;activation
       The next word of the gadget structure determines the gadget type. 
       Heres the meaning of the individual bits:
       Bit   Value   Name            Meaning(report what circumstances)
       ----------------------------------------------------------------
        0     1      BOOLGADGET      This is a boolean gadget
        1     2      GADGET002       
        2     4      STRGADGET       String order Integer gadget
       0+1    3      PROPGADGET      Proportional gadget
       System gadgets:
        4     $10    SIZING          Size changing gadget
        5     $20    WDRAGGING       Moving gadget for window
       4+5    $30    SDRAGGING       Same for screen
        6     $40    WUPFRONT        Gadget to move window forward
       6+4    $50    SUPFRONT        Gadget to move screen forward
       6+5    $60    WDOWNBACK       Move window back
       6+5+4  $70    SDOWNBACK       Move screen back
        7     $80    CLOSE           Window close gadget
       Type definitions:
        12    $1000  REQGADGET       Requester gadget
        13    $2000  GZZGADGET       Border gadget in GIMMEZEROZERO
                                     window
        14    $4000  SCRGADGET       Screen gadget when set
        15    $8000  SYSGADGET       System gadget when set
       You want to use a simple boolean gadget for your example,so enter:
              dc.w  1                ;gadget type:boolean
       Next comes a pointer to the gadget structure.The first pointer
       contains the address of the image or border structure which should
       be used to represent the gadget.If no representation is needed,put
       a zero here.You want to represent the gadget as an image,so put a 
       pointer to the image structure that you produced in the chapter
       about images:
              dc.l  image            ;gadget image
       The next pointer is only used if the GADGHIMAGE flag in the flag
       word of the structure is set.This is a pointer to another
       structure that should be put on the screen when the object is
       activated.If a border structure is used for the gadget represent- 
       ation,this must be a border structure as well.You won't use a
       second image,so put a zero here:
              dc.l  0                ;no new gadget displayed
       The next pointer is to the text structure that should be output by
       the gadget.If no text is needed,just put a zero here.You want to
       use some text,however:
              dc.l  ggtext           ;gadget text
       Now comes a long word that determines which gadgets are
       deactivated when this is activated.This function still doesn't
       work right so put a zero here:
              dc.l  0                ;no exclude
       You'll set the next pointer to zero as well,because it is only
       used for String and Proportional gadgets.For these gadgets,this is
       a special structure to describe the characteristics of the gadget.
       Its called SpecialInfo.
              dc.l  0                ;no SpecialInfo

       The next word contains the Gadget Identification (ID) number:
              dc.w  1                ;gadget ID
       Finally there is a long word that doesn't have any function,so put
       a zero here:
              dc.l  0                ;user data (ignore)
       Thats it.Heres a quick overview of the gadget structure:
       gadget1:
              dc.l  0                ;no more gadgets
              dc.w  40               ;X and
              dc.w  50               ;Y position of gadget
              dc.w  32               ;width and
              dc.w  13               ;height of hit box
              dc.w  4                ;flags:image,invert
              dc.w  $102             ;activation flags
              dc.w  1                ;gadget type:boolean
              dc.l  image            ;gadget image
              dc.l  0                ;no new gadget displayed
              dc.l  ggtext           ;gadget text
              dc.l  0                ;no exclude
              dc.l  0                ;no SpecialInfo
              dc.w  1                ;gadget ID
              dc.l  0                ;user data (ignore)
       You've already prepared a structure that you can use for this
       image.Now you need the text that appears under the gadget.
       Since the gadget looks like a switch,label it "switch".The text
       structure looks like this:
       ggtext:
              dc.b  1,0              ;colours
              dc.b  1                ;mode
          align
              dc.w  -8,14            ;X and Y position
              dc.l  0                ;standard font
              dc.l  swtext           ;pointer to text
              dc.l  0                ;no more text
       swtext:
              dc.b  "switch",0
          align
       Once you've typed this in,save it,assemble it and start again.You 
       can click the switch and cause it to be inverted.Click it again,  
       and it appears normal.
       Now you can experriment with the structure.If you change the flag 
       from four to five,you can cause the gadget to be framed when it is
       activated.Set the RELVERIFY bit(bit0:+1)in the Activation Flag
       word.Then you can move the mouse pointer onto the object and press
       the button.It is activated.Keep the mouse button pressed down and 
       move the mouse.Once you leave the hit box,the activation disapears
       This way,you can avoid accidently activating a gadget.
       Now you want to display the switch in an on state.This is easy.All
       you need to do is produce another image structure,one for the on  
       state.You put this pointer in the long word right after the
       pointer to the normal image structure.You can change the flag word
       to six which causes a second image to be displayed when the gadget
       is activated.
       Here is the image structure for the switch in the one state.
       image2:
              dc.w  0,0              ;no offset
              dc.w  32,13            ;32x13 pixels
              dc.w  1                ;mode 1
              dc.l  imgdata2         ;pointer to the data
              dc.b  2,1              ;same colours as before
              dc.l  0                ;nothing else
      
       imgdata2:                     ;data for switch in the On state
              dc.l  %00000000000000000000000000000000
              dc.l  %00000000011100000000000000000000
              dc.l  %00000000111110000011101001000000
              dc.l  %00000000111110000010101101000000
              dc.l  %00000000011110000010101011000000
              dc.l  %00000000000111000011101001000000
              dc.l  %00000000000011100000000000000000
              dc.l  %00000000000001110000000000000000
              dc.l  %00000000000111111111100000000000
              dc.l  %00000000001111111111110000000000
              dc.l  %00000000001111111111110000000000
              dc.l  %00000000000110000001100000000000
              dc.l  %00000000000000000000000000000000
       Now the state of the object can be determined by looking at the
       picture.If the gadget is activated,the switch is on.If not,the
       switch is off.
       Thats it for boolean gadgets.You can learn about the things you
       did'nt touch with some experimentation.You want to get to the
       string gadgets that also do some interesting things.
     7.9.2.String Gadgets.
     ---------------------
       Lets pretend you want a program to load data from the disk.To get 
       the user to enter the filename,you need to output text telling the
       user to enter the name.Then you need to call an input routine to
       evaluate the keyboard input.
       Its easier and more elegant to use a String gadget.This function  
       allows for easy input and/or editingof short text.You have the
       option of having the text framed.The Undo function can be used by 
       pressing the right <Amiga> key and a "Q",and the old contents of
       the gadget,the old text are restored.
       You can also vary the size of the text and the input field.If the 
       text is longer than the input field is wide,the text is moved back
       and forth through the visible area when you move the cursor keys
       or the normal input to the border.
       You can also restrict input to just digits.This makes it posible
       to accept numeric input.Intuition even converts the digit string  
       into a binary number.This saves the machine language programmer
       some work.A specialized String gadget of this sort is called a    
       Integer gadget.
       The structure is similar to the Boolean gadgets structure.There
       are only two major differences:
       The type word of the structure must be a four to declare that this
       is a String gadget (STRGADGET).
 
       The pointer to the SpecialInfo structure is needed.Put a pointer
       to the StringInfo structure that you are going to design later
       here.
       The width and height entries in the gadget structure have a
       different meaning than they had previously.They do declare the
       area in which you can bring the mouse pointer to activate the
       String gadget.However,it is also used for representation of text. 
       These values determine the size of the box in which the text is
       output.You should surround the box with a border using the Border 
       function,so that the user can see where it is.
       If the text is longer than the box,only a portion of it is seen on
       the screen.You can move through the area by entering text or using
       the left/right cursor keys to move through the box.The characters 
       that are entered are inserted at the cursor position,so the rest
       of the text is shifted by one character when you are on the right 
       edge of the input area.The following functions can be used for
       editing this text:
       Cursor key left/right
             Moves the cursor over the text thats already on hand.Moves
             the text through the Container.
       Cursor keys with <Shift>
             Puts the cursor on the beginning or the end of the text.
        Deletes the character under the cursor.
       <Backspace>
             Deletes the character to the left of the cursor.
       <Return>
             Ends text input.
       <Amiga>right+"Q"
             This is the Undo function.It replaces the text with the
             original contents.
       The StringInfo structure only has a few entries:
       First theres a pointer to the memory area that is used to store
       the text that is input.The memory buffer must be big enough to
       handle all the text entered.
       strinfo:
              dc.l  strpuffer        ;pointer to text buffer
       Next comes the pointer to the Undo buffer.This pointer and this
       buffer are only needed if you want the Undo function.If you do,you
       must have a buffer that is at least as big as your text buffer.   
       Every time the string gadget function is called,the text buffers  
       contents are copied into this buffer.To get the old contents back,
       just press the right <Amiga>key and the "Q"key.The contents of the
       Undo buffer are copied back to the text buffer.If you use several 
       string gadgets in a program,you can use the same Undo buffer for
       all of them,since only one string gadget is used at one time.
              dc.l  undo             ;pointer to undo buffer
       The following word contains the cursor position in the text.You   
       should set this word to zero,so that the user can see the
       beginning of the text when the string gadget appears.
              dc.w  0                ;cursor position
       The next word contains the maximum number of characters that can
       be input.If you type one more than this number of characters,the  
       screen blinks,to show that you can't enter a longer input string. 
       The number of characters and the reserved space for the input
       field don't have to agree,since text can be scrolled by typing.
              dc.w  10               ;maximum # of characters
       The following word tells at which character of text in the buffer,
       the output to the box should begin.You should put a zero here,so
       that the user can see the beginning of the text.
              dc.w  0                ;output text from this character
       The next five words are used by Intuition,so you don't have to    
       initialize them.Just put zeros here.The words contain the
       following information:
              dc.w  0                ;character position in undo buffer
              dc.w  0                ;number of chars in text buffer
              dc.w  0                ;number of chars visible in box
              dc.w  0                ;horizontal box offset
              dc.w  0                ;vertical box offset
       The next two long words are initialized by Intuition as well:
              dc.l  0                ;pointer to rastport
              dc.l  0                ;long word with value of the input
       ;                             ;(for integer gadgets)
       The final entry is a pointer to the keyboard table that is used if
       the ALTKEYMAP flag of the gadget is set.
              dc.l  0                ;standard keyboard table
       Heres a quick overview of the StringInfo structure:
       strinfo:
              dc.l  strpuffer        ;pointer to text buffer
              dc.l  undo             ;pointer to undo buffer
              dc.w  0                ;cursor position
              dc.w  10               ;maximum # of characters
              dc.w  0                ;output text from this character
              dc.w  0                ;character position in undo buffer
              dc.w  0                ;number of chars in text buffer
              dc.w  0                ;number of chars visible in box
              dc.w  0                ;horizontal box offset
              dc.w  0                ;vertical box offset
              dc.l  0                ;pointer to rastport
              dc.l  0                ;long word with value of input
       ;                             ;(for integer gadgets)
              dc.l  0                ;standard keyboard table
       Here are the text and undo buffers:
       strpuffer:
              dc.b  "Hello!",0,0,0
       undo:
              dc.l  0,0,0,0
          align
       Once you've entered these lines,you can either alter the old
       gadget structure or build a new one.We'd recommend building
       another gadget structure so that you can have the switch and use
       it later.Change the first pointer in the old structure from zero
       to "gadget1"and insert this new structure.Here is an example
       strucure for the string gadget.It as the following entries:
       gadget1:                      ;*structure for string gadget
              dc.l  0                ;no more gadgets
              dc.w  20,80            ;position
              dc.w  80,10            ;width and height of box
              dc.w  0                ;flags:normal
              dc.w  2                ;activation($802 for long int)
              dc.w  4                ;type:string gadget
              dc.l  border           ;pointer to border
              dc.l  0                ;no drawing selected
              dc.l  0                ;no text
              dc.l  0                ;no exclude
              dc.l  strinfo          ;pointer to stringinfo structure
              dc.w  2                ;gadget ID
              dc.l  0                ;no user data
       border:                       ;*border for box frame
              dc.w  0,0              ;no offset
              dc.b  3,3              ;red colour
              dc.b  0                ;mode:JAM1
              dc.b  5                ;5 X,Y pairs
              dc.l  coord            ;pointer to coordinates table
              dc.l  0                ;no more structures
       coord:                        ;*coordinates for frame
              dc.w  -2,-2            ;start in upper left corner
              dc.w  80,-2            ;upper right
              dc.w  80,9             ;lower right
              dc.w  -2,9             ;lower left
              dc.w  -2,-2            ;back to beginning
       This data causes a red rectangle,the border,to appear around the  
       "Hello!"text.You can change the text by clicking in the field and 
       editing once the cursor appears.If you type something wrong,you
       can use the undo function(the right <Amiga> key and the Q key),to 
       get "Hello!"back.
       Once you've done some typing and deactivated the gadget by
       pressing <Return> or by clicking outside the field (cursors
       disapear),you can terminate the program.
       Change the activation flag to $802 and the "strbuffer"to "dc.l
       0,0,0,0",assemble,and then start the program.You can type in the
       string gadget once it has been activated,but you can only enter
       digits.The screen blinks if you enter letters.
       Enter a number,and then end the program after deactivating the
       gadget.If you look at the stringinfo structure you can look at the
       value of the number you input(in hex)in the eight long word.
       After looking at boolean,text and numeric input to gadgets,lets
       look at Proportional gadgets which allow the user to enter analog 
       values by moving a symbol.
     7.9.3.Proportional Gadgets.
     ---------------------------
       You've seen the advantages of slider devices over knobs that you
       turn,maybe on a hifi,maybe on a toaster,but certainly someplace.
       Its easier to tell the state the item is in with a slider,
       especially if several such devices are next to each other(for
       example graphic equalizers).You can represent sliders on the
       Amigas screen and work with them with the mouse.This offers a nice
       way to represent information graphically in your programs.
       You can do this with gadgets.Using Proportional gadgets,you can
       put a symbol in a frame and move horzontally and/or vertically.The
       size of the frame and the slider can be variable size,so that the
       frame size is relative to the screen size so when the window
       changes size,it will also.The slider can be set up so that its
       size in the grows or shrinks.
       These are best seen via example and experimentation.(The
       posibilities mentioned do not form a complete list by any stretch 
       of the imagination.)You want to set up a simple Proportional
       gadget that can be moved horizontally.
       You need a gadget structure that as the same form as others.To
       show the differences,heres a complete example structure for your  
       gadget.You can connect this gadget to the other one,by changing
       the first long word in the last structure to "dc.l gadget2".
       gadget2:                      ;*structure for Proportional gadget
              dc.l  0                ;no more gadgets
              dc.w  150,30           ;position
              dc.w  100,10           ;width and height of frame
              dc.w  4                ;flags:GADGIMAGE
              dc.w  2                ;activation:GADGIMMEDIATE
              dc.w  3                ;type:proportional gadget
              dc.l  mover            ;pointer to slider data
              dc.l  0                ;no select structure
              dc.l  0                ;no text
              dc.l  0                ;no exclude
              dc.l  propinfo         ;pointer to propinfo structure
              dc.w  3                ;gadget ID
              dc.l  0                ;no user data
       You see two special features.Use an image structure for the mover 
       and put a pointer to another structure in the spot for the Special
       Info pointer.
       First,lets look at the "mover"structure,the sliders image
       structure.Heres an example of this structure:
       mover:                        ;*structure for slider image
              dc.w  0,0              ;no offset
              dc.w  16,7             ;16x7 pixels big
              dc.w  1                ;one bit plane
              dc.l  moverdata        ;pointer to image data
              dc.b  1,0              ;colour:white
              dc.l  0                ;don't continue
       moverdata:                    ;*image data for mover
              dc.w %0111111111111110
              dc.w %0101111111111010
              dc.w %0101011111101010
              dc.w %0101010110101010
              dc.w %0101011111101010
              dc.w %0101111111111010
              dc.w %0111111111111110
       Up till now,there was'nt anything new.Now lets look at the
       PropInfo structure that describes the properties of the
       Proportional gadget.
       The structure starts with a flag word that contains the following 
       bits:
       Bits   Value   Name              Meaning
       -----------------------------------------------------------------
        0       1     AUTOKNOB          Mover is set up automatically
        1       2     FREEHORIZ         Allows horizontal movement
        2       4     FREEVERT          Allows vertical movement
        3       8     PROPBORDERLESS    Turns off automatic framing
        8      $100   KNOBHIT           Set when the mover is touched
       You can set the first four bits to get the representation that you
       want.Bit 8 is set by Intuition when the mover is clicked with the
       mouse pointer.
       Bit 0,AUTOKNOB,allos for the simplest sort of Proportional gadget.
       If this bit is set,no move data are used for the mover image.
       Instead,a white mover is generated that is adjusted to the size of
       the box and the values to be represented.When you use this slider
       to represent the displayed lines in a long text of a program,the
       displayed lines are a percentage of the total text.The
       relationship between the total number of lines and the lines shown
       is represented by an AUTOKNOB as the relationship between the
       frame and the slider.The bigger the percentage,the bigger the
       slider is.You don't want to work with this though,even though it
       is simple and interesting,because a simple white button isn't
       particularly attractive.If you experiment with it,make sure that
       the pointer to the image data points to a four word long buffer
       that Intuition can use to store values.The buffer is of the
       following form:
       buffer:
              dc.w  0                ;X position of the slider in the box
              dc.w  0                ;Y position in the box
              dc.w  0                ;width of slider
              dc.w  0                ;height of slider
       Leys look at the PropInfo structure.Since you're not using
       AUTOKNOB and wish to allow horizontal movement only,put two in as
       a flag:
       propinfo:
              dc.w  2                ;flags:FREEHORIZ
       In the next two words of the structure,the horizontal (HorizPot)
       and vertical (VertPot) position of sliders are stored.A value of  
       zero means left or upper,while the value $FFFF means right or
       lower.The value that results from movement is in this range.You
       set these values to zero at the start of the program.After moving 
       the mouse,there is different values here.
              dc.w  0,0              ;X and Y position of the slider

       Next come two words which determine the size of the AUTOKNOB or
       the step size of the slider(this determines how far the slider
       moves when you click in the box next to the slider).These words
       are called HorizBody (horizontal movement) and VertBody (vertical 
       movement).
              dc.w  $ffff/16         ;horizontal step size:1/16
              dc.w  0                ;no vertical movement
       ;The next six words are initialized by Intuition.
              dc.w  0                ;box width
              dc.w  0                ;box height
              dc.w  0                ;absolute step size horizontal
              dc.w  0                ;and vertical
              dc.w  0                ;left border of box 
              dc.w  0                ;upper border of box
       Thats it.Heres a quick overview of the PropInfo structure:
        
       prpoinfo:
              dc.w  2                ;flags:FREEHORIZ
              dc.w  0,0              ;X and Y position of slider
              dc.w  $ffff/16         ;horizontal step size:1/16
              dc.w  0                ;no vertical movement
              dc.w  0                ;box width
              dc.w  0                ;box height
              dc.w  0                ;absolute step size horizontal
              dc.w  0                ;and vertical
              dc.w  0                ;left border of box
              dc.w  0                ;upper border of box
       Once you've typed this in,you can start the program and try it
       out.
       You can also try vertical movement by setting the flag word equal
       to six,the vertical step size to $FFFF/10,and the height of the
       gadget to 80,for the example.To try out the AUTOKNOBs,change the  
       flag value to seven.
     7.10.Example Program.
     ---------------------
       Here is a complete example program using what you have learned in
       this chapter:
       ;7_Intuition.asm
       ;** Demo-Program for working with Intuition **
       movescreen    =-162
       openscreen    =-198
       closescreen   =-66
       openwindow    =-204
       closewindow   =-72
       autorequest   =-348
       setmenustrip  =-264
       clearmenustrip=-54
       printitext    =-216
       drawimage     =-144
       drawborder    =-108
       displaybeep   =-96
       closelibrary  =-414
       openlib       =-408
       execbase      = 4
       getmsg        =-372
       joy2          =$dff0c
       fire          =$bfe001
       ;!!!when > 500kb !!!
       ;org $40000
       ;load $40000
       ; or use AssemPro to place in CHIP RAM
       ;!!!!!!!!!!!!!!!!!!!!!!!
       run:   
              bsr     openint
              bsr     scropen
              bsr     windopen
              bsr     setmenu
              bsr     print
              lea     border,a1
              move    #22,d0
              move    #30,d1
              bsr     borderdraw
             
              bsr     draw
              
              bsr     request
       loop:
              move.l  execbase,a6
              move.l  windowhd,a0
              move.l  86(a0),a0        ;user port
              jsr     getmsg(a6)
              tst.l   d0
              beq     loop             ;no event
              move.l  d0,a0
              move.l  $16(a0),msg      ;event:LO=item,HI=Event
              move.l  msg,d6           ;to test
              move.l  d6,d7
              lsr     #8,d7
              lsr     #3,d7            ;sub menu point in D7
              clr.l   d5
              roxr    #1,d6
              roxl    #1,d5            ;menu number in D5
              and.l   #$7f,d6
              cmp     #$7f,d6          ;no menu point?
              beq     loop             ;no:continue
              lsr     #4,d6            ;menu point in D6
              cmp     #1,d6            ;point 2?
              bne     no1
              move,l  intbase,a6
              move.l  screenhd,a0
              jsr     displaybeep(a6)
       no1:
              cmp     #0,d6
              bne     loop
       ende:
              bsr     clearmenu
              bsr     windclose
              bsr     scrclose
              bsr     closeint
              rts
       openint:
              move.l  execbase,a6
              lea     intname,a1
              jsr     openlib(a6)
              move.l  d0,intbase
              rts
       closeint:
              move.l  execbase,a6
              move.l  intbase,a1
              jsr     closelibrary(a6)
              rts
       scropen:
              move.l  inbase,a6
              lea     screen_defs,a0
              jsr     openscreen(a6)
              move.l  d0,screenhd
       scrclose:
              move.l  inbase,a6
              move.l  screenhd,a0
              jsr     closescreen(a6)
              rts
       scrmove:
              move.l  intbase,a6
              move,l  screenhd,a0
              jsr     movescreen(a6)
              rts
       windopen:
              move.l  intbase,a6
              lea     windowdef,a0
              jsr     openwindow(a6)
              move.l  d0,windowhd
              rts
       windclose:
              move.l  intbase,a6
              move.l  windowhd,a0
              jsr     closewindow(a6)
              rts
       request:
              move.l  windowhd,a0
              lea     btext,a1
              lea     ltext,a2
              lea     rtext,a3
              move.l  #0,d0
              move.l  #0,d1
              move.l  #180,d2
              move.l  #80,d3
              move.l  intbase,a6
              jsr     autorequest(a6)
              rts
       setmenu:
              lea     mentab,a0        ;pointer to text pointer in A0
              lea     menu,a1          ;pointer to menu field in A1
              move    #10,d1           ;menu position = 10
       menuloop:
              clr.l   d2               ;menu point-Y=0
              move.l  a1,a2            ;save pointer
              tst.l   (a0)
              beq     setmenu1         ;end
              clr.l   (a1)+
              move    d1,(a1)+
              add.l   #70,d1
              move.l  #50,(a1)+
              move.l  #$a0001,(a1)+
              move.l  (a0)+,(a1)+      ;menu title
              lea     12(a1),a3
              move.l  a3,(a1)+         ;menu point
              clr.l   (a1)+
              clr.l   (a1)+
       itemloop:
              tst.l   (a0)             ;last one?
              beq     menuend          ;yes
              lea     54(a1),a3
              move.l  a3,(a1)+         ;pointer to next point
              move.l  d2,(a1)+         ;X/Y
              add     #10,d2
              move.l  #$5a000a,(a1)+   ;width/height
              move    #$52,(a1)+
              clr.l   (a1)+
              lea     16(a1),a3
              move.l  a3,(a1)+         ;text structor-pointer
              clr.l   (a1)+
              clr.l   (a1)+
              clr.l   (a1)+
              move    #$1,(a1)+        ;text-structor set
              clr     (a1)+
              move.l  #$50003,(a1)+
              clr.l   (a1)+
              move.l  (a0)+,(a1)+      ;text pointer
              clr.l   (a1)+
              bra     itemloop         ;next point...
       menuend:
              clr.l   -54(a1)
              tst.l   (a0)+
              tst.l   (a0)             ;still in menu?
              beq     setmenu1         ;no:ready
              move.l  a1,(a2)          ;pointer to next menu
              bra     menuloop         ;and continue
       setmenu1:
              move.l  intbase,a6
              move.l  windowhd,a0
              lea     menu,a1
              jsr     setmenustrip(a6)
              rts
       clearmenu:
              move.l  intbase,a6
              move.l  windowhd,a0
              jsr     clearmenustrip(a6)
              rts
       print:
              move.l  intbase,a6
              move.l  windowhd,a0
              move.l  50(a0),a0
              lea     ggtext,a1
              move.l  #30,d0           ;X
              move.l  #16,d1           ;Y
              jsr     printitext(a6)
              rts
       draw:
              move.l  intbase,a6
              move.l  windowhd,a0
              move.l  50(a0),a0
              lea     image,a1
              move.l  #200,d0
              move.l  #100,d1
              jsr     drawimage(a6)
              rts
       borderdraw:
              move.l  intbase,a6
              move.l  windowhd,a0
              move.l  50(a0),a0
              jsr     drawborder(a6)
              rts
       screen_defs:
              dc.w  0,0
              dc.w  640,200
              dc.w  4
              dc.b  0
              dc.b  1
              dc.w  $800
              dc.w  15
              dc.l  0
              dc.l  tite1
              dc.l  0
              dc.l  0
       windowdef:
              dc.w  10,20
              dc.w  300,150
              dc.b  0,1
              dc.l  $300
              dc.l  $100f
              dc.l  gadget
              dc.l  0
              dc.l  windname
       screenhd:
              dc.l  0
              dc.l  0 
              dc.w  200,40,600,200
              dc.w  $f
       btext:
              dc.b  3,3
              dc.b  0
              align
              dc.w  10,10
              dc.l  0
              dc.l  bodytxt
              dc.l  0
     
       bodytxt:dc.b  "Requester-Text",0
              align
       ltext:
              dc.b  3,1
              dc.b  0
              align  dc.w 5,3
              dc.l  0
              dc.l  lefttext
              dc.l  0
       lefttext: dc.b "left",0
              align
       rtext:
              dc.b  0,1
              dc.b  0
              align  dc.w 5,3
              dc.l  0
              dc.l  righttext
              dc.l  0
       righttext: dc.b "right",0
              align
       tite1: dc.b  "User Screen",0
       windname: dc.b "Window-Title",0
              align  windowhd: dc.l 0
       intbase:dc.l  0
       intname:dc.b  "intuition.library",0
              align  msg:dc.l 0
       mentab:
              dc.l  menu1
              dc.l  mp11,np12,mp13,mp14,mp15,mp16,mp17,mp18,mp19,0
              dc.l  menu2
              dc.l  mp21,mp22,mp23,0
              dc.l  menu3
              dc.l  mp31,mp32,0
              dc.l  menu4,mp41,0
              dc.l  0
       menu1: dc.b  "Menu 1",0
       mp11:  dc.b  "Point 11",0
       mp12:  dc.b  "Point 12",0
       mp13:  dc.b  "Point 13",0
       mp14:  dc.b  "Point 14",0
       mp15:  dc.b  "Point 15",0
       mp16:  dc.b  "Point 16",0
       mp17:  dc.b  "Point 17",0
       mp18:  dc.b  "Point 18",0
       mp19:  dc.b  "Point 19",0
       menu2: dc.b  "Menu 2",0
       mp21:  dc.b  "End!",0
       mp22:  dc.b  "Beep",0
       mp23:  dc.b  "Point 23",0
 
       menu3: dc.b  "Menu 3",0
       mp31:  dc.b  "Point 31",0
       mp32:  dc.b  "Point 32",0
       menu4: dc.b  "Menu 4",0
       mp41:  dc.b  "Point 41",0
              align
       gadget:
              dc.l  gadget1
              dc.w  20,80,80,10
              dc.w  0
              dc.w  $2               ;activation,$802 for longint
              dc.w  4
              dc.l  border
              dc.l  0
              dc.l  0
              dc.l  0
              dc.l  strinfo
              dc.w  2
              dc.l  0
       border:
              dc.w  0,0
              dc.b  1,0,0
              dc.d  5               ;XY-pair
              dc.l  koord
              dc.l  0
       koord:
              dc.w  -2,-2,80,-2,80,9,-2,9,-2,-2
       strinfo:
              dc.l  strpuffer
              dc.l  undo
              dc.w  0               ;cursor position
              dc.w  10              ;max.char
              dc.w  0  
              dc.w  0,0,0,0,0
              dc.l  0,0,0
       strpuffer:
              dc.b  "Hello!",0,0,0
       
       undo:  dc.l  0,0,0
              align
       gadget1:
              dc.l  gadget2           ;more gadget
              dc.w  40,50,32,13
              dc.w  $6                ;flags:invert
              dc.w  $103              ;activate
              dc.w  1                 ;gadget type
              dc.l  image             ;gadget image
              dc.l  image2            ;select gadget
              dc.l  ggtext            ;gadget text
              dc.l  0                 ;no exclude
              dc.l  0                 ;special info
              dc.w  1                 ;ID
              dc.l  0                 ;user data
       ggtext:
              dc.b  1,0,1
              align
              dc.w  -8,14
              dc.l  0
              dc.l  swtext
              dc,l  0
      
       swtext:
              dc.b  "Switch",0
              align
       image:
              dc.w  0,0
              dc.w  32,13
              dc.w  1
              dc.l  imgdata
              dc.b  2,1
              dc.l  0
       image2:
              dc.w  0,0
              dc.w  32,13
              dc.w  1
              dc.l  imgdata2
              dc.b  2,1
              dc.l  0
       imgdata:
              dc.l 0
              dc.l %00000000011100000000000000000000
              dc.l %00000000111110000011101001000000
              dc.l %00000000111110000010101101000000
              dc.l %00000000011110000010101011000000
              dc.l %00000000000111000011101001000000
              dc.l %00000000000011100000000000000000
              dc.l %00000000000001110000000000000000
              dc.l %00000000000111111111100000000000
              dc.l %00000000001111111111110000000000
              dc.l %00000000001111111111110000000000
              dc.l %00000000000110000001100000000000
              dc.l 0
       imgdata2:
              dc.l 0
              dc.l %00000000000000000000111000000000
              dc.l %00011101110111000001111100000000
              dc.l %00010101000100000001111100000000
              dc.l %00010101100110000001111000000000
              dc.l %00011101000100000011100000000000
              dc.l %00000000000000000111000000000000
              dc.l %00000000000000001110000000000000
              dc.l %00000000000111111111100000000000
              dc.l %00000000001111111111110000000000
              dc.l %00000000001111111111110000000000
              dc.l %00000000000110000001100000000000
              dc.l 0
       gadget2:
              dc.l  0
              dc.w  150,30,100,50
              dc.w  5
              dc.w  2
              dc.w  3                   ;prop.gadet
              dc.l  mover               ;border
              dc.l  0,0,0
              dc.l  specinfo
              dc.w  3
              dc.l  0
       specinfo:
              dc.w  6                   ;flags:free horiz
              dc.w  0,0
              dc.w  $ffff/10,$ffff/5
              dc.w  0,0,0,0,0,0
       mover:
              dc.w  0,0,16,7
              dc.w  1
              dc.l  moverdata
              dc.b  1,0
              dc.l  0
       moverdata:
              dc.w %0111111111111110
              dc.w %0101111111111010
              dc.w %0101011111101010
              dc.w %0101010110101010
              dc.w %0101011111101010
              dc.w %0101111111111010
              dc.w %0111111111111110
       menu:blk.w  500
              end