/****************************************************************/
/*   Name: Factor                                               */
/* Author: Brian Hosty                                          */
/*   Desc: A simple program that returns the factors of a value */
/*         --- Now with GUI!!                                   */
/*   Date: 20-12-96                                             */
/*   $ver: 0.52                                                 */
/*                                                              */
/*  Compile under SAS/C with "sc math standard link factor.c"   */
/*                                                              */
/****************************************************************/


#include <stdio.h>
#include <stdlib.h>
#include <math.h>

/* MUI */
#include <libraries/mui.h>

/* System */
#include <dos/dos.h>
#include <graphics/gfxmacros.h>
#include <workbench/workbench.h>

/* Prototypes */
#include <clib/alib_protos.h>
#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#include <clib/graphics_protos.h>
#include <clib/intuition_protos.h>
#include <clib/gadtools_protos.h>
#include <clib/utility_protos.h>
#include <clib/muimaster_protos.h>

#include <pragmas/dos_pragmas.h>
#include <pragmas/graphics_pragmas.h>
#include <pragmas/intuition_pragmas.h>
#include <pragmas/gadtools_pragmas.h>
#include <pragmas/utility_pragmas.h>
#include <pragmas/muimaster_pragmas.h>

#define TEMPLATE "NUMBER/N"

#define MAKE_ID(a,b,c,d) ((ULONG) (a)<<24 | (ULONG) (b)<<16 | (ULONG) (c)<<8 | (ULONG) (d))

extern struct Library *SysBase,*IntuitionBase,*UtilityBase,*GfxBase,*DOSBase,*IconBase;
struct Library *MUIMasterBase;

BOOL running = TRUE;
BOOL addedmisc = FALSE; 

int CXBRK(void) { return(0); }
int _CXBRK(void) { return(0); }

void chkabort(void) {}

LONG __stack = 8192;

static const char IN_Text[] = "cWelcome to Factor\nc2.1!\n\ncEnter a number";
static Object * LV_Results;

void BuildGui(void);

/*************************/
/* Init & Fail Functions */
/*************************/

static VOID fail(APTR app,char *str)
{
	if (app)
		MUI_DisposeObject(app);
	if (MUIMasterBase)
		CloseLibrary(MUIMasterBase);
	if (str)
	{
		puts(str);
		exit(20);
	}
	exit(0);
}

static VOID init(VOID)
{
	if (!(MUIMasterBase = OpenLibrary(MUIMASTER_NAME,MUIMASTER_VMIN)))
		fail(NULL,"Failed to open "MUIMASTER_NAME".");
}

int main(void)
{
	struct RDArgs *rdargs;

	int input, i, nr_pairs=0, sqinput, opts[]={0,0};

	if(rdargs=ReadArgs(TEMPLATE,(long *)opts,NULL)){
		if(opts[0]){
			input=*((int *)(opts[0]));
			printf("The following numbers are factors:\n");
			sqinput = sqrt(input);
			for(i=1;i<=sqinput;i++){
				if(input % i == 0){
					printf("%d \t%d\n", i, input / i);
					nr_pairs++;
				}
			}
			if(nr_pairs == 1){
				printf("%d is a prime number!\n", input);
			} else {
				printf("(%d pairs)\n", nr_pairs);
			}
			if((i-1)*(i-1)==input){printf("%d is a square number!\n", input);}
			printf("\n");	
		}
		else
			BuildGui();
		FreeArgs(rdargs);
	}
}

enum { MEN_PROJECT=1,MEN_ABOUT,MEN_QUIT,GO_DOIT,MEN_FILE,MEN_SAVE,MEN_SETTINGS,MEN_MUISETTINGS };

static struct NewMenu MenuData1[] =
{
	{ NM_TITLE, "Project"                  , 0 ,0 ,0             ,(APTR)MEN_PROJECT  },
	{ NM_ITEM ,  "About"                   ,"?",0 ,0             ,(APTR)MEN_ABOUT    },
	{ NM_ITEM ,  NM_BARLABEL               , 0 ,0 ,0             ,(APTR)0            },
	{ NM_ITEM ,  "Quit"                    ,"Q",0 ,0             ,(APTR)MEN_QUIT     },

	{ NM_TITLE, "File"                     , 0 ,0 ,0             ,(APTR)MEN_FILE     },
	{ NM_ITEM , "Save list to file"        , "S" ,0 ,0           ,(APTR)MEN_SAVE     },

	{ NM_TITLE, "Settings"                 , 0 ,0 ,0             ,(APTR)MEN_SETTINGS },
	{ NM_ITEM , "MUI..."                   , "M" ,0 ,0           ,(APTR)MEN_MUISETTINGS },

	{ NM_END,NULL,0,0,0,(APTR)0 },
};

/***********************/
/* Create and show GUI */
/***********************/

