AmiSafe.c - preliminary source code for Amiga OS4.1 reaction

;/* Execute me to compile
gcc -g AmiSafe.c -o AmiSafe -lauto
quit
;*/
/*
 * AmiSafe password enryption for safety
 * Written by Scott A. Cabit November 2011/2012
 *
 */  
//#define DEBUG
 
#include <sys/types.h>  
#include <exec/exec.h>
#include <intuition/intuition.h>
#include <intuition/gui.h>
#include <intuition/icclass.h>
#include <dos/dos.h>
#include <string.h>
#include <images/label.h>
#include <classes/window.h>
#include <classes/requester.h>
#include <stdio.h>
#include <stdlib.h>
#include <gadgets/fuelgauge.h>
#include <gadgets/layout.h>
#include <gadgets/texteditor.h>
#include <gadgets/radiobutton.h>
#include <gadgets/chooser.h>
#include <gadgets/integer.h>
#include <gadgets/clicktab.h>
#include <gadgets/listbrowser.h>
#include <libraries/keymap.h>
 
/*
 * Autoinit takes care of these
 */
#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/intuition.h>
#include <proto/label.h>
#include <proto/listbrowser.h>
 
/*
 * Simply include the proto file for all ReAction classes you intent to use
 * to trigger their autoinitialization.
 */
#include <proto/fuelgauge.h>
#include <proto/window.h>
#include <proto/layout.h>
#include <proto/texteditor.h>
#include <proto/radiobutton.h>
#include <proto/chooser.h>
#include <proto/checkbox.h>
#include <proto/integer.h>
#include <proto/space.h>
#include <proto/clicktab.h>
#include <proto/requester.h>
#include <proto/utility.h>
 
#include <reaction/reaction_macros.h>
 
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
 
Object *win;
Object *lb_gad = NULL;
 
struct MsgPort *AppPort;
struct List listbrowser_list1;
struct ColumnInfo *columninfo1 = NULL;
struct List listbrowser_list2;
struct ColumnInfo *columninfo2 = NULL;
struct List listbrowser_list3;
struct ColumnInfo *columninfo3 = NULL;
struct List listbrowser_list4;
struct ColumnInfo *columninfo4 = NULL;
 
STRPTR PageLabels[] =
{
	"Credit or Bank Cards",
	" Internet Passwords ",
    "  Other Passwords   ",
    " Insurance Policies ",
	NULL
};
 
#define STRSIZE 40
#define MAXENTRIES 100
#define COLSTAB1 5
#define COLSTAB2 3
#define COLSTAB3 2
#define COLSTAB4 3
/*
STATIC BYTE Tab1Data[bufsize];
STATIC BYTE Tab2Data[bufsize];
STATIC BYTE Tab3Data[bufsize];
STATIC BYTE Tab4Data[bufsize];
*/
// Arrays of text data for each tab
STRPTR Tab1Strings[MAXENTRIES];
STRPTR Tab2Strings[MAXENTRIES];
STRPTR Tab3Strings[MAXENTRIES];
STRPTR Tab4Strings[MAXENTRIES];
 
/*
 * This enum generates the unique ID's we need both for
 * GadgetID's as well as for the index into our objects
 * array. You might want to use separate variables (we
 * did so for the window object) or use this method.
 * Note that not all objects need an id, and not all
 * objects need to be stored (Layout groups for example).
 * Essentially only store object pointers that you need
 * to manipulate from your program.
 */
enum
{
	/* -- other controls -- */
	OBJ_CLICKTAB,
    OBJ_LISTBROWSER1,
    OBJ_LISTBROWSER2,
	OBJ_LISTBROWSER3,
	OBJ_LISTBROWSER4,
    OBJ_ADD,
	OBJ_DELETE,
	OBJ_ABOUT,
	OBJ_NUM
};
 
/*
 * This array will hold the objects we create. The two macros
 * below are for convenience.
 */
Object *Objects[OBJ_NUM];
#define OBJ(x) Objects[x]
#define GAD(x) (struct Gadget *)Objects[x]
 
BOOL make_browserlist(struct List *, char ** , int );
 
/* Quite handy */
#define SPACE LAYOUT_AddChild, SpaceObject, End
 
