Contents page


    Many programs need to display a list of information that the user can scroll
    through and select items from. An obvious example would be the list of names
    in a file requester.

    Most lists tend to be similar in format. They are  arranged  vertically  and
    have  a scroll bar and incremental click gadgets on the right. When the user
    clicks on an item in the list, it becomes highlighted.

    InovaTools 1 provides  a  quick  method  for  handling  such  vertical,  one
    dimensional  lists.  There  are  routines  to  create, display, insert into,
    delete from, and scroll lists. The  lists  can  be  dynamically  resized  in
    height, should the user adjust the window size.

    If you need to display a one dimensional linked list of data  items,  here's
    how you go about it:

    The ListInfo Structure

    This carries all the information about your list display.

    struct ListInfo{
        USHORT LeftEdge, TopEdge, Width, Height;
        USHORT ItemHeight;
        USHORT ScrollID, ListID, ClickUpID, ClickDownID;
        USHORT BorderPen, FillPen;
        struct ListItem *TopItem, *TopDisplayItem, *ActiveItem;
        struct Window *Window;
        struct Gadget *ScrollGadget, *ListGadget,
                      *ClickUpGadget, *ClickDownGadget;
        void (*DrawRoutine)();
        USHORT OldL, OldT, OldW, OldH


    As you probably noticed, there was reference to  a  ListItem  structure.  As
    seen by the list handling routines, the ListItem structure is simply:

    struct ListItem {
        struct ListItem *Next;

    Each item that you present to the list handler must have a  pointer  to  the
    next  item  as  its  first field. You might accomplish this by embedding the
    ListItem structure in your structure declaration. For example:

    struct Bologna {
          struct ListItem listitem;
          int granola;

    Or, you might say

    struct Bologna {
          struct Bologna *next;
          int granola;

    Either way comes out the same. All the list routines need to  know  is  that
    the  first  field points to the next item. The size of the item is no issue,
    since you do the allocating and freeing yourself.

    Using Lists

    You install your list with a call to InitListInfo(); Prior to doing so,  you
    must prepare the following fields in you ListInfo structure:

        LeftEdge  indicates the left boundary of the list box.

         TopEdge  indicates the top boundary of the list box.

           Width  indicates the width of the list box.

          Height  indicates the height of the list box.

      ItemHeight  specifies how tall each item is. This is divided  into  Height
                  to determine how many items are displayed at once.

        ScrollID  This is the GadgetID number you would like the scroll  bar  to
                  have.  A scroll gadget will be created with this number in its
                  GadgetID field. Later, when  your  program  receives  GADGETUP
                  events  with  this  GadgetID,  call  ScrollList  to scroll the

          ListID  This is the GadgetID number for the area comprising  the  list
                  display.  Later,  when  your program receives a GADGETUP event
                  with this GadgetID, this will indicate the user is clicking on
                  an  item in the list, so call GetListItem which will highlight
                  that item and return a pointer to it.

       ClickUpID  Yet another GadgetID number, this is for the arrow  gadget  at
                  the top of the scroll bar, indicating the user wants to scroll
                  the display down one. When you receive a GADGETUP  event  with
                  this id, you call the routine ClickList.

     ClickDownID  The last GadgetID number, this is for the down arrow below the
                  scroll bar. This is also used to call ClickList.

       BorderPen  The pen number for the border of the box  that  surrounds  the

         FillPen  The pen number for the inside of the list box.

         TopItem  If you have a list of items to work with, put the  pointer  to
                  the top one here. If not, this must be NULL.

      TopDisplay  This is a pointer to the first item that should be  displayed.
                  Item  This  might be the top item, or it could be somewhere in
                  the middle of the list. If there is no list, make  this  NULL.
                  When  the  list  is scrolled, this is changed by InovaTools to
                  point to the new top of display.

      ActiveItem  This is the currently highlighted item. If there is none, make
                  it NULL.

          Window  You must provide a pointer to the window this  list  is  being
                  displayed in.

     DrawRoutine  This is a pointer to a routine that  you  provide  to  display
                  information  about  an item. InovaTools will call this routine
                  to display an item in the list box. The  parameters  that  are
                  passed to this routine are:

                  RastPort  The rastport to draw in.

                  Listltem  A pointer to the item to display.

                      XPos  X coordinate for drawing.

                      YPos  Y coordinate for drawing.

                 HighLight  A flag that  is  set  to
                            TRUE  if this is to be highlighted,
                            FALSE if not.
                            How you go about highlighting is up to you.

                  InovaTools draws the list by calling this routine for each  of
                  the  items  that  are  displayed,  giving  each  a different Y
                  coordinate as it runs down the list.

                  Your routine is responsible for clipping. What it draws should
                  not  be  wider  than  the ListInfo Width parameter, nor taller
                  than the ListInfo ItemHeight parameter.

    The remaining parameters should be left alone.

    Having initialised your ListInfo structure, call InitListInfo(ListInfo) just
    after  opening  your  window  and  it  will  install the list in the window,
    allocate the four gadgets, and display the list.

    The list will generate the four gadget events. The ListGadget, ClickUpGadget
    and  ClickDownGadget  should  all be dealt with when they produce GADGETDOWN
    events, while the ScrollGadget should be handled on GADGETUP.

    When the List gadget is clicked, the user is selecting  a  list  item.  Call
    GetListItem  (ListInfo).  It  will  highlight the selected item and return a
    pointer to it.

    When the ClickUp gadget is selected, the user is requesting  that  the  list
    display move up one notch. Call ClickList(ListInfo,ClickUpID) to instruct it
    to move the list up one. ClickList will wait for the user to let up  on  the
    button.   If  that  doesn't  happen  for  a  while,  the  list  will  scroll

    When  the  ClickDown  gadget  is   selected,   call   ClickList   (ListInfo,
    CliekDownID).  When  the  Scroll gadget is selected, the display needs to be
    scrolled to the new position. Call ScrollList(ListInfo)  and  it  will  take
    care  of  it.

    At  some  point,  you  may  wish  to  enter  a  new  item   in   the   list.
    InsertListItem(ListInfo,ListItem) will stick the item in the list just prior
    to the currently selected item.

    If the user wishes to delete the  currently  highlighted  item,  a  call  to
    RemoveListItem(ListInfo) will talke the highlighted item out of the list and
    highlight the one that precedes it. RemoveListItem returns a pointer to  the
    removed item. You must then dispose of the removed item yourself.

    Should you need to redisplay  the  list,  call  SizeList(ListInfo).  If  you
    change  the  list  size  information (in particular, the Height), it will be
    updated appropriately (after erasing the old list..) This is  handy  if  the
    user   sizes  the  window.  On  NEWSIZE  events,  adjust  the  Height  field
    appropriately and call SizeList.

    When you are done and it is time to close the  window,  call  RemoveListInfo
    (ListInfo)   first.   It  will  deallocate  the  four  gadgets.  Then,  call
    CloseWindow to close the window.

    There is a set of list manipulation routines provided in  the  library.  You
    can  use  these to work with your linked lists. Note that these linked lists
    are all singly linked, rather than doubly  linked.  The  Amiga's  Exec  list
    structures are doubly linked.

    The list routines are:

         List_Len Returns the length of the list.

    List_Position Returns the integer position of an item in the list.

        List_Pred Returns the item in the list preceding the given item.

       List_Index Returns the item at the given integer position in the list.

      List_Insert Inserts the item at the given integer position in the list.

      List_Remove Removes the item at the given integer position from the list.

         List_Cat Concatanates two lists into one.

    These routines  fall  under  the  heading  List  Functions  in  the  routine

    Any linked list that puts a pointer to the next item in the first  field  of
    each  structure can use these. For example, Intuition Gadgets have a pointer
    to the next gadget in the NextGadget field which is the first  item  in  the
    Gadget  structure.  So,  you  can  manipulate  your  gadget  list with these