{*
** An example of GadTools library usage: Scroller Gadget.
**
** Adapted from RKM: Libraries (1992), p 383-385 
** and NDK example gadget1.c, by David Benn, 
** 18th March, 3rd April, 1st,4th May, 8th June 1995.
*}

#include <gadtools.h>

declare function printf external

{*
** Constant definitions.
*}
CONST GAD_SCROLLER = 1

{*
** Forward SUB declarations.
*}
DECLARE SUB process_window_events(ADDRESS wdw)
DECLARE SUB gadtools_window
DECLARE SUB handle_gadget(ADDRESS msg)
DECLARE SUB do_window_refresh(ADDRESS wdw)

{*
** Shared library function declarations.
*}
LIBRARY "exec.library"
LIBRARY "utility.library"
LIBRARY "intuition.library"
LIBRARY "gadtools.library"

'..intuition.library
DECLARE FUNCTION ModifyIDCMP(ADDRESS wdw, LONGINT flags) LIBRARY
DECLARE FUNCTION SHORTINT AddGList(ADDRESS wdw, ADDRESS gad, ~
			  	   SHORTINT position, SHORTINT numGad, ~
			  	   ADDRESS req) LIBRARY intuition

DECLARE FUNCTION RefreshGadgets(ADDRESS gad, ADDRESS wdw, ~
				ADDRESS req) LIBRARY intuition

'..gadtools.library
DECLARE FUNCTION ADDRESS CreateContext(ADDRESS glistPtr) LIBRARY gadtools
DECLARE FUNCTION FreeGadgets(ADDRESS glist) LIBRARY gadtools
DECLARE FUNCTION ADDRESS GetVisualInfoA(ADDRESS scrn, ADDRESS tags) LIBRARY gadtools
DECLARE FUNCTION FreeVisualInfo(ADDRESS visualInfo) LIBRARY gadtools
DECLARE FUNCTION ADDRESS CreateGadgetA(LONGINT kind, ADDRESS prevGad, ~
				       ADDRESS newGad, ADDRESS tags) LIBRARY gadtools
DECLARE FUNCTION GT_RefreshWindow(ADDRESS wdw,ADDRESS requester) LIBRARY gadtools
DECLARE FUNCTION ADDRESS GT_GetIMsg(ADDRESS userPort) LIBRARY gadtools
DECLARE FUNCTION GT_ReplyIMsg(ADDRESS intuiMsg) LIBRARY gadtools
DECLARE FUNCTION GT_BeginRefresh(ADDRESS wdw) LIBRARY gadtools
DECLARE FUNCTION GT_EndRefresh(ADDRESS wdw, SHORTINT complete) LIBRARY gadtools

'..utility.library
DECLARE FUNCTION ADDRESS AllocateTagItems(LONGINT numTags) LIBRARY utility
DECLARE FUNCTION FreeTagItems(ADDRESS tagArrayPtr) LIBRARY utility

'..exec.library
DECLARE FUNCTION WaitPort(ADDRESS userPort) LIBRARY exec

{*
** Global variables.
*}
'..see intuition/gadgetclass.h re: this.
LONGINT GA_RelVerify
GA_RelVerify = TAG_USER + &H30016

DECLARE STRUCT TextAttr gadFont
gadFont->ta_Name  = SADD("topaz.font")
gadFont->ta_YSize = 8
gadFont->ta_Style = 0
gadFont->ta_Flags = 0

{*
** Subprogram definitions.
*}
SUB gadtools_window
{*
** Prepare for using GadTools, set up gadgets
** and open window.
*}
'*** MUST SHARE THESE!! ***
SHARED GTSC_Top, GTSC_Total, GTSC_Visible, GTSC_Arrows, GA_RelVerify
SHARED SCROLLERIDCMP

SHARED gadFont