Object *
make_window(void)
{
    columninfo1 = IListBrowser->AllocLBColumnInfo(COLSTAB1,
        LBCIA_Column, 0,
            LBCIA_Title, " Name",
            LBCIA_Width, 40,
            LBCIA_AutoSort, TRUE,
            LBCIA_SortArrow, TRUE,
        LBCIA_Column, 1,
            LBCIA_Title, " Number",
            LBCIA_Width, 20,
            LBCIA_AutoSort, TRUE,
            LBCIA_SortArrow, TRUE,
        LBCIA_Column, 2,
            LBCIA_Title, " Exp Date",
            LBCIA_Width, 8,
            LBCIA_AutoSort, TRUE,
            LBCIA_SortArrow, TRUE,
        LBCIA_Column, 3,
            LBCIA_Title, " PIN",
            LBCIA_Width, 8,
            LBCIA_AutoSort, TRUE,
            LBCIA_SortArrow, TRUE,
        LBCIA_Column, 4,
            LBCIA_Title, " Phone",
            LBCIA_Width, 14,
            LBCIA_AutoSort, TRUE,
            LBCIA_SortArrow, TRUE,
        TAG_DONE);
 
    columninfo2 = IListBrowser->AllocLBColumnInfo(3,
        LBCIA_Column, 0,
            LBCIA_Title, " Title",
            LBCIA_Width, 40,
            LBCIA_AutoSort, TRUE,
            LBCIA_SortArrow, TRUE,
        LBCIA_Column, 1,
            LBCIA_Title, " URL",
            LBCIA_Width, 80,
            LBCIA_AutoSort, TRUE,
            LBCIA_SortArrow, TRUE,
        LBCIA_Column, 2,
            LBCIA_Title, " Password",
            LBCIA_Width, 80,
            LBCIA_AutoSort, TRUE,
            LBCIA_SortArrow, TRUE,
        TAG_DONE);
 
    columninfo3 = IListBrowser->AllocLBColumnInfo(2,
        LBCIA_Column, 0,
            LBCIA_Title, " Item",
            LBCIA_Width, 80,
            LBCIA_AutoSort, TRUE,
            LBCIA_SortArrow, TRUE,
        LBCIA_Column, 1,
            LBCIA_Title, " Password",
            LBCIA_Width, 20,
            LBCIA_AutoSort, TRUE,
            LBCIA_SortArrow, TRUE,
        TAG_DONE);
 
    columninfo4 = IListBrowser->AllocLBColumnInfo(3,
        LBCIA_Column, 0,
            LBCIA_Title, " Company",
            LBCIA_Width, 40,
            LBCIA_AutoSort, TRUE,
            LBCIA_SortArrow, TRUE,
        LBCIA_Column, 1,
            LBCIA_Title, " Policy Number",
            LBCIA_Width, 30,
            LBCIA_AutoSort, TRUE,
            LBCIA_SortArrow, TRUE,
        LBCIA_Column, 2,
            LBCIA_Title, " Phone Number",
            LBCIA_Width, 24,
            LBCIA_AutoSort, TRUE,
            LBCIA_SortArrow, TRUE,
        TAG_DONE);
 
	/*
	 * Page 1: Credit Cards
	 *
	 * Page 2: Internet
     *
     * Page 3: Others
     *
     * Page 4: Insurance Policies
	 */
 
	Object
		*page1 = NULL,
		*page2 = NULL,
        *page3 = NULL,
        *page4 = NULL;
 
	page1 = VLayoutObject,
		LAYOUT_AddChild, HLayoutObject,
			/* BevelStyle sets the style of the group border to BVS_GROUP,
			 * which is the standard group frame. The Label tags gives a
			 * text string to be displayed embedded into the frame.
			 */
			LAYOUT_BevelStyle,  BVS_GROUP,
			LAYOUT_Label,       "Credit or Bank Card Info",
			/* LAYOUT_AddChild adds a new child into the group. Depending
			 * on the layout parameter (horizontal vs. vertical) the
			 * objects are placed next to each other, or stacked one
			 * above the other.
			 */
            LAYOUT_AddChild, OBJ(OBJ_LISTBROWSER1) = IIntuition->NewObject(NULL, "listbrowser.gadget",
                GA_ID,                     OBJ_LISTBROWSER1,
                GA_RelVerify,              TRUE,
                GA_TabCycle,               TRUE,
                LISTBROWSER_AutoFit,       TRUE,
                LISTBROWSER_Labels,        &listbrowser_list1,
                LISTBROWSER_ColumnInfo,    columninfo1,
                LISTBROWSER_ColumnTitles,  TRUE,
                LISTBROWSER_TitleClickable,TRUE,
                LISTBROWSER_ShowSelected,  TRUE,
                LISTBROWSER_Editable,      TRUE,
                LISTBROWSER_Striping,      LBS_ROWS,
            TAG_DONE),
 
 
        End, /* HLayoutObject */
	End; /* VLayoutObject */
 
	page2 = VLayoutObject,
		LAYOUT_AddChild,    HLayoutObject,
			LAYOUT_BevelStyle,  BVS_GROUP,
			LAYOUT_Label,       "Internet Passwords",
            LAYOUT_AddChild, OBJ(OBJ_LISTBROWSER2) = IIntuition->NewObject(NULL, "listbrowser.gadget",
                GA_ID,                     OBJ_LISTBROWSER2,
                GA_RelVerify,              TRUE,
                GA_TabCycle,               TRUE,
                LISTBROWSER_AutoFit,       TRUE,
                LISTBROWSER_Labels,        &listbrowser_list2,
                LISTBROWSER_ColumnInfo,    columninfo2,
                LISTBROWSER_ColumnTitles,  TRUE,
                LISTBROWSER_TitleClickable,TRUE,
                LISTBROWSER_ShowSelected,  TRUE,
                LISTBROWSER_Editable,      TRUE,
                LISTBROWSER_Striping,      LBS_ROWS,
            TAG_DONE),
        End, /* HLayout */
	End; /* VLayout */
 
	page3 = VLayoutObject,
		LAYOUT_AddChild,    HLayoutObject,
			LAYOUT_BevelStyle,  BVS_GROUP,
			LAYOUT_Label,       "Other Passwords",
            LAYOUT_AddChild, OBJ(OBJ_LISTBROWSER3) = IIntuition->NewObject(NULL, "listbrowser.gadget",
                GA_ID,                     OBJ_LISTBROWSER3,
                GA_RelVerify,              TRUE,
                GA_TabCycle,               TRUE,
                LISTBROWSER_AutoFit,       TRUE,
                LISTBROWSER_Labels,        &listbrowser_list3,
                LISTBROWSER_ColumnInfo,    columninfo3,
                LISTBROWSER_ColumnTitles,  TRUE,
                LISTBROWSER_TitleClickable,TRUE,
                LISTBROWSER_ShowSelected,  TRUE,
                LISTBROWSER_Editable,      TRUE,
                LISTBROWSER_Striping,      LBS_ROWS,
            TAG_DONE),
        End, /* HLayout */
	End; /* VLayout */
 
	page4 = VLayoutObject,
		LAYOUT_AddChild,    HLayoutObject,
			LAYOUT_BevelStyle,  BVS_GROUP,
			LAYOUT_Label,       "Insurance Policies",
            LAYOUT_AddChild, OBJ(OBJ_LISTBROWSER4) = IIntuition->NewObject(NULL, "listbrowser.gadget",
                GA_ID,                     OBJ_LISTBROWSER4,
                GA_RelVerify,              TRUE,
                GA_TabCycle,               TRUE,
                LISTBROWSER_AutoFit,       TRUE,
                LISTBROWSER_Labels,        &listbrowser_list4,
                LISTBROWSER_ColumnInfo,    columninfo4,
                LISTBROWSER_ColumnTitles,  TRUE,
                LISTBROWSER_TitleClickable,TRUE,
                LISTBROWSER_ShowSelected,  TRUE,
                LISTBROWSER_Editable,      TRUE,
                LISTBROWSER_Striping,      LBS_ROWS,
            TAG_DONE),
        End, /* HLayout */
	End; /* VLayout */
 
	/*
	 * A clicktab object is a controller for the page object. It's the
	 * register card type gadget along the top of the resultiong dialog.
	 * The GA_Text tag points to the STRPTR array with the labels to
	 * display (plain ascii text in this case), and the pagegroup is
	 * a special case of group that only displays one child at a time.
	 *
	 * This way we can select exactly one of the above pages as a time.
	 */
	OBJ(OBJ_CLICKTAB) = ClickTabObject,
		GA_Text,            PageLabels,
		CLICKTAB_Current,   0,
		CLICKTAB_PageGroup, PageObject,
			PAGE_Add,       page1,
			PAGE_Add,       page2,
		    PAGE_Add,       page3,
		    PAGE_Add,       page4,
        End, /* PageObject */
	End; /* ClickTab */
 
	/*
	 * This will generate our window object. The content of the window
	 * is specified with the WINDOW_ParentGroup. We make this a VLayout
	 * because we want to place our clicktabbed group above a row of
	 * additional buttons (Print, Cancel and Help).
	 */
	return WindowObject,
		WA_Title,               "AmiSafe Password Protection for Amiga OS4",
		WA_DragBar,             TRUE,
		WA_SmartRefresh,        TRUE,
		WA_CloseGadget,         TRUE,
		WA_SizeGadget,          TRUE,
		WA_DepthGadget,         TRUE,
        WA_Activate,            TRUE,
        WA_InnerWidth,          400,
        WA_InnerHeight,         400,
        WA_Opaqueness,          255,    /* Initial opaqueness on opening (0..255) */
        WA_OverrideOpaqueness,  TRUE,   /* Override global settings? (TRUE|FALSE) */
        WA_FadeTime,            500000, /* Duration of transition in microseconds */
        WINDOW_GadgetHelp,      TRUE,
        WINDOW_IconifyGadget,   TRUE,
        WINDOW_IconTitle,       "AmiSafe",
        WINDOW_AppPort,         AppPort,
        WINDOW_Position,        WPOS_CENTERSCREEN,
 
		WINDOW_ParentGroup, VLayoutObject,
			LAYOUT_AddChild, OBJ(OBJ_CLICKTAB),
			/*
			 * This will be special because we want the group to
			 * stay the same size vertically regardless of window size
			 * and rather let the content above (the clicktabbed groups)
			 * expand and take up the space.
			 */
 
			 /* For that we first generate a group with horizontal layout
			 * and add our buttons to it. Specifying LAYOUT_EvenSize will
			 * make all buttons the same size, which looks nicer.
			 */
			LAYOUT_AddChild,        HLayoutObject,
				LAYOUT_BevelStyle,  BVS_SBAR_HORIZ,
				LAYOUT_EvenSize,    TRUE,
				LAYOUT_AddChild,    ButtonObject,
                    GA_HintInfo,    "Select this button to add a new entry",
					GA_ID,          OBJ_ADD,
					GA_Text,        "_Add Entry",
					GA_RelVerify,   TRUE,
				End, /* Button */
				LAYOUT_AddChild,    ButtonObject,
                    GA_HintInfo,    "Select this button to delete the selected entry",
					GA_ID,          OBJ_DELETE,
					GA_Text,        "_Delete Entry",
					GA_RelVerify,   TRUE,
				End, /* Button */
				LAYOUT_AddChild,    ButtonObject,
                    GA_HintInfo,    "Select this button for program information",
					GA_ID,          OBJ_ABOUT,
					GA_Text,        "_Help",
					GA_RelVerify,   TRUE,
				End, /* Button */
			End, /* HLayout */
			CHILD_WeightedHeight,   0,
		End, /* VLayout */
	End; /* WindowObject */
}
 
 
uint32 MessageBoxA(char *gadgets, char *format, APTR args )
{
	Object *requester;
	char buffer[512];
	uint32 result = 0;
 
	memset(buffer, 0, 512);
	IExec->RawDoFmt(format, args, NULL, buffer);
	requester = IIntuition->NewObject(IRequester->REQUESTER_GetClass(), NULL,
		REQ_Type,               REQTYPE_INFO,
		REQ_TitleText,          "Auto Sample",
		REQ_BodyText,           buffer,
		REQ_GadgetText,         gadgets,
	TAG_DONE);
	if (requester)
	{
		result = IIntuition->IDoMethod( requester, RM_OPENREQ, NULL, NULL, NULL );
		IIntuition->DisposeObject(requester);
	}
 
	return result;
}
 