void BuildGui(void)
{
	int input, sqinput, i, nr_pairs;
	LONG t;
	ULONG signals;
	APTR app,window,btgo,strip,innumber,TX_Info, pop1;
	char *buffer, *current_vals="", *buffer2;
	FILE *tempfile;
	struct CurrentPair *cur_pair;

	init();

	app = ApplicationObject,
		MUIA_Application_Title      , "Factor",
		MUIA_Application_Version    , "$VER: Factor 2.1 (13.12.96)",
		MUIA_Application_Copyright  , "©1996, Brian Hosty",
		MUIA_Application_Author     , "Brian Hosty",
		MUIA_Application_Description, "Factor util window",
		MUIA_Application_Base       , "Factor",

		SubWindow, window = WindowObject,
			MUIA_Window_Title    , "Factor 2.1",
			MUIA_Window_ID       , MAKE_ID('T','E','S','T'),
			MUIA_Window_Menustrip, strip = MUI_MakeObject(MUIO_MenustripNM,MenuData1,0),
			MUIA_Window_Width , MUIV_Window_Width_Screen(30),
			MUIA_Window_Height, MUIV_Window_Height_Screen(30),

			WindowContents, VGroup,

				Child, HGroup,
					Child, Label1("Number:"),
					Child, innumber = StringObject,
						StringFrame,
						MUIA_String_MaxLen, 11,
						MUIA_String_Accept, "0123456789",
					End,
				End,				
				Child, HGroup,
					Child, btgo = MUI_MakeObject(MUIO_Button,"Do it!!"),
				End,
				Child, HGroup, GroupFrameT("List of factors"),
					Child, LV_Results = ListviewObject,
						MUIA_Listview_List, FloattextObject, ReadListFrame,
							MUIA_Floattext_Text, IN_Text,
						End,
					End,
				End,
				Child, TX_Info = TextObject,
					TextFrame,
					MUIA_Background, MUII_TextBack,
					MUIA_Text_Contents, "\33cand click Do it!!",
				End,
				Child, HGroup, 
					Child, Label2("Save to:"),
					Child, pop1 = PopaslObject,
						MUIA_Popstring_String, KeyString(0,256,'f'),
						MUIA_Popstring_Button, PopButton(MUII_PopFile),
					End,
				End,
			End,
		End,
	End;

	DoMethod(btgo,MUIM_Notify,MUIA_Pressed,FALSE,app,2,MUIM_Application_ReturnID,GO_DOIT);
	DoMethod(window,MUIM_Notify,MUIA_Window_CloseRequest,TRUE,app,2,MUIM_Application_ReturnID,MUIV_Application_ReturnID_Quit);
	DoMethod(innumber,MUIM_Notify,MUIA_String_Acknowledge,MUIV_EveryTime,app,2,MUIM_Application_ReturnID,GO_DOIT); /* If user presses RETURN in the string box, pass GO_DOIT to switch*/

	/* Input Loop */

	set(window,MUIA_Window_Open,TRUE);

	while (running)
	{
		ULONG id = DoMethod(app,MUIM_Application_Input,&signals);

		switch (id)
		{
			case MEN_QUIT:
			case MUIV_Application_ReturnID_Quit:
				running = FALSE;
				break;

			case MEN_ABOUT:
				MUI_Request(app,window,0,NULL,"OK","cbFactor 2.1\ncn By Brian Hosty\n\nc http://www.chucki.demon.co.uk/\n\nc b.t.hosty@sees.bangor.ac.uk\n\ncMUI is copyright by Stefan Stuntz.");
				break;

			case GO_DOIT:
				nr_pairs = 0;
				DoMethod(LV_Results,MUIM_List_Clear);
				get(innumber,MUIA_String_Contents,&buffer);
				input = atoi(buffer);
				if(input < 2 || input > 2147483647){
					DoMethod(TX_Info, MUIM_SetAsString, MUIA_Text_Contents,"Enter a (valid) number!");
					break;
				}
				sqinput = sqrt(input);
				for(i=1;i<=sqinput;i++){
					if(input % i == 0){
						sprintf(current_vals, "%ld   (%ld)", i, input / i);
						DoMethod(LV_Results,MUIM_List_InsertSingle,current_vals,MUIV_List_Insert_Bottom);
						nr_pairs++;
					}
				}
				if(nr_pairs==1)
					DoMethod(TX_Info, MUIM_SetAsString, MUIA_Text_Contents,"c%ld is a bprimen number!", input);				
				else
					DoMethod(TX_Info, MUIM_SetAsString, MUIA_Text_Contents,"%ld Pairs ", nr_pairs);
				if((i-1)*(i-1) == input)
					DoMethod(TX_Info, MUIM_SetAsString, MUIA_Text_Contents,"%ld Pairs (bSquaren Number)", nr_pairs);
				break;

			case MEN_SAVE:
				get(pop1,MUIA_String_Contents,&buffer2);
				if ((tempfile = fopen(buffer2, "w")) == NULL){
					DoMethod(TX_Info, MUIM_SetAsString, MUIA_Text_Contents,"Error writing to file");
					break;
				}
				fprintf(tempfile, "The following are factors of %d:\n\n", input);
				for (t=0;t<nr_pairs;t++){
					DoMethod(LV_Results,MUIM_List_GetEntry,t,&cur_pair);
					fprintf(tempfile, "%s\n",cur_pair);
				}
				fprintf(tempfile, "\n(%d pairs)", nr_pairs);
				fclose(tempfile);
				break;

			case MEN_MUISETTINGS:
				DoMethod(app,MUIM_Application_OpenConfigWindow,0);
				break;

		}
		if (running && signals) Wait(signals);
	}

	set(window,MUIA_Window_Open,FALSE);

	if (!app)
		fail(app,"Failed to create Application.");

	/* Shut down */

	fail(app,NULL);
}