    // ------------------------------- //
    // -------- Start of File -------- //
    // ------------------------------- //
    // ----------------------------------------------------------- //
    // C++ Source Code File Name: testprog.cpp
    // Compiler Used: MSVC, BCC32, GCC, HPUX aCC, SOLARIS CC
    // Produced By: glNET Software
    // File Creation Date: 04/05/1996
    // Date Last Modified: 05/25/2001
    // Copyright (c) 2001 glNET Software
    // ----------------------------------------------------------- //
    // ------------- Program Description and Details ------------- //
    // ----------------------------------------------------------- //
    /*
    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
    USA

    Doubly linked list class test program.
    */
    // ----------------------------------------------------------- //
    #include <iostream.h>
    #include <string.h>
    #include "gxlistb.h"

    #ifdef __MSVC_DEBUG__
    #include "leaktest.h"
    #endif

    void PausePrg()
    {
      // PausePrg the program until enter is pressed
      cout << endl;
      cout << "Press Enter to continue...\n";
      cin.get();
    }

    void ScrollForward(gxListB &list)
    {
      cout << "Walking through the list..." << endl;
      gxListNodeB *ptr = list.GetHead();
      while(ptr) {
        int val = (int)ptr->data;
        cout << (char)val << ' ';
        ptr = ptr->next;
      }
      cout << endl;
    }

    void RewindList(gxListB &list)
    {
      cout << "Walking through the list in a backward direction..." << endl;
      gxListNodeB *ptr = list.GetTail();

      // Walk through the list in a backward direction
      while(ptr) {
        int val = (int)ptr->data;
        cout << (char)val << ' ';
        ptr = ptr->prev;
      }

      cout << endl;
    }

    int main()
    {
    #ifdef __MSVC_DEBUG__
      InitLeakTest();
    #endif

      gxListB list;
      gxListNodeB *ptr;

      // Consturct some list nodes
      cout << "Loading data elements into linked list..." << endl;
      gxListNodeB *na = new gxListNodeB;
      gxListNodeB *nb = new gxListNodeB;
      gxListNodeB *nc = new gxListNodeB;
      gxListNodeB *nd = new gxListNodeB;
      gxListNodeB *n1 = new gxListNodeB;
      gxListNodeB *n2 = new gxListNodeB;
      gxListNodeB *n3 = new gxListNodeB;
      gxListNodeB *n4 = new gxListNodeB;

      // Statically allocated list data
      const unsigned num_blocks = 9;
      char buf[num_blocks];
      unsigned i;

      // Load some values into the buffer starting with ASCII character 'A'
      for(i = 0; i < num_blocks; i++) buf[i] = (char)(65+i);

      na->data = (void *)buf[0];
      nb->data = (void *)buf[1];
      nc->data = (void *)buf[2];
      nd->data = (void *)buf[3];

      // Load some list elements
      list.InsertAfter(list.GetHead(), na);
      list.InsertAfter(na, nb);
      list.InsertAfter(nb, nc);
      list.InsertAfter(nc, nd);

      n1->data = (void *)buf[4];
      n2->data = (void *)buf[5];
      n3->data = (void *)buf[6];
      n4->data = (void *)buf[7];

      // Testing insert functions
      list.InsertBefore(na, n1);
      list.InsertBefore(nc, n2);
      list.InsertAfter(nb, n3);
      list.InsertAfter(nd, n4);

      // Reordering the list
      list.MoveToBack(na);
      list.MoveAfter(na, nc);
      list.MoveBefore(nc, nb);
      list.MoveAfter(nc, nd);
      list.MoveAfter(nd, n2);
      list.MoveBefore(n2, n1);
      list.MoveAfter(n2, n3);
      list.MoveAfter(n3, n4);

      ScrollForward(list);
      RewindList(list);

      PausePrg();

      cout << "Adding another item to the list..." << endl;
      ptr = list.Add((void *)buf[8]);
      ScrollForward(list);

      PausePrg();

      cout << "Moving list item to the front of the list" << endl;
      list.MoveToFront(ptr);
      ScrollForward(list);

      cout << "Moving item to the back of the list..." << endl;
      list.MoveToBack(ptr);
      ScrollForward(list);

      PausePrg();

      cout << "Removing the head of the list..." << endl;
      ptr = list.GetHead();
      list.Remove(ptr);
      ScrollForward(list);

      cout << "Removing the tail of the list..." << endl;
      ptr = list.GetTail();
      list.Remove(ptr);
      ScrollForward(list);

      // NOTE: A gxListB::ClearList() call is used here to free the memory
      // allocated for the node since the node data was statically allocated.
      list.ClearList();

      PausePrg();
      cout << "Testing for memory leaks..." << endl;
      const char *test_str = "The quick brown fox jumps over the lazy dog";
      unsigned len = strlen(test_str);
      const unsigned num_to_allocate = 10 * 100; // 1000 * 1000;
      const unsigned mem_bufs = (sizeof(gxListNodeB) + len) * num_to_allocate;
      cout << "Allocating " << mem_bufs << " bytes..." << endl;

      unsigned count1 = 0;
      unsigned count2 = 0;
      for(i = 0; i < num_to_allocate; i++) {
        char *sbuf = new char[len+1]; // Allocate memory for the string
        count1 += sizeof(sbuf);
        if(!sbuf) {
          cout << "Memory allocation error at " << (count1+count2) << " bytes"
    	   << endl;
          break;
        }
        memmove(sbuf, test_str, len);
        sbuf[len] = 0; // Null terminate the string
        count2 += sizeof(gxListNodeB);
        if(!list.Add((void *)sbuf))  {
          cout << "Memory allocation error at " << (count1+count2) << " bytes"
    	   << endl;
          break;
        }
      }
      cout << "Done" << endl;
      PausePrg();

      cout << "Releasing memory allocated back to the heap..." << endl;
      // NOTE: A gxListB::DestroyList() call will free the memory allocated for
      // both the node and its data.
      list.DestroyList();
      PausePrg();

      cout << "Exiting..." << endl;
      cout << endl;
      return 0;
    }
    // ----------------------------------------------------------- //
    // ------------------------------- //
    // --------- End of File --------- //
    // ------------------------------- //