uint32 VARARGS68K MessageBox(char *gadgets, char *format, ...)
{
	va_list  ap;
	LONG     result;
 
	va_startlinear (ap, format);
	result = MessageBoxA(gadgets, format, va_getlinearva(ap,void*) );
	va_end(ap);
	return result;
}
 
 
BOOL WriteBrowserList(struct List *browserlist, u_char columns, FILE *Outfile)
{
struct Node *currentNode;
 
STRPTR Text1;
STRPTR Text2; 
STRPTR Text3;
STRPTR Text4;
STRPTR Text5;
 
char temp[500];
 
        currentNode = IExec->GetHead(browserlist);
 
        while(currentNode != NULL)
           {
		    switch(columns)
            {
            case 2:    
		       IListBrowser->GetListBrowserNodeAttrs(currentNode,
		 	   LBNA_Column, 0,
		 	   LBNCA_Text, &Text1,
		 	   LBNA_Column, 1,
		 	   LBNCA_Text, &Text2,
			   TAG_DONE);
 
               sprintf(temp,"%s\n",Text1);
               fputs(temp,Outfile);
               sprintf(temp,"%s\n",Text2);
               fputs(temp,Outfile);
 
            break;
 
            case 3:
		       IListBrowser->GetListBrowserNodeAttrs(currentNode,
		 	   LBNA_Column, 0,
		 	   LBNCA_Text, &Text1,
		 	   LBNA_Column, 1,
		 	   LBNCA_Text, &Text2,
		 	   LBNA_Column, 2,
		 	   LBNCA_Text, &Text3,
			   TAG_DONE);
 
               sprintf(temp,"%s\n",Text1);
               fputs(temp,Outfile);
               sprintf(temp,"%s\n",Text2);
               fputs(temp,Outfile);
               sprintf(temp,"%s\n",Text3);
               fputs(temp,Outfile);
 
            break;
 
            case 4:
		       IListBrowser->GetListBrowserNodeAttrs(currentNode,
		 	   LBNA_Column, 0,
		 	   LBNCA_Text, &Text1,
		 	   LBNA_Column, 1,
		 	   LBNCA_Text, &Text2,
		 	   LBNA_Column, 2,
		 	   LBNCA_Text, &Text3,
		 	   LBNA_Column, 3,
		 	   LBNCA_Text, &Text4,
			   TAG_DONE);
 
               sprintf(temp,"%s\n",Text1);
               fputs(temp,Outfile);
               sprintf(temp,"%s\n",Text2);
               fputs(temp,Outfile);
               sprintf(temp,"%s\n",Text3);
               fputs(temp,Outfile);
               sprintf(temp,"%s\n",Text4);
               fputs(temp,Outfile);
 
            break;
 
            case 5:
		       IListBrowser->GetListBrowserNodeAttrs(currentNode,
		 	   LBNA_Column, 0,
		 	   LBNCA_Text, &Text1,
		 	   LBNA_Column, 1,
		 	   LBNCA_Text, &Text2,
		 	   LBNA_Column, 2,
		 	   LBNCA_Text, &Text3,
		 	   LBNA_Column, 3,
		 	   LBNCA_Text, &Text4,
		 	   LBNA_Column, 4,
		 	   LBNCA_Text, &Text5,
			   TAG_DONE);
 
               sprintf(temp,"%s\n",Text1);
               fputs(temp,Outfile);
               sprintf(temp,"%s\n",Text2);
               fputs(temp,Outfile);
               sprintf(temp,"%s\n",Text3);
               fputs(temp,Outfile);
               sprintf(temp,"%s\n",Text4);
               fputs(temp,Outfile);
               sprintf(temp,"%s\n",Text5);
               fputs(temp,Outfile);
            break;
 
           default:
                IDOS->Printf(" Invalid number of columns for write!\n");
                return(FALSE);
 
               }  // switch(columns)
	           currentNode = IExec->GetSucc(currentNode);
           }   // while currentNode != NULL  
    return(TRUE);
    }
 