DECLARE STRUCT ScreenStruct *mysc
DECLARE STRUCT TextAttr *scrFont
DECLARE STRUCT WindowStruct *mywin
DECLARE STRUCT IntuiGadget *glist, *gad
DECLARE STRUCT NewGadget ng
DECLARE STRUCT TagItem *gadTags, *tag
ADDRESS vi

  glist = NULL
  
  mysc = SCREEN(1)
  IF mysc <> NULL THEN
    vi = GetVisualInfoA(mysc, NULL)
    IF vi <> NULL THEN
      '..GadTools always requires this step to be taken.
      gad = CreateContext(@glist)

    {* All the gadget creation calls accept a pointer to the previous
     * gadget, and link the new gadget to that gadget's NextGadget field.
     * Also, they exit gracefully, returning NULL, if any previous gadget
     * was NULL.  This limits the amount of checking for failure that
     * is needed.  You only need to check before you tweak any gadget
     * structure or use any of its fields, and finally once at the end,
     * before you add the gadgets. *}

    {* Create a (horizontal by default) scroller *}

    ng->ng_LeftEdge = 210
    ng->ng_TopEdge = 60
    ng->ng_Width = 100
    ng->ng_Height = 10
    ng->ng_GadgetText = SADD("My Amazing Scroller")
    ng->ng_TextAttr = gadFont
    ng->ng_VisualInfo = vi
    ng->ng_GadgetID = GAD_SCROLLER
    ng->ng_Flags = NULL
    
    gadTags = AllocateTagItems(6)
    IF gadTags <> NULL THEN
        tag = gadTags
        tag->ti_Tag = GTSC_Top : tag->ti_Data = 2
	tag = tag + SIZEOF(TagItem)
        tag->ti_Tag = GTSC_Total : tag->ti_Data = 10
	tag = tag + SIZEOF(TagItem)
        tag->ti_Tag = GTSC_Visible : tag->ti_Data = 5
	tag = tag + SIZEOF(TagItem)
        tag->ti_Tag = GTSC_Arrows : tag->ti_Data = 12
	tag = tag + SIZEOF(TagItem)
        tag->ti_Tag = GA_RelVerify : tag->ti_Data = 1
	tag = tag + SIZEOF(TagItem)
	tag->ti_Tag = TAG_DONE
    END IF

    gad = CreateGadgetA(SCROLLER_KIND, gad, ng, gadTags)
    FreeTagItems(gadTags)

      '..Open window, render gadgets and enter event-handling loop.	
      IF gad <> NULL THEN
	WINDOW 1,"GadTools Scroller Gadget Demo",(0,0)-(400,150),30
	IF ERR = 0 THEN
 	  mywin = WINDOW(7)

	  ModifyIDCMP(mywin, mywin->IDCMPFlags OR SCROLLERIDCMP)

	  AddGList(mywin,glist,0,-1,NULL)
	  RefreshGadgets(glist,mywin,NULL)
	  GT_RefreshWindow(mywin,NULL)

	  process_window_events(mywin)
	  WINDOW CLOSE 1
        END IF
      END IF
    
      '..FreeGadgets() must be called after the context has been
      '..created. It does nothing if glist is NULL.
      FreeGadgets(glist)
      FreeVisualInfo(vi)
    END IF        
  END IF
END SUB

SUB process_window_events(ADDRESS mywinaddr)
{*
** Standard message handling loop with GadTools message
** handling functions used (GT_GetIMsg() and GT_ReplyIMsg()).
*}
DECLARE STRUCT WindowStruct *mywin : mywin = mywinaddr
DECLARE STRUCT IntuiMessage *imsg
DECLARE STRUCT IntuiGadget *gad
LONGINT terminated, class

  WHILE NOT terminated
    WaitPort(mywin->UserPort)

    '..Use GT_GetIMsg() and GT_ReplyIMsg() for handling
    '..IntuiMessages with GadTools gadgets.    
    REPEAT
      imsg = GT_GetIMsg(mywin->UserPort)
      class = imsg->Class
      CASE
	'..Scroller/arrow button activation verified?
 	class = GADGETUP : handle_gadget(imsg)
        '..Has window close gadget been clicked? 
	class = CLOSEWINDOW : terminated = true
        '..This handling is REQUIRED with GadTools.
	class = REFRESHWINDOW : do_window_refresh(mywin)
      END CASE
      GT_ReplyIMsg(imsg)          
    UNTIL terminated OR imsg = NULL
  WEND
END SUB

SUB handle_gadget(ADDRESS msg)
DECLARE STRUCT IntuiMessage *imsg
  imsg = msg  
  MsgBox STR$(imsg->Code),"OK"
END SUB

SUB do_window_refresh(ADDRESS wdw)
  GT_BeginRefresh(mywin)
  GT_EndRefresh(mywin,true)
END SUB

{*
** Main program.
*}
gadtools_window
LIBRARY CLOSE
END
