


			Intuition Part 3
			================

 Gadgets! I said gadgets, so you will get gadgets. Even if it is the third
time this particular subject has cropped up.

 I took a right slamming after last months tutorial. Apparently the
examples were to complicated, too much source to demonstrate basic
principles. This month I will use simpler examples, but I'm also going to
make use of the start.s code.

 The start.s code can be used as the basis for a multitude of utilities
that run from an intuition window. It really is worth familiarising
yourself with it.

 Gadgets
 =======

 Steve Marshall supplied the first gadget explanation way back on disc 4.
This was not supported by any examples. On disc 8 the same tutorial was
repeated along with some example source.

 If you missed both these discs, your in luck! I am going to duplicate the
same tutorial here ( the wonders of magnetic media ). If you have read
through this before, I apologise for repetition. Steves tutorial serves as
an excellent reference piece.

 Following Steves tutorial I will pick things up again, explaining how to
detect gadgets and act on them. This will be demonstrated with a number of
examples. Do not worry if this seems complicated, it's mainly jargon. The
examples should clarify gadgets a little.

 So for the third time:

======================================================================
======================================================================
=                          Intuition Gadgets                         =
=                                                                    =
=                            By S Marshall                           =
======================================================================
 
   We all know what  gadgets are,we have all seen  them and used  them,from
 the close gadget on this window (no don't use it yet!),the screen position
 gadget in  preferences  to the  File  Name gadget  used to load a  file in
 Notepad.
  
 There are three  basic  types of gadget  supported by  Intuition  (but a
 number of variations on these -Note most manuals state that there are four
 types of gadget,however the Integer  gadget is only  really a special type 
 of string gadget).The  simplest  type of gadget is the Boolean gadget.This
 is a  simple on off  point and click type of gadget like the Close gadget.
 The  other  types of  gadget are the  proportional  gadget  and the string
 gadget.The proportional gadget is the type found down the left side of a
 window for  scrolling text or the move  screen  gadget in preferences. The
 string  gadget is the  type used in file  requesters,the  workbench rename 
 function etc. in fact any gadget that requires you to click in it and type
 some text.

 Gadget Structures
 ~~~~~~~~~~~~~~~~~   
   The gadget structure takes up 44 bytes and is made up as shown below.
   
gg_NextGadget    (long)
gg_LeftEdge      (word)
gg_TopEdge       (word)
gg_Width         (word)
gg_Height        (word)
gg_Flags         (word)
gg_Activation    (word)
gg_GadgetType    (word)
gg_GadgetRender  (long)
gg_SelectRender  (long)
gg_GadgetText    (long)
gg_MutualExclude (long)
gg_SpecialInfo   (long)
gg_GadgetID      (word)
gg_UserData      (long)

 Lets take a closer look at these variables.
 
 gg_NextGadget
 ~~~~~~~~~~~~~
   Gadgets are  usually added to a window  in the form of a linked  list of
 gadgets.This variable simply points to the next gadget in the list.If this
 is the only gadget or is the last in the list set this variable to NULL.
 
 gg_LeftEdge
 ~~~~~~~~~~~
   These next  four variables  discribe the  gadgets 'Hit' box.This  is the
 area which may be clicked in to activate the gadget.This variable discribes
 the position of the left  edge of the hit box in  relation  to the  windows
 left edge expressed in pixels.
     
 gg_TopEdge
 ~~~~~~~~~~
   This variable specifies  the top edge of the hit  box in relation to the
 top edge of the window,again expressed in pixels.

 gg_Width
 ~~~~~~~~
   The width in pixels of the gadgets hit box.
   
 gg_Height
 ~~~~~~~~~
   The height in pixels of the gadgets hit box.
   
 gg_Flags
 ~~~~~~~~
   Now we get to the more interesting stuff.These flags specify things like
 the gadgets type of imagery ind type of hihlighting etc.The flags are :-
 
 GADGHCOMP  ($0000) - When selected compement the gadgets colours.

 GADGHBOX   ($0001) - Draw a Box around gadget when selected.

 GADGHIMAGE ($0002) - Use an alternate image to render selected gadget.

 GADGHNONE  ($0003) - Do not hightlight selected gadget

 GADGIMAGE  ($0004) - Use image supplied to render unselected gadget.

 GRELBOTTOM ($0008) - If set gg_TopEdge is  relative to windows bottom edge.
                     
 GRELRIGHT  ($0010) - If set gg_LeftEdge is  relative to windows right edge.

 GRELWIDTH  ($0020) - If set gg_Width is relative to windows width.The value
                      in gg_Width should be a negative number.This number is
                      added to windows width to give  the gadgets width.Only
                      really makes sense with sizable windows.
                     
 GRELHEIGHT ($0040) - This works just like  GRELWIDTH but  makes the gadgets
                      relative to the windows height.
                     
 SELECTED   ($0080) - This  flag  preselects  the  gadgets  state.If set the
                      gadget will start off selected.

GADGDISABLED ($0100)- This  flag  disables a  gadget  if set.You  wouldn't
                      usually change this flag manually.Use the  functions
                      OnGadget and OffGadget instead.

 gg_Activation
 ~~~~~~~~~~~~~
   This variable sets some of the gadgets attributes.The flags are :-
   
RELVERIFY  ($0001) - Short for RELease VERIFY.If this flag is  set you will
                     only get a  GADGETUP  message if the  pointer is still
                     over the hit box when the mousebutton is  released.The
                     window close gadget is an example of this.You can click
                     in the close gadget then  move the pointer away before 
                     releasing the mousebutton and the window will not close.
                     
GAGIMMEDIATE ($0002) - If this flag is set you will recieve a GADGETDOWN
                       message immediatly the gadget is selected.
                       
ENDGADGET  ($0004) - This flag is  used with  requester  gadgets.If set the 
                     gadget will close the requester.
                     
FOLLOWMOUSE  ($0008) - When  this flag  is set you  will  receive MOUSEMOVE
                       messages while the gadget is selected.Note you  must
                       set   the   MOUSEMOVE   flag   in  your   NewWindows 
                       nw_IDCMPFlags variable to recieve these messages.
                       
RIGHTBORDER  ($0010) - If set the width and position of this gadget is used
                       to set the width of the windows right border.
                       
LEFTBORDER ($0020) - If set the width and  position of this  gadget is used
                     to set the width of the windows left border.
                       
TOPBORDER  ($0040) - If set the height and  position of this gadget is used
                     to set the height of the windows top border.It is also
                     used  to tell  intuition  that  this  gadget  must  be 
                     refreshed after it has rendered into the top border.

BOTTOMBORDER ($0080) - If set the height and position of this gadget is used
                       to set the height of the windows bottom border.

TOGGLESELECT ($0100) - This flag is  used with boolean  gadgets and  if set
                       causes  the gadget to toggle  on and  off instead of
                       only  being selected  while the left  mousebutton is
                       down.
                       
STRINGRIGHT  ($0200) - This flag is used with string gadgets and tells the 
                       system to centre the string.
                      
STRINGRIGHT  ($0400) - Also used with string  gadgets  this flag tells the
                       system to right justify the string.
                       
LONGINT    ($0800) - When set this  flag turns this  string gadget into an
                     Integer gadget.An Integer  gadget is a string  gadget
                     that will only except numerical characters (and + and
                     - signs).The string  will be  converted into a 32 bit
                     signed integer  and the value returned in the LongInt
                     variable of the StringInfo Structure.
                     
ALTKEYMAP ($1000) - This flag is used to tell  intuition  that you wish to 
                    use an  alternate  keymap with a string  gadget.If you
                    set this  flag you will  have  to point  the AltKeymap
                    variable in the StringInfo Structure to your keymap.
                    
BOOLEXTEND   ($2000) - Used with Boolean gadgets this flag tells intuition
                       that there is a BoolInfo structure attached to it.                       

gg_GadgetType
~~~~~~~~~~~~~
   This variable  indicates what type of gadget this is.You must set one of
 the  following flags or you will get a  recoverable Alert telling you that
 the gadget is of unknown type (04000001).The flags are :-

BOOLGADGET ($0001) - If set indicates that this is a Boolean gadget.

GADGET0002 ($0002) - Your guess is as good as mine.

PROPGADGET ($0003) - Indicates that this is a proportional gadget.

STRGADGET  ($0004) - Indicates that this is a string gadget.

Gadgets ($0010) to ($0080) refer to system gadgets and are not of that much
interest here.

REQGADGET ($1000) - Only set this bit if this is a requester gadget.

GZZGADGET ($2000) - Set this bit if your  gadget  is to be rendered  into a
                    Gimmezerozero windows border otherwise clear it.

SCRGADGET ($4000) - If set indicates that this is a screen gadget and not a
                    window gadget.
                    
SYSGADGET ($8000) - If set  this  is a system  gadget  otherwise  it is  an 
                    Applications Gadget.
 
gg_GadgetRender
~~~~~~~~~~~~~~~
   This variable is a  pointer to an  Image or a Border structure.These are 
 used to  render the  gadgets  imagery.If this is set to NULL no  rendering
 will be  done.If you  have set GADGIMAGE  in gg_Flags this  variable  must
 point to an Image  structure.If you haven't  set  GADGIMAGE then this must
 point to a Border structure or be set to NULL.
 
gg_SelectRender
~~~~~~~~~~~~~~
   If you have set GADGHIMAGE in gg_Flags then  this must point to the same
 type of structure in gg_GadgetRender.
   
gg_GadgetText
~~~~~~~~~~~~~
   If you want some text rendering  with your gadget you can point this to
 an IntuiText structure (more on this later).Otherwise set this to NULL.
  
gg_MutualExclude
~~~~~~~~~~~~~~~~
   This is currently  ignored  by intuition.Set to NULL unless you have set
 the BOOLEXTEND  flag in  gg_Activation,in  which  case it must  point to a
 BoolInfo  structure even though RKM says that gg_SpecialInfo  should point
 to the BoolInfo Structure.
 
gg_SpecialInfo
~~~~~~~~~~~~~~
   If this gadget  is  proportional  then  this  variable  bust  point to a
 PropInfo  structure.If it is a string or integer gadget  then this  should
 point  to a StringInfo  structure.If  the  gadget is  none  of these  this
 variable is ignored and should be set to NULL.
 
gg_GadgetID
~~~~~~~~~~~
   This variable is not  used by intuition  and is for the  programmers own
 use.It is  usually used to hold a number  which is used to  identify which
 gadget this is.

gg_UserData
~~~~~~~~~~~
   Again not used by intuition and may be used as you wish.
   

  Well thats the Gadget  structure.Quite a lot to learn in one go but thats
 how it  goes.We  haven't  finished  yet  though.We  still need to  look at 
 IntuiText,PropInfo,BoolInfo and  StringInfo  Structures.We will start with
 the  IntuiText structure.This is a  very useful  structure and crops up in
 many other intuitions functions.
 
it_FrontPen      (byte)
it_BackPen       (byte)
it_DrawMode      (byte)
it_Kludgfill00   (byte)
it_LeftEdge      (word)
it_TopEdge       (word)
it_ITextFont     (long)
it_IText         (long)
it_NextText      (long)

 
it_FrontPen
~~~~~~~~~~~
   This variable sets the pen number of the foreground colour.
   
it_BackPen
~~~~~~~~~~
   And this variable the backgroung pen number.
   
it_DrawMode
~~~~~~~~~~~
   This variable set the drawmode to be used  to render the text.The modes
 supported are :-

RP_JAM1        ($00) - Write in foreground colour,background is transparent

RP_JAM2        ($01) - Write using both foreground and background colours.

RP_COMPLEMENT  ($02) - Colours overwritten are complemented.

RP_INVERSVID   ($04) - Inverse video drawing mode.

  You may or  these together to produce  16 drawing  modes.Some more useful
 than others.

it_Kludgfill00
~~~~~~~~~~~~~~
   This is just to word align the rest of the structure.Set to 0.
   
it_LeftEdge
~~~~~~~~~~~
   This sets the leftedge of the  text relative to whatever graphics object
 the text is to be  rendered  with  ie. if this is for  gadget text then it 
 will be  positioned  relative to  the  top  left of the  gadget.If you are
 simply writing text into a window using intuitions PrintIText then it will
 be positioned relative to the windows top left.
 
it_TopEdge
~~~~~~~~~~
  This sets the topedge of the text relative to the graphics object that it
 is being rendered with.
  
it_ITextFont
~~~~~~~~~~~~
  This should be NULL if you are willing to use the font set by preferences
 or point to a TextFont structure if you want a specific font. 
 
it_IText
~~~~~~~~
   This variable simply points to the NULL terminated string to be printed.
   
it_NextText
~~~~~~~~~~~
   This is a pointer to another IntuiText structure if more than one is to
 be printed.Otherwise set this to NULL.
  The IntuiText structure is one of the building blocks of intuition and is
 well worth getting familiar with.

  Now lets look at the BoolInfo structure  which is  used to  create Masked
 gadgets.Masked gadgets are a  way of creating irregular shape gadgets.The
 BoolInfo structure is a small one at 10 bytes long and is defined below.
  
bi_Flags         (word) - Only BOOLMASK ($0001) supported at present.

bi_Mask          (long) - Pointer used for selecting and highlighting the
                          gadget.Mask must be in chip ram.
                          
bi_Reserved      (long) - Reserved for future expansion.Set to NULL.

 The  PropInfo  structure  is   used  for  all   proportional  gadgets  and 
 gg_SpecialInfo  should  point to  one if  the  gadget is  proportional.The
 PropInfo structure is 22 bytes long and is defined below.

pi_Flags         (word)
pi_HorizPot      (word)
pi_VertPot       (word)
pi_HorizBody     (word)
pi_VertBody      (word)
pi_CWidth        (word)
pi_CHeight       (word)
pi_HPotRes       (word)
pi_VPotRes       (word)
pi_LeftBorder    (word)
pi_TopBorder     (word)


pi_Flags
~~~~~~~~
   This variable defines some of the gadgets characteristics.The flags are.
   
AUTOKNOB         ($0001) - Use default mover  image.If  this flag is  clear 
                           then  gg_GadgetRender  must  point to  the image
                           structure that defines the custom mover.

FREEHORIZ        ($0002) - If set the mover may move horizontally.

FREEVERT         ($0004) - The mover can move vertically if this flags set.

PROPBORDERLESS   ($0008) - If set the gadget is rendered without a border

KNOBHIT          ($0010) - This flag is set when the knob is hit (ouch!).
                           Your program may test this flag.
                          
pi_HorizPot
~~~~~~~~~~~
  This variable contains the  current horizontal position of  the mover.The
 values always range  from $0000 to  $ffff.You may initialize this variable
 so the position of  the mover is  set when the gadget is  rendered.You may
 also read this variable while the user is messing with the gadget.
 
pi_VertPot
~~~~~~~~~~
  This variable works just like pi_HorizPot but for the vertical position.

pi_HorizBody
~~~~~~~~~~~~
   These next two variables serve two purposes.When used with the autoknob
  mover they  define the size of  the mover.The range of  the variable  is 
  from KNOBHMIN ($0006) to  $ffff.A size of  $ffff fills  the container in
  the horizontal  direction and  KNOBMIN makes the mover the smallest size
  possible.If a value of $8000 is  used the mover will be half the size of 
  the container.With  both autoknob  and custom movers  this variable also
  sets the amount the mover will move  when the user clicks  in the gadget
  container either side  of the mover.For example  if a value  of $5555 is 
  used the mover will be one third the size of the container and will move
  one third of  the distance across  the container when the user clicks to
  one side of the mover.You should not directly change the values of these
  two variables,use ModifyProp or NewModifyProp instead.
   
pi_VertBody
~~~~~~~~~~~
   This variable works just like pi_HorizBody but works for the vertical
  direction.
  

- The following variables are private to intuition.Initialize them to NULL
  and don't mess with them.

pi_CWidth
~~~~~~~~~
   This  variable  contains  the  absolute size  of  the gadgets  container
  width (the container is the part of  the gadget that the mover is free to
  move in).
  
pi_CHeight
~~~~~~~~~~
   This  variable  contains  the  absolute size  of  the gadgets  container
  height.
   
pi_HPotRes
~~~~~~~~~~
   This variable contains the gadgets horizontal pot increments.
   
pi_VPotRes
~~~~~~~~~~
   This variable contains the gadgets vertical pot increments.

pi_LeftBorder
~~~~~~~~~~~~~
   This variable contains the position of the gadgets left border.
   
pi_TopBorder
~~~~~~~~~~~~
   This variable contains the position of the gadgets top border.
  

  This leaves  us with  the last gadget structure  the StingInfo structure.
 The  StringInfo structure is used for  all string  and integer gadgets and 
 gg_SpecialInfo should point to one  if the gadget is string or integer.The
 StringInfo structure is 36 bytes long and is defined below.


si_Buffer        (long)
si_UndoBuffer    (long)
si_BufferPos     (word)
si_MaxChars      (word)
si_DispPos       (word)
si_UndoPos       (word)
si_NumChars      (word)
si_DispCount     (word)
si_CLeft         (word)
si_CTop          (word)
si_LayerPtr      (long)
si_LongInt       (long)
si_AltKeyMap     (long)


si_Buffer
~~~~~~~~~
  Pointer to the buffer for gadgets text.Buffer should be at least the same
 size as si_MaxChars.This buffer  is where you will find the text after the
 user has finished using the gadget.
 
si_UndoBuffer
~~~~~~~~~~~~~
  Pointer  to the buffer used  for the  undo function.May  be NULL  if you
 don't want  the undo function.Buffer should be the same size as si_Buffer.

si_BufferPos
~~~~~~~~~~~~
  Character position in the buffer.
  
si_MaxChars
~~~~~~~~~~~
  Set  to maximun number  of characters  allowed + 1  (for NULL teminator).
 Note  the maximum  number  of characters  may  be greater than  the gadget
 container  can hold.The gadget  will handle  the scrolling  through  text,
 editing etc.
 
si_DispPos
~~~~~~~~~~
  This variable contains  the position  of the first character displayed in
 the gadgets container.
 
- These next six variables are initialised and maintained  by intuition.Set
  them to NULL.
  
si_UndoPos
~~~~~~~~~~
  Character position in the undo buffer.
  
si_NumChars
~~~~~~~~~~~
  This variable contains the number of characters currently in the buffer.
   
si_DispCount
~~~~~~~~~~~~
 This variable contains the number of whole (completely visible) characters
 that are displayed in the gadget.
 
si_CLeft
~~~~~~~~
  This variable contains the left offset of the container.
  
si_CTop
~~~~~~~
  This variable contains the top offset of the container.
  
si_LayerPtr
~~~~~~~~~~~
  This is a pointer to the RastPort containing this gadget.
  
si_LongInt
~~~~~~~~~~
  If your gadget is of the Integer variety then this variable will contain
 the numerical value  of the string ie.  if the user typed in '32768' then
 this variable will contain  the numerical  value 32768 when  the user has 
 finished using the gadget.
   
si_AltKeyMap
~~~~~~~~~~~~
  If you set the  ALTKEYMAP flag  in gg_Activation then  this must point to
 your alternate keymap.
 

  Well thats all the gadget structures covered (phew!).That's the nasty bit
 over now we can have a little fun with some gadgets.

  Here we  will look at the Intuition routines that are used to  manipulate
 gadgets and how we add gadgets to a window.

  The easiest way to add gadgets to a  window is to point nw_FirstGadget in
 your NewWindow structure to our list of gadgets before we open the window.
 This will cause all the gadgets in  our list to be displayed ready for use
 when the window opens.Other methods of  adding gadgets to  windows are the
 intuition routines AddGadget (-$002a) and AddGList (-$01b6).AddGadget adds
 a  single gadget to the window and AddGList adds a  linked list of gadgets
 to the window.They are called with:
 
AddGadget (Window,Gadget,Position)
             A0     A1      D0
             
  Where Window  is a  pointer to  the  window  structure of  the  window to
 receive the gadget.This is the same pointer as returned by OpenWindow.
  Gadget is a pointer to the gadget to be added.
  Position is the position in the windows list of gadgets.A value of 0 will
 add the gadget to the head of the list and a value greater than the number
 of gadgets already  in the list will add the gadgets  to the end (tail) of
 the list.

  On return from AddGadget D0 will contain the position in the list where
  the gadget was actually added.
  
AddGList (Window,Gadgets,Position,NumGad,Requester)
            A0     A1      D0      D1       A2
            
  Where Window  is  a  pointer  to the window  structure  of the  window to 
 receive the gadgets.
  And Gadgets is a pointer to the gadget list to be added.
  Position  is the position  in the windows list  of gadgets.The same rules
 apply here as for AddGadget.
  NumGad is the  number of  gadgets to  be added.A value of -1 will add all
 the gadgets in the list.
  Requester is a pointer to the requester the gadgets are to be added to.If
 the first gadget  in the list is not  of type REQGADGET this value will be
 ignored,in which case set A2 to NULL.

  On return from AddGadget D0 will contain the position in the list where
  the gadget was actually added.
 
  If we have added our gadgets to the window with one of these two routines
 then they will not yet be displayed.To display the gadgets we must refresh
 them.We may also want to  refresh the gadgets later if  we think that some
 drawing routine has  overwritten our  gadgets.There are  two  routines for
 refreshing  gadgets.These  are  RefreshGadgets  (-$00de) and  RefreshGList
 (-$01b0).These are called as shown below:
  
RefreshGadgets (Gadgets,Window,Requester)
                  A0     A1      A2
                  
  The meanings of  the registers are the same as  before.Note A0 and A1 are
 reversed.
 
RefreshGList (Gadgets,Window,Requester,NumGad)
                A0      A1      A2       D0
                
 RefreshGList is much the same as RefreshGadgets except that we may specify
 the number  of gadgets to be refreshed in D0.If a value of -1 is used then
 all the gadgets  in  the  list  will  be  refreshed  making  this  routine
 functionally the same as RefreshGadgets.
 
  If at some time during program execution we decide we want to remove the
 gadgets the routines available are  RemoveGadget (-$00e4) and RemoveGList
 (-$01bc).These are called as shown below.
 
RemoveGadget (Window,Gadget)
                A0     A1
                
RemoveGList (Window,Gadget,NumGad)
                A0     A1    D0
                
  Again the meanings of the registers are much the same as before.On return
 from both routines D0 will contain the gadgets position in the gadget list
 before it was removed.If the gadget was not found D0 will contain -1.
 
  If we wish to simply disable the gadget or to enable an already disabled
 gadget then the routines to use are OffGadget(-$00b4) and OnGadget($00ba).
 These are called as shown below:
 
OffGadget (Gadgets,Window,Requester)
             A0      A1      A2 
                
OnGadget (Gadgets,Window,Requester)
             A0      A1      A2     
 
  
  Calling  OffGadget  will cause  the gadget  to  be ghosted  and cannot be
 selected by the user.Calling OnGadget  will reverse this process.Note that
 these routines are for gadgets that have already been attached to a window.
 If the gadget has not yey been added to a window then you may directly set
 or clear the GADGDISABLED flag in gg_Flags  and should not use OnGadget or
 OffGadget.
 
  If we have a sting gadget  in our window then we may at some time want to 
 activate it so the user can simply start typing his/her text without first
 having to click on the gadget.To do this we have the routine ActivateGadget
 (-$01ce).This is called as shown below:
 
ActivateGadget (Gadget,Window,Requester)
                  A0     A1      A2
                  
  For this routine to work the window containing the gadget must be active,
 and the user must not  be using  the menus or  any other gadgets.When this
 routine returns the value in D0 will be either TRUE or FALSE.If the gadget
 was activated  D0 will return  TRUE and  if ActivateGadget failed  D0 will
 return FALSE.
 
  If for some reason we  wish to  alter a  proportional  gadget we use the
 routines ModifyProp (-$009c) and  NewModifyProp (-$01d4).These are called
 as shown below:
 
ModifyProp(Gadget,Window,Request,Flags,HorizPot,VertPot,Horizbody,VertBody)
             A0     A1      A2    D0      D1       D2       D3       D4
             
  This looks quite complex but  isn't really.The  first three have the same
 meanings as those used previously.The other five values in  D0 - D4 simply
 contain the new  values for the  similary named variables in the  PropInfo
 structure.See the previous  discription of  the PropInfo structure for the
 values and  meanings  of  these  variables.Note  calling  ModifyProp  will 
 refresh  all  the  gadgets from  the one  being modified to the end of the 
 gadget list.
 
NewModifyProp:
(Gadget,Window,Request,Flags,HorizPot,VertPot,Horizbody,VertBody,NumGad)
   A0     A1      A2    D0      D1       D2       D3       D4      D5
   
  NewModifyProp is much the same as  ModifyProp except for the extra NumGad
 parameter.This gives us  control over  the number of  gadgets that will be
 refreshed when we call this routine.A value of-1 means refresh all gadgets
 to  the end  of the list making  NewModifyProp  functionally  the same  as
 ModifyProp.This is the better (and newest) routine  to use as we don't get
 that  nasty  flickering  of  the rest  of  the gadgets when  we modify our
 proportional gadget.
 Well that just about covers gadgets. I hope that the  information provided
 here is a  little more  clear than  that  provided  in the  Libraries  and
 Devices manual.
 
 Steve Marshall  Unstone,Sheffield,England

======================================================================
======================================================================
======================================================================

 Programming Gadgets
 ~~~~~~~~~~~~~~~~~~~

 To summarise a gadget structure then. A rectangular area of the screen
must be initialsied as thew 'Hit Box' where the user can click. Three types
of gadget are available and one of these types MUST be specified. The types
available are BOOLEAN, STRING ( INTEGER ) and PROPORTIONAL.

 BOOLEAN gadgets can have their hit box represented by a Border or an
Image. STRING gadgets and PROPORTIONAL gadgets are usualy represented by a
Border.

 Text can be displayed with the gadget by attaching IntuiText structures to
the gadget structure.

 The most commonly used activation flags are RELVERIFY and GADGIMMEDIATE.
If GADGIMMEDIATE is used, Intuition will send a message to your program
as soon as the gadgets is clicked on. If RELVERIFY is used, Intuition will
not send a message until the user releases the left mouse button. A further
advantage of RELVERIFY is that if the user moves the mouse pointer off the
gadget and then releases the mouse button, no message is sent.

 Gadgets can be linked to a NewWindow structure so they appear when the
window is first opened.

 Lets look at a straight forward BOOLEAN gadget structure:  

BoolGadg:
	dc.l	0		next gadget
	dc.w	29,24		origin XY of hit box relative to window TopLeft
	dc.w	78,13		hit box width and height
	dc.w	0		gadget flags
	dc.w	RELVERIFY	activation flags
	dc.w	BOOLGADGET	gadget type flags
	dc.l	.Border		gadget border or image to be rendered
	dc.l	0		alternate imagery for selection
	dc.l	.IText		first IntuiText structure
	dc.l	0		gadget mutual-exclude long word
	dc.l	0		SpecialInfo structure
	dc.w	0		user-definable data
	dc.l	0		pointer to user-definable data

.Border
	dc.w	-2,-1		XY origin relative to container TopLeft
	dc.b	2,0,RP_JAM1	front pen, back pen and drawmode
	dc.b	5		number of XY vectors
	dc.l	.Vectors	pointer to XY vectors
	dc.l	0		next border in list

.Vectors
	dc.w	0,0
	dc.w	81,0
	dc.w	81,14
	dc.w	0,14
	dc.w	0,0

.IText
	dc.b	1,0,RP_JAM2,0	front and back text pens, drawmode and fill byte
	dc.w	16,3		XY origin relative to container TopLeft
	dc.l	0		font pointer or 0 for default
	dc.l	.String		pointer to text
	dc.l	0		next IntuiText structure

.String
	dc.b	'CANCEL',0
	even

 Notice I have used local labels to mark the Border and IntuiText
structures. I do this so that I can cut this gadget out and use it time and
time again. All that will need to be altered is the gadgets label, x and y
position on the screen, text string and possibly dimensions. There is no
need to alter the sub-structure labels as they are local. Look at most of
my programs and you will find this method adopted.

 Lets look at each field in the gadget structure. I will not cover the
Border or IText structures as these were explained last month.

 The next gadget field is set to zero. This indicates that this is the last
gadget in the list, in this case it's the only gadget in the list. The
gadgets hit box will be at (29,24) and will be 78 pixels wide and 13 pixels
high.

 The gadgets flags is set to 0, this is the same a setting GADGHCOMP or
inverse video highlighting. The gadget is a RELVERIFY BOOLEAN gadget.

 Pointers to the Border and Text structures are placed in the appropriate
fields. The remaining fields are set to 0.

 This gadget could be added into an example program, but first I would like
to cover gadget detection programming. I have adopted the method explained
to me by Steve Marshall as this is easier to grasp than the RKM C method.

 When a gadget is selected, Intuition sends a message to the appropriate
port ( the UserPort of window ). If you remember, the im_IAddress field
will contain the address of the structure belonging to the object
responsible for the message.

 In the case of a gadget the im_IAddress field will contain the address of
the gadget selected. If we were to store the address of the subroutine to
be called when a gadget is selected in the gg_UserData field of the gadgets
structure, it becomes a simple task to decide what action to take when a
gadget is selected.

 In the event loop discussed last month the im_Address is stored in
register a5. So suitable code to obtain the address of a subroutine stored
in the gg_UserData field and then call that subroutine would be:

		move.l		gg_UserData(a5),d0
		beq		.no_sub
		move.l		d0,a0
		jsr		(a0)

.no_sub

 Notice the little check to make sure that there is something stored in the
UserData field. Failure to do this could lead to the reset routine being
called!

 Lets program a Cancel gadget as explained above. To make the code a little
easier to follow, I have used a stripped version of the start.s code used
last month. This comes without any of the useful subroutines. This code
just opens a window and enters an event loop set up to deal with gadget
selection as outlined above. I will still use the full blown start.s code
in the course of these tutorials to build up some simple utility programs.
Gadgets are a very powerful tool to assembly language programmers and I am
going to spend quite some time on them.

 The gadget I am going to use is the one explained as above, with the
address of a subroutine added to the UserData field. This subroutine moves
the value CLOSEWINDOW into register d2, the only way to quit the event
loop. What this is doing is fooling the event loop into thinking the
windows close gadget was clicked.

 The gadget structure then, less the Border and IText structures as these
are identical to those shown above:

CancelGadg:
	dc.l	0		next gadget
	dc.w	29,24		origin XY of hit box relative to window TopLeft
	dc.w	78,13		hit box width and height
	dc.w	0		gadget flags
	dc.w	RELVERIFY	activation flags
	dc.w	BOOLGADGET	gadget type flags
	dc.l	.Border		gadget border or image to be rendered
	dc.l	0		alternate imagery for selection
	dc.l	.IText		first IntuiText structure
	dc.l	0		gadget mutual-exclude long word
	dc.l	0		SpecialInfo structure
	dc.w	0		user-definable data
	dc.l	Cancel		address of subroutine to call on selection

 The address of this gadget structure ( it's label ) is inserted into the
new window structure so that the gadget appears when the window is first
opened.

 And the subroutine that will be called when this gadget is selected:

Cancel		move.l		#CLOSEWINDOW,d2
		rts

 That is all there is to it. A functional Cancel gadget. Did you see how
the drawing pens are set different for the text and border so they appear
in different colours?

 This example is on the disc and is called int_eg1.s. To make life easier,
in all the gadget examples the gadget data structures and subroutines will
be appended to the end of start.s. To see the gadget specific code jump to
the end of the listing. The start of each listing is a the library
open/close and event loop code.

 Do you see the advantage of this method of programming. When you wish to
add a new function, add the gadget to the list and supply the subroutine to
deal with this.

 Lets experiment with this example. Below is a list of alterations to make
to the gadget structure. Each alteration should be preformed on the
original int_eg1.s code and then assembled and run to see the result of the
alteration:

 1/ The gadget is in a silly position, so we need to move it down a bit.
    To move the gadget we only need alter the starting X,Y position of the
    Hit Box as all other defenitions are relative to this. Change the y
    value from 24 to 170, reassemble and run.

     You can save this version as the gadget is now in a sensible position.

 2/ Lets make this a GADGIMMEDIATE gadget. Delete the RELVERIFY from the 
    activation flags field and enter GADGIMMEDIATE, assemble and run.

    Once you have played with this change back to RELVERIFY.

 3/ Lets experiment with the gadgets selection highlighting. To do this we
    need to add an entry to the gadget flags field, presently set to 0. 
    Change this to GADGHBOX, this will cause a box to appear round the 
    gadget when selected.

     To see this in action, move the mouse pointer over the gadget and
    press but do not release the left mouse button. With the button still
    down move the mouse pointer on and off the gadget. You should see the
    gadget highlighting switch on and off.

 4/ There is no need to have a Border round a gadget. To verify this delete
    the pointer to the Border structure ( .Border ), assemble and run.

 5/ There is no need to have Text printed with a gadget. To verify this
    delete the pointer to the IntuiText structure ( .IText ), assemble and
    run.

 6/ Lastly, lets allow the gadget to move when the window is sized. First
    remove the pointer to the Border as in example 4/. Next change the y
    position to -30, this means 30 pixels ABOVE the bottom border. Next
    add GRELBOTTOM and GADGHBOX to the gadget flags field. The structure
    should now look like this:


BoolGadg:
	dc.l	0		next gadget
	dc.w	29,-30		origin XY of hit box relative to window TopLeft
	dc.w	78,13		hit box width and height
	dc.w	GRELBOTTOM+GADGHBOX		gadget flags
	dc.w	RELVERIFY	activation flags
	dc.w	BOOLGADGET	gadget type flags
	dc.l	0		gadget border or image to be rendered
	dc.l	0		alternate imagery for selection
	dc.l	.IText		first IntuiText structure
	dc.l	0		gadget mutual-exclude long word
	dc.l	0		SpecialInfo structure
	dc.w	0		user-definable data
	dc.l	Cancel		pointer to user-definable data

    Assemble and run this example. Try changing the window size using the
    sizing gadget. The gadget should move to its new position 30 pixels 
    above the bottom window border when you release the sizing gadget.

    You can also make a gadget move relative to the right border and even
    set it's width and height as variables dependant on the windows size.
    Play some more with the GREL options ( as explained in Steves notes ).

 I should point out at this stage that a RELVERIFY gadget will cause a
GADGETUP message to be sent by Intuition while a GADGIMMEDIATE will cause a
GADGETDOWN one. The event loop used in start.s can deal with both.

 Lets add another gadget to this window. 

 For simplicity, lets add a gadget that will turn the background colour red
when clicked and one to turn it blue ( sorry if you are using some other
colour, alter the source ). Before adding the gadgets, lets look at the
subroutine:

GoRed		move.l		window.ptr,a0		a0->the window
		CALLINT		ViewPortAddress		get addr of ViewPort
		move.l		d0,a0			a0->ViewPort
		moveq.l		#0,d0			d0=WBench background
		moveq.l		#$f,d1			max RED component
		moveq.l		#0,d2			no GREEN
		moveq.l		#0,d3			no BLUE
		CALLGRAF	SetRGB4
		moveq.l		#0,d2			ensure no quit
		rts


GoBlue		move.l		window.ptr,a0		a0->the window
		CALLINT		ViewPortAddress		get addr of ViewPort
		move.l		d0,a0			a0->ViewPort
		moveq.l		#0,d0			d0=WBench background
		moveq.l		#0,d1			no RED
		moveq.l		#0,d2			no GREEN
		moveq.l		#$f,d3			max BLUE component
		CALLGRAF	SetRGB4
		moveq.l		#0,d2			ensure no quit
		rts

 The graphics function SetRGB4 requires the address of the ViewPort to
alter a colour in. To obtain this I have used the Intuition function
ViewPortAddrss which requires a pointer to the window structure in register
a0.

 Colour register 0 is used for the WorkBench screens background colour,
this is set prior to calling SetRGB4.

 Now for the gadgets. Below are the structures for both. These were
obtained by cutting out the original gadget struct and altering the
position, text and subroutine address. Quite simple or what?


RedGadg:
	dc.l	BlueGadg	next gadget
	dc.w	120,50		origin XY of hit box relative to window TopLeft
	dc.w	78,13		hit box width and height
	dc.w	GADGHBOX	gadget flags
	dc.w	RELVERIFY	activation flags
	dc.w	BOOLGADGET	gadget type flags
	dc.l	.Border		gadget border or image to be rendered
	dc.l	0		alternate imagery for selection
	dc.l	.IText		first IntuiText structure
	dc.l	0		gadget mutual-exclude long word
	dc.l	0		SpecialInfo structure
	dc.w	0		user-definable data
	dc.l	0		pointer to user-definable data

.Border
	dc.w	-2,-1		XY origin relative to container TopLeft
	dc.b	2,0,RP_JAM1	front pen, back pen and drawmode
	dc.b	5		number of XY vectors
	dc.l	.Vectors	pointer to XY vectors
	dc.l	0		next border in list

.Vectors
	dc.w	0,0
	dc.w	81,0
	dc.w	81,14
	dc.w	0,14
	dc.w	0,0

.IText
	dc.b	1,0,RP_JAM2,0	front and back text pens, drawmode and fill byte
	dc.w	16,3		XY origin relative to container TopLeft
	dc.l	0		font pointer or 0 for default
	dc.l	.String		pointer to text
	dc.l	0		next IntuiText structure

.String
	dc.b	' RED ',0
	even



BlueGadg:
	dc.l	0		next gadget
	dc.w	120,80		origin XY of hit box relative to window TopLeft
	dc.w	78,13		hit box width and height
	dc.w	GADGHBOX	gadget flags
	dc.w	RELVERIFY	activation flags
	dc.w	BOOLGADGET	gadget type flags
	dc.l	.Border		gadget border or image to be rendered
	dc.l	0		alternate imagery for selection
	dc.l	.IText		first IntuiText structure
	dc.l	0		gadget mutual-exclude long word
	dc.l	0		SpecialInfo structure
	dc.w	0		user-definable data
	dc.l	0		pointer to user-definable data

.Border
	dc.w	-2,-1		XY origin relative to container TopLeft
	dc.b	2,0,RP_JAM1	front pen, back pen and drawmode
	dc.b	5		number of XY vectors
	dc.l	.Vectors	pointer to XY vectors
	dc.l	0		next border in list

.Vectors
	dc.w	0,0
	dc.w	81,0
	dc.w	81,14
	dc.w	0,14
	dc.w	0,0

.IText
	dc.b	1,0,RP_JAM2,0	front and back text pens, drawmode and fill byte
	dc.w	16,3		XY origin relative to container TopLeft
	dc.l	0		font pointer or 0 for default
	dc.l	.String		pointer to text
	dc.l	0		next IntuiText structure

.String
	dc.b	' BLUE',0
	even

 Notice that the next gadget field of the RedGadg points to the BlueGadg.
It is also necessary to put the address of the RedGadg in the next gadget
field of the CancelGadg. Once this is done a list will have been built as
shown below:

			________________
			|    window    |
			|______________|
				|
				|
			________|_______ 
			|  Cancel gadg |
			|______________|
				|
				|
			________|_______
			|  Red    gadg |
			|______________|
				|
				|
			________|_______
			| Blue    gadg |
			|______________|


 So when the window is opened all three gadgets will be displayed. Assemble
and run the example, int_eg2.s.

 This tutorial should have given you some insight into Gadgets under
Intuition. Next month I will introduce Images into the gadget structure and
also mutually exclusive gadgets. I'm afraid you'll have to wait for string
and proportional gadgets for a while.

 Do not forget to experiment with boolean gadgets. As always I would be
interested in seeing any of your efforts.

					Mark.