/*  Count the number of nodes (rows) in a browserlist and return it */
u_char CountNodes(struct List *browserlist)
{
struct Node *currentNode;
u_char i=0;
 
    	currentNode = IExec->GetHead(browserlist);
	    while(currentNode != NULL)
           {
	       currentNode = IExec->GetSucc(currentNode);
           i++;
           }
    return i;
    }
 
/* Add a new empty node to a browser list */
BOOL AddNode(struct Window * window, uint32 tabnum)
{
struct Node *node;
struct List *browserlist;
 
int columns;
// Detach the listbrowser list first
switch (tabnum + 1)
{
    case 1:
    IIntuition->SetAttrs(OBJ(OBJ_LISTBROWSER1), 
    LISTBROWSER_Labels, NULL, TAG_DONE);
	columns = COLSTAB1;
    browserlist = (struct List *)&listbrowser_list1;
    break;
 
    case 2:
    IIntuition->SetAttrs(OBJ(OBJ_LISTBROWSER2), 
    LISTBROWSER_Labels, NULL, TAG_DONE);
	columns = COLSTAB2;
    browserlist = (struct List *)&listbrowser_list2;
	break;
 
    case 3:
    IIntuition->SetAttrs(OBJ(OBJ_LISTBROWSER3), 
    LISTBROWSER_Labels, NULL, TAG_DONE);
	columns = COLSTAB3;
    browserlist = (struct List *)&listbrowser_list3;
	break;
 
    case 4:
    IIntuition->SetAttrs(OBJ(OBJ_LISTBROWSER4), 
    LISTBROWSER_Labels, NULL, TAG_DONE);
	columns = COLSTAB4;
    browserlist = (struct List *)&listbrowser_list4;
	break;
 
default:
    IDOS->Printf(" Invalid tab number passed to AddNode()\n");
	return(FALSE);
	break;    
}   // end switch (tabnum)
 
 
    switch (columns)
    {
        case COLSTAB3:
            if (node = IListBrowser->AllocListBrowserNode(columns,
                LBNA_Column, 0,
                LBNCA_Text,     "New data",
                LBNCA_Editable, TRUE,
                LBNCA_CopyText, TRUE,
                LBNCA_MaxChars, 30,
                LBNA_Column,    1,
                LBNCA_Text,     "",
                LBNCA_Editable, TRUE,
                LBNCA_CopyText, TRUE,
                LBNCA_MaxChars, 30,
                (TAG_DONE)))
            {
                IExec->AddTail(browserlist, node);
            }
            else
            {
                IDOS->Printf(" AllocListBrowserNode() failed\n");
                return(FALSE);
            }
            break;
 
        case COLSTAB2:
            if (node = IListBrowser->AllocListBrowserNode(columns,
                LBNA_Column, 0,
                    LBNCA_Text, "New data",
                LBNCA_Editable, TRUE,
                LBNCA_CopyText, TRUE,
                LBNCA_MaxChars, 30,
                LBNA_Column, 1,
                    LBNCA_Text, "",
                LBNCA_Editable, TRUE,
                LBNCA_CopyText, TRUE,
                LBNCA_MaxChars, 30,
                LBNA_Column, 2,
                    LBNCA_Text, "",
                LBNCA_Editable, TRUE,
                LBNCA_CopyText, TRUE,
                LBNCA_MaxChars, 30,
                (TAG_DONE)))
            {
                IExec->AddTail(browserlist, node);
            }
            else
            {
                IDOS->Printf(" AllocListBrowserNode() failed\n");
                return(FALSE);
            }
            break;
 
        case COLSTAB1:
            if (node = IListBrowser->AllocListBrowserNode(columns,
                LBNA_Column, 0,
                    LBNCA_Text, "New data",
                LBNCA_Editable, TRUE,
                LBNCA_CopyText, TRUE,
                LBNCA_MaxChars, 30,
                LBNA_Column, 1,
                    LBNCA_Text, "",
                LBNCA_Editable, TRUE,
                LBNCA_CopyText, TRUE,
                LBNCA_MaxChars, 30,
                LBNA_Column, 2,
                    LBNCA_Text, "",
                LBNCA_Editable, TRUE,
                LBNCA_CopyText, TRUE,
                LBNCA_MaxChars, 30,
                LBNA_Column, 3,
                    LBNCA_Text, "",
                LBNCA_Editable, TRUE,
                LBNCA_CopyText, TRUE,
                LBNCA_MaxChars, 30,
                LBNA_Column, 4,
                    LBNCA_Text, "",
                LBNCA_Editable, TRUE,
                LBNCA_CopyText, TRUE,
                LBNCA_MaxChars, 30,
                (TAG_DONE)))
            {
                IExec->AddTail(browserlist, node);
            }
            else
            {
                IDOS->Printf(" AllocListBrowserNode() failed\n");
                return(FALSE);
            }
 
            break;
 
        default:
                IDOS->Printf(" Invalid number of list fields\n");
                return(FALSE);
        break;
 
    };  // switch(columns)
 
/* Re-attach the listbrowser and force intuition
* to refresh the gadget imagery.
*/
switch (tabnum + 1)
{
    case 1:
			IIntuition->SetGadgetAttrs((struct Gadget *)OBJ(OBJ_LISTBROWSER1), window, NULL,
            LISTBROWSER_Labels, browserlist, TAG_END);
	break;
 
    case 2:
			IIntuition->SetGadgetAttrs((struct Gadget *)OBJ(OBJ_LISTBROWSER2), window, NULL,
            LISTBROWSER_Labels, browserlist, TAG_END);
	break;
 
    case 3:
			IIntuition->SetGadgetAttrs((struct Gadget *)OBJ(OBJ_LISTBROWSER3), window, NULL,
            LISTBROWSER_Labels, browserlist, TAG_END);
	break;
 
    case 4:
			IIntuition->SetGadgetAttrs((struct Gadget *)OBJ(OBJ_LISTBROWSER4), window, NULL,
            LISTBROWSER_Labels, browserlist, TAG_END);
	break;
 
	default:
            IDOS->Printf("Invalid tab number passed to AddNode()\n");
    break; 	    
    }
 
    return(TRUE);
 }
 
 
void LoadFile()
{
FILE *Infile;
u_char length1,length2,length3,length4;
char mystring[100];
BOOL FILEOK = TRUE;
int i,j;
 
      Infile = fopen("AmiSafe.dat", "r");
       if(Infile == 0)
         {
         FILEOK = FALSE;
         }
         else   // read in parameter data
         {
 
// Read Tab #1 Info
         if(!feof(Infile))
            {   
            length1 = fgetc(Infile);
#ifdef DEBUG
            IDOS->Printf("Tab 1 has %lu entries\n",length1);
#endif
            IExec->NewList((struct List *)&listbrowser_list1);
 
            i = 0;
            while(length1 > 0)
            {
                j = COLSTAB1;
                while(j > 0)
                {
                   fgets(mystring, 100, Infile); 
                   if(feof(Infile))
                      {
                      FILEOK = FALSE;    
                      goto CloseFile;
                      } 
                   mystring[strlen(mystring)-1] = 0;  // convert \n to 0
                   strcpy(Tab1Strings[i++], mystring);
                   j--;
                }
                length1--;
            }
            Tab1Strings[i] = 0;   // add tail null
 
#ifdef DEBUG
		    IDOS->Printf("Created First tab data\n");        
#endif
 
            if(!make_browserlist(&listbrowser_list1, (char **)Tab1Strings, COLSTAB1))
              IDOS->Printf("Failed to create browserlist Tab1\n");
            }
            else
            {
		    IDOS->Printf("No Valid File Data for Tab1!\n"); 
            FILEOK = FALSE;
		    goto CloseFile;  
            }
 
// Read Tab #2 Info
         if(!feof(Infile))
            {   
            length2 = fgetc(Infile);
#ifdef DEBUG
            IDOS->Printf("Tab 2 has %lu entries\n",length2);
#endif
            IExec->NewList((struct List *)&listbrowser_list2);
 
            i = 0;
            while(length2 > 0)
            {
                j = COLSTAB2;
                while(j > 0)
                {
                   fgets(mystring, 100, Infile); 
                   if(feof(Infile))
                      {
                      FILEOK = FALSE;    
                      goto CloseFile;
                      } 
                   mystring[strlen(mystring)-1] = 0;  // convert \n to 0
                   strcpy(Tab2Strings[i++], mystring);
                   j--;
                }
                length2--;
            }
            Tab2Strings[i] = 0;   // add tail null
#ifdef DEBUG
		    IDOS->Printf("Created Second tab data\n");        
#endif
            if(!make_browserlist(&listbrowser_list2, (char **)Tab2Strings, COLSTAB2))
              IDOS->Printf("Failed to create browserlist Tab2\n");                            
            }
            else
            {
		    IDOS->Printf("No Valid File Data for Tab2!\n"); 
            FILEOK = FALSE;
		    goto CloseFile;  
            }
 
// Read Tab #3 Info
         if(!feof(Infile))
            {   
            length3 = fgetc(Infile);
#ifdef DEBUG
            IDOS->Printf("Tab 3 has %lu entries\n",length3);
#endif
            IExec->NewList((struct List *)&listbrowser_list3);
 
            i = 0;
            while(length3 > 0)
            {
                j = COLSTAB3;
                while(j > 0)
                {
                   fgets(mystring, 100, Infile); 
                   if(feof(Infile))
                      {
                      FILEOK = FALSE;    
                      goto CloseFile;
                      } 
                   mystring[strlen(mystring)-1] = 0;  // convert \n to 0
                   strcpy(Tab3Strings[i++], mystring);
                   j--;
                }
                length3--;
            }
            Tab3Strings[i] = 0;   // add tail null
#ifdef DEBUG
		    IDOS->Printf("Created Third tab data\n");        
#endif
            if(!make_browserlist(&listbrowser_list3, (char **)Tab3Strings, COLSTAB3))
              IDOS->Printf("Failed to create browserlist Tab3\n");                            
            }
            else
            {
		    IDOS->Printf("No Valid File Data for Tab3!\n"); 
            FILEOK = FALSE;
		    goto CloseFile;  
            }
 
// Read Tab #4 Info
         if(!feof(Infile))
            {   
            length4 = fgetc(Infile);
#ifdef DEBUG
            IDOS->Printf("Tab 4 has %lu entries\n",length4);
#endif
            IExec->NewList((struct List *)&listbrowser_list4);
 
            i = 0;
            while(length4 > 0)
            {
                j = COLSTAB4;
                while(j > 0)
                {
                   fgets(mystring, 100, Infile); 
                   if(feof(Infile))
                      {
                      FILEOK = FALSE;    
                      goto CloseFile;
                      } 
                   mystring[strlen(mystring)-1] = 0;  // convert \n to 0
                   strcpy(Tab4Strings[i++], mystring);
                   j--;
                }
                length4--;
            }
            Tab4Strings[i] = 0;   // add tail null
#ifdef DEBUG
		    IDOS->Printf("Created Fourth tab data\n");        
#endif
            if(!make_browserlist(&listbrowser_list4, (char **)Tab4Strings, COLSTAB4))
              IDOS->Printf("Failed to create browserlist Tab4\n");                            
            }
            else
            {
		    IDOS->Printf("No Valid File Data for Tab4!\n"); 
            FILEOK = FALSE;
		    goto CloseFile;  
            }
         }
 
CloseFile:
            fclose(Infile);
 
            if(FILEOK == FALSE)
            {
                MessageBox("Continue","Unable to find a valid AmiSafe.dat input file.\n"\
                           "Creating an empty file.");
//	 create an empty group of tabs here         
	            IExec->NewList((struct List *)&listbrowser_list1);
	            IExec->NewList((struct List *)&listbrowser_list2);
	            IExec->NewList((struct List *)&listbrowser_list3);
	            IExec->NewList((struct List *)&listbrowser_list4);
	            Tab1Strings[0] = 0;   // add tail null
	            Tab2Strings[0] = 0;   // add tail null
	            Tab3Strings[0] = 0;   // add tail null
	            Tab4Strings[0] = 0;   // add tail null
	            if(!make_browserlist(&listbrowser_list1, (char **)Tab1Strings, COLSTAB1))
	              IDOS->Printf("Failed to create browserlist Tab1\n");
	            if(!make_browserlist(&listbrowser_list2, (char **)Tab2Strings, COLSTAB2))
	              IDOS->Printf("Failed to create browserlist Tab2\n");                            
	            if(!make_browserlist(&listbrowser_list3, (char **)Tab3Strings, COLSTAB3))
	              IDOS->Printf("Failed to create browserlist Tab3\n");                            
	            if(!make_browserlist(&listbrowser_list4, (char **)Tab4Strings, COLSTAB4))
	              IDOS->Printf("Failed to create browserlist Tab4\n");                            
	         }
}
 
 
void SaveFile(STRPTR sfile)
{
FILE *Outfile;
u_char length1,length2,length3,length4;
 
      Outfile = fopen(sfile, "w");
       if(Outfile == 0)
         {
             MessageBox("UhOh!","Unable to open AmiSafe output file!\n"\
                        "Check to see if the file is write protected please!");
         }
             else   // write out Amisafe data
         {
 
        // count number of rows in each Listbrowser and save it for later
       length1 = CountNodes(&listbrowser_list1);
       length2 = CountNodes(&listbrowser_list2);
       length3 = CountNodes(&listbrowser_list3);
       length4 = CountNodes(&listbrowser_list4);
 
#ifdef DEBUG
       IDOS->Printf("Number of nodes in tabs = %lu %lu %lu %lu\n",length1,length2,length3,length4);
#endif
         // Write row numbers then string data for each tab
         fputc(length1, Outfile);
         WriteBrowserList(&listbrowser_list1, COLSTAB1, Outfile);
 
         fputc(length2, Outfile);
         WriteBrowserList(&listbrowser_list2, COLSTAB2, Outfile);
 
         fputc(length3, Outfile);
         WriteBrowserList(&listbrowser_list3, COLSTAB3, Outfile);
 
         fputc(length4, Outfile);
         WriteBrowserList(&listbrowser_list4, COLSTAB4, Outfile);
 
         fclose(Outfile);
         }    // unable to open output file!
}
 
 
int
main()
{
//	Object *winobj;
	struct Window *window = NULL;
    uint32  fade_time   = 50000;
    uint32  current_tab;
    uint32  activenode = 0;
    int i;
 
    /* make sure our classes opened... */
 
    if (!IntegerBase || !WindowBase || !LayoutBase || !IntuitionBase)
        return (30);
 
 
    if (( AppPort = IExec->CreateMsgPort() ))
    {
        // Allocate Space for Strings + 1 for nul for all tabs
        for(i = 0; i < MAXENTRIES; i++)
        {
            Tab1Strings[i] = malloc((STRSIZE + 1)*sizeof(char));
            Tab2Strings[i] = malloc((STRSIZE + 1)*sizeof(char));
            Tab3Strings[i] = malloc((STRSIZE + 1)*sizeof(char));
            Tab4Strings[i] = malloc((STRSIZE + 1)*sizeof(char));        
            }         
 
        LoadFile();   // create browser lists from file input
        {
 
	win = make_window();
 
	window = RA_OpenWindow(win);
	if (window)
	{
		uint32
			sigmask     = 0,
			siggot      = 0,
			result      = 0,
			code        = 0;
 
		BOOL
			done        = FALSE;
 
 
    	IIntuition->GetAttr(WINDOW_SigMask, win, &sigmask);
 
		while (!done)
		{
			siggot = IExec->Wait(sigmask | SIGBREAKF_CTRL_C);
			if (siggot & SIGBREAKF_CTRL_C) done = TRUE;
 
			while ((result = RA_HandleInput(win, &code)))
			{
				switch(result & WMHI_CLASSMASK)
				{
					case WMHI_CLOSEWINDOW:
						done = TRUE;
						break;
 
                    case WMHI_ICONIFY:
                           IIntuition->SetAttrs( win, WA_FadeTime, fade_time , TAG_END );
                           if (RA_Iconify(win)) window = NULL;
                        break;
 
                    case WMHI_UNICONIFY:
                           window = RA_OpenWindow(win);
                           IIntuition->SetAttrs( win, WA_FadeTime, fade_time , TAG_END );
                        break;
 
					case WMHI_GADGETUP:
 
						switch (result & WMHI_GADGETMASK)
						{
							case OBJ_ADD:
//								MessageBox("OK", 
//									"Adding new Entry\n");
                                IIntuition->GetAttr(CLICKTAB_Current,OBJ(OBJ_CLICKTAB), &current_tab); 
                                if(AddNode(window, current_tab))
                                {
                                    }
                                    else
                                    {
                                    IDOS->Printf(" Unable to add listbrowser node!\n");
                                        }                                 
								break;
 
                            case OBJ_DELETE:
								MessageBox("Delete",
								    "Delete Selected Entry?\n");
                                // display tab and row here
                                IIntuition->GetAttr(CLICKTAB_Current,OBJ(OBJ_CLICKTAB), &current_tab); 
                                IIntuition->GetAttrs( OBJ(current_tab + 1), LISTBROWSER_SelectedNode, (uint32 *)&activenode, TAG_DONE);
#ifdef DEBUG
				if (activenode) {
			    	IDOS->Printf("Node = %ld\n",activenode);    /* got selected node */
				} else {
			   		IDOS->Printf("No node is selected!\n");    /* no node selected */
				}
				IDOS->Printf(" Current Tab = %ld\n", current_tab);
#endif
								// remove node, free it and update display
								IIntuition->DoGadgetMethod((struct Gadget *)OBJ(current_tab + 1), window, NULL, LBM_REMNODE, NULL, activenode);
                                break;
 
                            case OBJ_ABOUT:
                                SaveFile("AmiSafe.dat");
								MessageBox("OK",
									"AmiSafe stores all your passwords in an encrypted file.\n" \
									"Only the proper password can unlock your encrypted data!\n" \
									"If you are seeing garbage, you have not entered the correct password!");
							    break;
						}
						break;
 
				} // switch
			}  // while result
		}    // while !done
      }     // if window
	    IIntuition->DisposeObject(win);
	}     // if make_broswerlist
 
        IListBrowser->FreeListBrowserList(&listbrowser_list1);
        IListBrowser->FreeLBColumnInfo(columninfo1);
        IListBrowser->FreeListBrowserList(&listbrowser_list2);
        IListBrowser->FreeLBColumnInfo(columninfo2);
        IListBrowser->FreeListBrowserList(&listbrowser_list3);
        IListBrowser->FreeLBColumnInfo(columninfo3);
        IListBrowser->FreeListBrowserList(&listbrowser_list4);
        IListBrowser->FreeLBColumnInfo(columninfo4);
        IExec->DeleteMsgPort(AppPort);
 
        // Free reserved space for strings for all tabs
        for(i = 0; i < MAXENTRIES; i++)
        {
            free(Tab1Strings[i]);
            free(Tab2Strings[i]);
            free(Tab3Strings[i]);
            free(Tab4Strings[i]);
            }         
 
    } // if AppPort
 
	return 0;
}
 
 
BOOL make_browserlist(struct List *list, char **tagstring, int columns)
{
    struct Node *node;
 
    IExec->NewList(list);
 
    switch (columns)
    {
        case 2:
        while (*tagstring)
        {
            if (node = IListBrowser->AllocListBrowserNode(columns,
                LBNA_Column, 0,
                LBNCA_Text,     *tagstring++,
                LBNCA_Editable, TRUE,
                LBNCA_CopyText, TRUE,
                LBNCA_MaxChars, 30,
                LBNA_Column,    1,
                LBNCA_Text,     *tagstring++,
                LBNCA_Editable, TRUE,
                LBNCA_CopyText, TRUE,
                LBNCA_MaxChars, 30,
                (TAG_DONE)))
            {
                IExec->AddTail(list, node);
            }
            else
            {
                IDOS->Printf(" AllocListBrowserNode() failed\n");
                return(FALSE);
            }
       }
 
        case 3:
        while (*tagstring)
        {
            if (node = IListBrowser->AllocListBrowserNode(columns,
                LBNA_Column, 0,
                    LBNCA_Text, *tagstring++,
                LBNCA_Editable, TRUE,
                LBNCA_CopyText, TRUE,
                LBNCA_MaxChars, 30,
                LBNA_Column, 1,
                    LBNCA_Text, *tagstring++,
                LBNCA_Editable, TRUE,
                LBNCA_CopyText, TRUE,
                LBNCA_MaxChars, 30,
                LBNA_Column, 2,
                    LBNCA_Text, *tagstring++,
                LBNCA_Editable, TRUE,
                LBNCA_CopyText, TRUE,
                LBNCA_MaxChars, 30,
                (TAG_DONE)))
            {
                IExec->AddTail(list, node);
            }
            else
            {
                IDOS->Printf(" AllocListBrowserNode() failed\n");
                return(FALSE);
            }
       }
 
        case 5:
        while (*tagstring)
        {
            if (node = IListBrowser->AllocListBrowserNode(columns,
                LBNA_Column, 0,
                    LBNCA_Text, *tagstring++,
                LBNCA_Editable, TRUE,
                LBNCA_CopyText, TRUE,
                LBNCA_MaxChars, 30,
                LBNA_Column, 1,
                    LBNCA_Text, *tagstring++,
                LBNCA_Editable, TRUE,
                LBNCA_CopyText, TRUE,
                LBNCA_MaxChars, 30,
                LBNA_Column, 2,
                    LBNCA_Text, *tagstring++,
                LBNCA_Editable, TRUE,
                LBNCA_CopyText, TRUE,
                LBNCA_MaxChars, 30,
                LBNA_Column, 3,
                    LBNCA_Text, *tagstring++,
                LBNCA_Editable, TRUE,
                LBNCA_CopyText, TRUE,
                LBNCA_MaxChars, 30,
                LBNA_Column, 4,
                    LBNCA_Text, *tagstring++,
                LBNCA_Editable, TRUE,
                LBNCA_CopyText, TRUE,
                LBNCA_MaxChars, 30,
                (TAG_DONE)))
            {
                IExec->AddTail(list, node);
            }
            else
            {
                IDOS->Printf(" AllocListBrowserNode() failed\n");
                return(FALSE);
            }
       }
 
            break;
 
        default:
                IDOS->Printf(" Invalid number of list fields\n");
                return(FALSE);
 
    };  // switch
 
   return(TRUE);
}