implementation module EdOptionsMenu1;

/*	The commands of the Options menu */

import	StdInt, StdString, StdBool, StdChar, StdClass,StdArray,StdReal;
import	deltaEventIO, deltaWindow, deltaDialog, deltaControls, deltaFont;
import	EdProgramState, EdProject, EdDialogs, EdWindows, EdDraw, EdSupport, EdFiles,
		EdPath, EdLists, EdProjectUtils, EdMyIO, EdMenuItems;
import  EdCleanSystem;
// RWS -> Rbrt import
import	StdList;
import UtilSequence;

// cons
(:+) infixr 0;
(:+) h t
	:==	[h : t];

// conditional cons
(:?) infixr 0;
(:?) ch t
	:== (\(c,h) t -> if c [h : t] t) ch t;

(InsertIfMacintoshSystem) infixr 0;
(InsertIfMacintoshSystem) h t
	:== IfMacintoshSystem [h:t] t;

(InsertIfNotUnixSystem) infixr 0;
(InsertIfNotUnixSystem) h t
	:== IfUnixSystem t [h:t];

/* Compiler Options Dialog */
	PSCTitleID	:== 10;
	PModID		:== 20;
		RTMoID	:== 21;
		RNMoID	:== 22;
	PSAnaID		:== 30;
	PSDiagID	:== 40;
	PAnaID		:== 50;
	BCompileNeverMemoryProfileID :== 51;
	BCompileNeverTimeProfileID	:== 52;
		BStrID	:== 53;
	PDiagID		:== 60;
		BWarID	:== 61;
		BVerID	:== 62;
	PTypID		:== 70;
		RNonID	:== 71;
		RInfID	:== 72;
		RSETID	:== 73;
		RAllID	:== 74;
	PAttrID		:== 8;
		BAttrID	:== 81;
	PCGID		:== 90;
	PGenID		:== 100;
		BGenID	:== 101;
		BReuseUniqueNodesID :== 102;
	PCancCID	:== 110;
	POKCID		:== 111;
	PSListTypesCaptionID :== 120;

/* Code Generator Options Dialog */
	PSCGTitleID	:== 200;
	PCGOID		:== 210;		
		RTCGID	:== 211;
		RNCGID	:== 212;
	PSOptID		:== 220;
	PSProcID	:== 230;
	POptID		:== 240;
		BChkSID	:== 241;
		BChkIID	:== 242;
		BKpID	:== 243;
	PProcID		:== 250;
		RCurID	:== 251;
		R000ID	:== 252;
		R020ID	:== 253;
		R881ID	:== 254;
	PProfileCheckBoxesID	:== 240;
		BProfileID			:== 241;
		BProfile601ID		:== 242;
	PCancCGID	:== 260;
	POKCGID		:== 270;

	
/* Application Options Dialog */
	PSATitleID	:== 300;
	PAppID		:== 310;		
 		RTAppID	:== 311;
		RNAppID	:== 312;
// RWS app options		RNAppID	:== RTAppID;
	PSConfID	:== 320;
	PSInfoID	:== 330;
	PSHSizeID	:== 340;
	PSSSizeID	:== 350;
	PSEMemID	:== 360;
	PSENextHeapSizeFactorID:==361;
	PSEInitialHeapSizeID:==362;
	PSEMemoryProfileMinimumHeapSizeID:==363;
	PHSizeID	:== 370;
	PSSizeID	:== 380;
	PEMemID		:== 390;	
	PNextHeapSizeFactorID:==391;
	PInitialHeapSizeID:==392;
	PMemoryProfileMinimumHeapSizeID:==393;
	PInfoID		:== 400;		
		BShwEID	:== 401;
		BShwGID	:== 402;
		BPrtSID	:== 403;
		BWriteStderrToFileID :== 408;
	PSOutpID	:== 410;
	POutpID		:== 420;
		RBscVID	:== 421;
		RShwCID	:== 422;
		RNoCnID	:== 423;
	PCancAID	:== 440;
	POKAID		:== 450;	
	PFntID		:== 460;
	PTimeProfileID	:== 470;
// RWS app options
		BProfilingID:==471;
// RWS app options
		BProfiling601ID:==472;
	PMemoryProfileID	:== 480;
		BMemoryProfilingID:==481;
	PMarkingCollectionID
					:== 490;
		BMarkingCollectionID:==491;
	PSProfileID :== 580;

/* Font Subdialog */
	PSFontID	:== 510;
	PFontID		:== 520;
	PSFSizeID	:== 530;
	PFSizeID	:== 540;
	PFoxID		:== 550;
	PCancFID	:== 560;
	POKFID		:== 570;

//
// Device function for the Clean Compiler Command
//

CCompiler :: !ProgState !IO -> ProgIO;
CCompiler prog io
	=  OpenModalDialog dialog prog` io;
	where {
	dialog= CommandDialog DCompOptionsID "Concurrent Clean Compiler Options" [] POKCID
						  [
							title,
							moduleRadioButtons,
							programAnalysisCaption, programAnalysisCheckBoxes,
							diagnosticsCaption, diagnosticsCheckBoxes,
							codeGenerationCaption, codeGenerationCheckBoxes,
							listTypesCaptions, listTypesCheckBoxes, listTypesShowAttributes,
							buttonCancel, buttonOK
						];

	title	= StaticText PSCTitleID Center "Concurrent Clean Compiler Options";
	moduleRadioButtons
		= RadioButtons PModID Left (Rows 1) thisornew [
			RadioItem RTMoID "This Module"			thisenabled		(SetCompiler RTMoID RNMoID winopt),
			RadioItem RNMoID "New Module"			Able			(SetCompiler RNMoID RTMoID defopt) ];

	programAnalysisCaption	= StaticText PSAnaID Left "Program Analysis";
	programAnalysisCheckBoxes	= CheckBoxes PAnaID (Below PSAnaID) (Columns 1) [
			CheckBox BStrID	"Strictness Analyzer"	Able 	mstrict	DFIdle ];

	diagnosticsCaption	= StaticText PSDiagID (XOffset PSAnaID (MM 25.0)) "Diagnostics";
	diagnosticsCheckBoxes = CheckBoxes PDiagID (Below PSDiagID) (Columns 1) [
			CheckBox BWarID	"Give Warnings"			Able	mwarn	DFIdle,
			CheckBox BVerID	"Be Verbose"			Able	mverb	DFIdle ];

	codeGenerationCaption	= StaticText PCGID Left "Code Generation";
	codeGenerationCheckBoxes	= CheckBoxes PGenID (Below PCGID) (Columns 1) (
		CheckBox BGenID "Generate Comments"		Able		mcmmnt	DFIdle :+
		CheckBox BReuseUniqueNodesID "Reuse Unique Nodes" Able reuseUniqueNodesMark DFIdle :+
		(CheckBox BCompileNeverTimeProfileID	"Never Time Profile"	Able	mnevertimeprofile	DFIdle) InsertIfNotUnixSystem
		(CheckBox BCompileNeverMemoryProfileID	"Never Memory Profile"	Able	mnevermemoryprofile	DFIdle) InsertIfMacintoshSystem 
		[]);

	listTypesCaptions	= StaticText PSListTypesCaptionID (Below PDiagID) "List Types";
	listTypesCheckBoxes	= RadioButtons PTypID (Below PSListTypesCaptionID) (Columns 1) type [
			RadioItem RNonID "No Types"				Able		disable,
			RadioItem RInfID "Inferred Types"		Able		enable,
			RadioItem RSETID "Strict Export Types"	Able		enable,
			RadioItem RAllID "All Types"			Able		enable ];
	listTypesShowAttributes	= CheckBoxes PAttrID (Below PTypID) (Columns 1) [
			CheckBox BAttrID "Show Attributes"		attrenabled	mattr	DFIdle ];

	buttonCancel	= DialogButton PCancCID	Left				"Cancel"	Able	Cancel;
	buttonOK	= DialogButton POKCID (RightTo PCancCID)	"OK"		Able	SetCompilerOptions;

	thisornew | usedefault					= RNMoID;
											= RTMoID;
	thisenabled								= BoolToSelect (not usedefault);
	type									= TypeToItemID opt.listTypes;
	mstrict									= BoolToMark opt.sa;
	mwarn									= BoolToMark opt.gw;
	mverb									= BoolToMark opt.bv;
	mcmmnt									= BoolToMark opt.gc;
	mattr									= BoolToMark opt.attr;
	reuseUniqueNodesMark					= BoolToMark opt.reuseUniqueNodes;
	mnevermemoryprofile						= BoolToMark (IfMacintoshSystem opt.neverMemoryProfile False);
	mnevertimeprofile						= BoolToMark (IfUnixSystem False opt.neverTimeProfile);
	attrenabled								= BoolToSelect (opt.listTypes <> NoTypes);
	(usedefault,opt,defopt,winopt,prog`)	= SelectCompilerOptions prog;
	
	enable dinfo dstate		= EnableDialogItems [BAttrID] dstate;
	disable dinfo dstate	= DisableDialogItems [BAttrID] dstate;
	};
	
SelectCompilerOptions ::	!ProgState
							-> (!Bool,!CompilerOptions,!CompilerOptions,!CompilerOptions,!ProgState);
SelectCompilerOptions prog=:{editor={editwindows,defaults={defaultCompilerOptions}}}
	| not present
		= (True	, defaultCompilerOptions, defaultCompilerOptions, defaultCompilerOptions	, prog);
	| not (IsImpPathname path)
		= (True	, defaultCompilerOptions, defaultCompilerOptions, defaultCompilerOptions	, prog);
		= (False, windowopt	, defaultCompilerOptions, windowopt		, prog);
	where {
	present		= WindowsPresent editwindows;
	(_,front)	= GetFrontWindow editwindows;
	path		= front.wstate.pathname;
	windowopt	= front.wstate.WinState.co;
	};
	
SetCompiler	:: 	!Int !Int !CompilerOptions !DialogInfo !(DialogState ProgState IO)
				-> DialogState ProgState IO;
SetCompiler myid otherid {neverMemoryProfile,neverTimeProfile,sa,listTypes,attr,gw,bv,gc,reuseUniqueNodes} dinfo dstate
	= 	ChangeDialogFunction otherid (SetCompiler otherid myid old) (
		EnableDialogItems enabled (
		DisableDialogItems disabled (
		MarkCheckBoxes marked (
		UnmarkCheckBoxes unmarked (
		SelectDialogRadioItem listTypes` dstate)))));
	where {
	(enabled,disabled)	= Flip able ([],[]);
	(marked,unmarked)	= Flip mark ([],[]);
	old					= GetCompilerDialogInfo dinfo;
	listTypes`			= TypeToItemID listTypes;
	showtypes			= listTypes <> NoTypes;
	able				= [(PAttrID,showtypes),(RNonID,True),(RInfID,True),(RSETID,True),(RAllID,True),(BStrID,True)];
	mark				= 	(IfMacintoshSystem True False, (BCompileNeverMemoryProfileID,neverMemoryProfile)) :?
							(BCompileNeverTimeProfileID,neverTimeProfile) InsertIfNotUnixSystem
							[(BStrID,sa),(BAttrID,attr),(BWarID,gw),(BVerID,bv),(BGenID,gc),(BReuseUniqueNodesID,reuseUniqueNodes)];
	};
	
Flip :: ![(!Int,!Bool)] !(![Int],[Int]) -> (![Int],![Int]);
Flip [] acc 
	= acc;
Flip [(id,marked):ids] (mark,unmark)
	| marked
		= Flip ids ([id:mark],unmark);
		= Flip ids (mark,[id:unmark]);

ItemIDToType :: !Int		-> ListTypes;
ItemIDToType RNonID	=  NoTypes;
ItemIDToType RInfID	=  InferredTypes;
ItemIDToType RSETID	=  StrictExportTypes;
ItemIDToType RAllID	=  AllTypes;
	
TypeToItemID :: !ListTypes -> Int;
TypeToItemID NoTypes			=  RNonID;
TypeToItemID InferredTypes		=  RInfID; 
TypeToItemID StrictExportTypes	=  RSETID;
TypeToItemID AllTypes			=  RAllID;
	
GetCompilerDialogInfo :: !DialogInfo -> CompilerOptions;
GetCompilerDialogInfo dinfo
	=	{	neverMemoryProfile	= IfMacintoshSystem (CheckBoxMarked	BCompileNeverMemoryProfileID	dinfo) False,
			neverTimeProfile	= IfUnixSystem False (CheckBoxMarked	BCompileNeverTimeProfileID	dinfo),
			sa		= CheckBoxMarked	BStrID	dinfo,
			listTypes
					= ItemIDToType (GetSelectedRadioItemId	PTypID	dinfo),
			attr	= CheckBoxMarked	BAttrID	dinfo,
			gw		= CheckBoxMarked	BWarID	dinfo,
			bv		= CheckBoxMarked	BVerID	dinfo,
			gc		= CheckBoxMarked	BGenID	dinfo,
			reuseUniqueNodes = CheckBoxMarked	BReuseUniqueNodesID	dinfo };

SetCompilerOptions	:: !DialogInfo !ProgState IO -> ProgIO;
SetCompilerOptions dialog prog=:{editor=ed=:{project,editwindows,defaults}} io
	| usedefaults					= (proga, io`);
	| projectset && projectmodule	= (progb, iob);
									= (progc, io`);
	where {
	proga				= {prog & editor={ed & defaults={defaults & defaultCompilerOptions=options}}};
	(progb, iob)		= UpdateProjectWindowAndSaveProjectFile project`
							{prog & editor={Editor | editorc & project=project`}} io`;
	progc				= {prog & editor=editorc};
	editorc				= {ed & editwindows=SetFrontWindow front` editwindows};
	(_,front)			= GetFrontWindow editwindows;
	projectset			= PR_ProjectSet project;
	front`				= {front & wstate = {WinState | front.wstate & co = options}};
	project`			= PR_UpdateModule module_new update project;
	options				= GetCompilerDialogInfo dialog;
	path				= front.wstate.WinState.pathname;
	module_new			= GetModuleName path;
	(projectmodule,_)	= PR_GetModuleInfo module_new project;
	usedefaults			= GetSelectedRadioItemId PModID dialog == RNMoID;
	io`					= ActivateCurrentWindow (CloseActiveDialog io);
	update minfo		= {minfo & compilerOptions = options};
	};
	
// Device function for the Code Generator Command

CodeGenerator :: !ProgState !IO -> ProgIO;
CodeGenerator prog io
	=  OpenModalDialog dialog prog` io;
	where {
		dialog = CommandDialog DCodeGenOptionsID "Code Generator" [] POKCGID
			       (IfMacintoshSystem [st1,rb1,st2,st3,cb1,rb2,bt1,bt2 /* ,cb2 */]
			                             [st1,rb1,st2,cb1,bt1`,bt2]);
		st1= StaticText		PSCGTitleID Center "Code Generator Options";
		rb1= RadioButtons	PCGOID Left (Columns 2) thisornew [
			RadioItem	RTCGID			"This Project"		thisenabled		(SetCodeGen RTCGID RNCGID prjopt),
			RadioItem	RNCGID			"New Projects"		Able			(SetCodeGen RNCGID RTCGID defopt)];
		st2= StaticText		PSOptID Left "Checks";
		cb1= CheckBoxes		POptID Left (Rows 3)
			(IfUnixSystem
				common
				[CheckBox BChkSID "Check Stacks"		Able	mstack	DFIdle : common]);
			where {
				common =
				[	CheckBox BChkIID "Check Indices"		Able	mindex	DFIdle,
					CheckBox BKpID "Keep ABC Files"	Able	mabc	DFIdle ];
			}

		st3= StaticText		PSProcID (XOffset PSOptID (MM 40.0)) "Target Processor";
		rb2= RadioButtons	PProcID (Below PSProcID) (Rows 4) processor [ 
//			RadioItem	RCurID			"Current Processor"	Able			DFIdle,	
			RadioItem	RCurID			"PowerPC"			Able			DFIdle,	
   			RadioItem	R000ID			"68000"				Able			DFIdle,
   			RadioItem	R020ID			"68020"				Able			DFIdle,
   			RadioItem	R881ID			"68020 + 68881"		Able			DFIdle ];

		bt1= DialogButton	PCancCGID Right "Cancel" 	Able 			Cancel;

		bt1`= DialogButton	PCancCGID (XOffset POptID (MM 10.0)) "Cancel" Able Cancel;

		bt2= DialogButton	POKCGID (RightTo PCancCGID)	"OK" Able SetCodeGeneratorOptions;
		thisornew				| projectset	= RTCGID;
	   											= RNCGID;
		thisenabled								= BoolToSelect projectset;
		mstack									= BoolToMark opt.cs;
		mindex									= BoolToMark opt.ci;
		mabc									= BoolToMark opt.kaf;
		processor								= ProcessorToInt opt.tp;
		(projectset,opt,defopt,prjopt,prog`)	= SelectCodeGenOptions prog;
   };
   
SelectCodeGenOptions :: !ProgState
						-> (!Bool,!CodeGenOptions,!CodeGenOptions,!CodeGenOptions,!ProgState);
SelectCodeGenOptions prog=:{editor={defaults={cgo=defaultopt},project}}
	| not projectset	= (False, defaultopt, defaultopt, defaultopt, prog);
						= (True	, projectopt, defaultopt, projectopt, prog);
	where {
	projectset	= PR_ProjectSet project;
	projectopt	= PR_GetCodeGenOptions project;
	};

SetCodeGen	::	!Int !Int !CodeGenOptions !DialogInfo (DialogState ProgState IO)
				-> DialogState ProgState IO;
SetCodeGen myid otherid opt dinfo dstate
	= 	ChangeDialogFunction otherid (SetCodeGen otherid myid old) (
		MarkCheckBoxes marked (
		UnmarkCheckBoxes unmarked(
		SelectDialogRadioItem (ProcessorToInt opt.tp) (
		dstate)))
		);
	where {
		(marked,unmarked)	= Flip ((BChkSID,opt.cs) InsertIfNotUnixSystem [(BChkIID,opt.ci)] InsertIfMacintoshSystem [(BKpID,opt.kaf)]) ([],[]);
		old					= GetCodeGenDialogInfo dinfo;
	};

ProcessorToInt :: !Processor -> Int;
ProcessorToInt CurrentProcessor		=  RCurID;
ProcessorToInt MC68000				=  R000ID;
ProcessorToInt MC68020				=  R020ID;
ProcessorToInt MC68020_and_68881	=  R881ID;

IntToProcessor :: !Int -> Processor;
IntToProcessor RCurID	=  CurrentProcessor;
IntToProcessor R000ID	=  MC68000;
IntToProcessor R020ID	=  MC68020;
IntToProcessor R881ID	=  MC68020_and_68881;
 
GetCodeGenDialogInfo :: !DialogInfo -> CodeGenOptions;
GetCodeGenDialogInfo dialog =
	{	cs	= IfUnixSystem False (CheckBoxMarked BChkSID dialog),
		ci	= CheckBoxMarked BChkIID dialog,
		kaf	= CheckBoxMarked BKpID dialog,
		tp	= IfMacintoshSystem
		           (IntToProcessor (GetSelectedRadioItemId PProcID dialog))
                   CurrentProcessor
	};

SetCodeGeneratorOptions	:: !DialogInfo !ProgState !IO -> ProgIO;
SetCodeGeneratorOptions dialog prog=:{editor=ed=:{defaults,project}} io
	| usedefault
		= (proga, io`);
		{
			proga			= {prog & editor={ed & defaults = {defaults & cgo = options}}};	
		}
		= (progb, iob);
		{
			(progb,iob)		= UpdateProjectWindowAndSaveProjectFile project` {prog & editor={Editor | ed & project=project`}} io`;
		}
	where {
		project`			= PR_SetCodeGenOptions options project;
		options				= GetCodeGenDialogInfo dialog;
		usedefault			= GetSelectedRadioItemId PCGOID dialog == RNCGID;
		io`					= ActivateCurrentWindow (CloseActiveDialog io);
	};

// Device function for the Application Command

::	ApplicationDialog = {	present	::	!Bool,
							default_	::	!ApplicationOptions,
							project	::	!ApplicationOptions };

ApplicationOptions	:: !ProgState !IO -> ProgIO;
ApplicationOptions prog=:{editor={project,defaults={ao=defopt}}} io
		= OpenApplicationDialog {present=False,default_=defopt,project=defopt} prog io;

Application	:: !ProgState !IO -> ProgIO;
Application prog=:{editor={project,defaults={ao=defopt}}} io
	| project_set
		= OpenApplicationDialog {present=project_set,default_=defopt,project=prjopt} prog io;
		= OpenApplicationDialog {present=project_set,default_=defopt,project=defopt} prog io;
	where {
		project_set = PR_ProjectSet project;
		prjopt	= PR_GetApplicationOptions project;
	};

OpenApplicationDialog :: !ApplicationDialog !ProgState !IO -> ProgIO;
OpenApplicationDialog astate=:{present,default_,project} prog io
	=	OpenModalDialog dialog prog io;
	where {
		dialog = CommandDialog DApplOptionsID "Application" [] POKAID thecontrols;
		thecontrols    = IfMacintoshSystem maccontrols commoncontrols;

		editTextWidth
			=	MM 20.0;
		editTextOffset
			=	Pixel 10;

		commoncontrols =
			StaticText		PSATitleID Center "Application Options" :+
// RWS app options			StaticText		RNAppID Center "Application Options" :+
// RWS app options
					RadioButtons	PAppID Left (Columns 2) thisornew [

// RWS app options		RadioItem	RNAppID 				"This Application" 				Able		(SetApplication RNAppID astate)
						RadioItem	RTAppID 				"This Project" (BoolToSelect present)	(SetApplication RTAppID astate),
						RadioItem	RNAppID 				"New Projects" 				Able		(SetApplication RNAppID astate)
				] :+
			StaticText PSConfID Left "Configuration" :+
			StaticText PSInfoID (XOffset PSConfID (MM 50.0)) "Information" :+

			StaticText PSHSizeID (Below PSConfID)  "Maximum Heap Size" :+
			StaticText PSSSizeID (Below PSHSizeID) "Stack Size" :+
			(IfMacintoshSystem True False, StaticText PSEMemID (Below PSSSizeID) "Extra Memory") :?
			StaticText PSENextHeapSizeFactorID (Below (IfMacintoshSystem PSEMemID PSSSizeID)) "Next Heap Size Factor" :+
			StaticText PSEInitialHeapSizeID (Below PSENextHeapSizeFactorID) "Initial Heap Size" :+
			CheckBoxes PMarkingCollectionID (Below PSEInitialHeapSizeID) (Columns 1) [
				CheckBox	BMarkingCollectionID "Marking Collection"		Able (BoolToMark opt.marking_collection) DFIdle
			] :+

			(CheckBoxes PTimeProfileID (Below PMarkingCollectionID) (Columns 2) (
	// RWS app options
					(CheckBox	BProfilingID "Time Profiling" Able (BoolToMark opt.profiling) DFIdle) :+
	// RWS app options
					(CheckBox	BProfiling601ID "601" Able (BoolToMark opt.profiling601) DFIdle) InsertIfMacintoshSystem
					[])) InsertIfNotUnixSystem
			
			(
			//IfMacintoshSystem True False,
			 IfUnixSystem False True, CheckBoxes PMemoryProfileID (Below PTimeProfileID) (Columns 1) [
				CheckBox	BMemoryProfilingID "Memory Profiling" Able (BoolToMark opt.memoryProfiling) DFIdle
			]) :?

			EditText PHSizeID (XOffset PSHSizeID (MM 8.0)) editTextWidth 1 (IntToMemSize opt.hs) :+
			EditText PSSizeID (Below PHSizeID) editTextWidth 1 (IntToMemSize opt.ss) :+
			(IfMacintoshSystem True False, EditText PEMemID (Below PSSizeID) editTextWidth 1 (IntToMemSize opt.em)) :?
			EditText PNextHeapSizeFactorID (Below (IfMacintoshSystem PEMemID PSSizeID)) editTextWidth 1 (FixedPointToString opt.heap_size_multiple) :+
			EditText PInitialHeapSizeID (Below PNextHeapSizeFactorID) editTextWidth 1 (IntToMemSize opt.initial_heap_size) :+

			(IfUnixSystem False True, StaticText PSEMemoryProfileMinimumHeapSizeID (RightTo PMemoryProfileID) "Minimum Profile Heap") :?
			(IfUnixSystem False True, EditText PMemoryProfileMinimumHeapSizeID ((IfMacintoshSystem RightTo Below) PSEMemoryProfileMinimumHeapSizeID) editTextWidth 1 (IntToMemSize opt.memoryProfilingMinimumHeapSize)) :?
			CheckBoxes PInfoID (Below PSInfoID) (Columns 1) [
				CheckBox	BShwEID 				"Show Execution Time"		Able (BoolToMark opt.set) DFIdle,
				CheckBox	BShwGID					"Show Garbage Collections" 	Able (BoolToMark opt.sgc) DFIdle,
				CheckBox	BPrtSID					"Print Stack Size" 			Able (BoolToMark opt.pss) DFIdle:
				(CheckBox	BWriteStderrToFileID "Write stderr to file" Able (BoolToMark opt.write_stderr_to_file) DFIdle) InsertIfNotUnixSystem
				[]
			] :+
			StaticText 	PSOutpID (Below PInfoID) 	"Output" :+
			RadioButtons 	POutpID (Below PSOutpID) (Rows 3) (OutputToInt opt.o) [
				RadioItem	RBscVID					"Basic Values Only" 		Able		DFIdle,
				RadioItem	RShwCID					"Show Constructors" 		Able		DFIdle,	
				RadioItem	RNoCnID					"No Console"        		Able		DFIdle
			] :+
			DialogButton 	PCancAID Right	"Cancel"	Able		Cancel :+
			DialogButton 	POKAID (RightTo PCancAID) 				"OK"		Able		(SetApplicationOptions astate) :+
			[];

		maccontrols = commoncontrols ++ [ DialogButton PFntID (XOffset POKAID (MM 40.0)) "Font..." Able (AppFont thisornew astate) ];

		thisornew	| present
					= RTAppID;
					= RNAppID;
		opt 		| present
						= project;
						= default_;
	};

SetApplication	::	!Int !ApplicationDialog !DialogInfo !(DialogState ProgState IO)
					-> DialogState ProgState IO;
SetApplication myid astate=:{default_,project} dinfo dstate
	=	dstate
		:-	( \state ->
				IfMacintoshSystem
					(state
						:- ChangeButtonFunction PFntID (AppFont myid new)
						:- ChangeEditText PEMemID (IntToMemSize opt.em))
					state)			
		:-	( \state ->
				IfUnixSystem
					state
					(state
						:- ChangeEditText PMemoryProfileMinimumHeapSizeID (IntToMemSize opt.memoryProfilingMinimumHeapSize)))			
		:- ChangeDialogFunction myid (SetApplication myid new)
		:- ChangeDialogFunction otherid (SetApplication otherid new)
		:- MarkCheckBoxes marked
		:- UnmarkCheckBoxes unmarked
		:- ChangeEditText PInitialHeapSizeID (IntToMemSize opt.initial_heap_size)
		:- ChangeEditText PNextHeapSizeFactorID (FixedPointToString opt.heap_size_multiple)
		:- ChangeEditText PHSizeID (IntToMemSize opt.hs)
		:- ChangeEditText PSSizeID (IntToMemSize opt.ss)
		:- SelectDialogRadioItem (OutputToInt opt.o)
		:- ChangeButtonFunction POKAID (SetApplicationOptions new);
	where {
		usedefaults				= myid == RNAppID;

//		opt						= if usedefaults default_ project;
		opt | usedefaults		= default_;
								= project;
		otherid | usedefaults	= RTAppID;
								= RNAppID;
		new | usedefaults		= {ApplicationDialog | astate & project = cur};
								= {astate & default_ = cur};
		(marked,unmarked)		= Flip [
										(BShwEID,opt.set),
										(BShwGID,opt.sgc),
										(BPrtSID,opt.pss),

										(BMarkingCollectionID,opt.marking_collection),
										(BWriteStderrToFileID,opt.write_stderr_to_file) :

										IfUnixSystem
											[]
											[(BProfilingID,opt.profiling),(BMemoryProfilingID,opt.memoryProfiling):
											IfMacintoshSystem
												[(BProfiling601ID,opt.profiling601)]
												[]
											]
									]
										([],[]);
		cur						= GetApplicationDialogInfo usedefaults dinfo astate;
	};
	
OutputToInt	:: !Output				-> Int;
OutputToInt BasicValuesOnly		=  RBscVID;
OutputToInt ShowConstructors	=  RShwCID;
OutputToInt	NoConsole			=  RNoCnID;
	
IntToOutput	:: !Int		-> Output;
IntToOutput RBscVID	=  BasicValuesOnly;
IntToOutput RShwCID	=  ShowConstructors;
IntToOutput RNoCnID	=  NoConsole;

SetApplicationOptions :: !ApplicationDialog !DialogInfo !ProgState !IO -> ProgIO;
SetApplicationOptions astate dialog prog=:{editor=ed=:{project,defaults}} io
	| usedefault
		 = (proga, ioa);
		 {
			proga		= {prog & editor={ed & defaults={defaults & ao=new}}};	
		 }
		= (progb, iob); 
		{
			(progb,iob)	= UpdateProjectWindowAndSaveProjectFile project`
								{prog & editor={Editor | ed & project=project`}} ioa;
		}
	where {
		ioa				= ActivateCurrentWindow (CloseActiveDialog io);
		project`		= PR_SetApplicationOptions new project;
		new				= GetApplicationDialogInfo usedefault dialog astate;
		usedefault		= GetSelectedRadioItemId PAppID dialog == RNAppID ;
	};
/* RWS app options ...
	=	({prog & editor.defaults.ao = GetApplicationDialogInfo True dialog astate}, CloseActiveDialog io);
... RWS */

GetApplicationDialogInfo :: !Bool !DialogInfo !ApplicationDialog -> ApplicationOptions;
GetApplicationDialogInfo usedefault dialog astate=:{default_,project}
	= {
		hs	= MemSizeToInt (GetEditText PHSizeID dialog),
		ss	= MemSizeToInt (GetEditText PSSizeID dialog),
		em	= IfMacintoshSystem (MemSizeToInt (GetEditText PEMemID dialog)) 0,
		heap_size_multiple = StringToFixedPoint (GetEditText PNextHeapSizeFactorID dialog),
		initial_heap_size = MemSizeToInt (GetEditText PInitialHeapSizeID dialog),
		set	= CheckBoxMarked BShwEID dialog,
		sgc	= CheckBoxMarked BShwGID dialog,
		pss	= CheckBoxMarked BPrtSID dialog,
		marking_collection = CheckBoxMarked BMarkingCollectionID dialog,
		o	= IntToOutput (GetSelectedRadioItemId POutpID dialog),
		fn	= fn,
		fs	= fs,
		write_stderr_to_file
						= IfUnixSystem False (CheckBoxMarked BWriteStderrToFileID dialog),
		memoryProfiling	= IfUnixSystem False (CheckBoxMarked BMemoryProfilingID dialog),
		memoryProfilingMinimumHeapSize = IfUnixSystem 0 (MemSizeToInt (GetEditText PMemoryProfileMinimumHeapSizeID dialog)),
		// RWS app options	profiling601	= False,
		profiling		= IfUnixSystem False (CheckBoxMarked BProfilingID dialog),
		profiling601	= IfMacintoshSystem (CheckBoxMarked BProfiling601ID dialog) False
		// RWS app options	profiling		= False
	  };


	where {
		fn	| usedefault	= default_.fn;
							= project.fn;
		fs	| usedefault	= default_.fs;
							= project.fs;
	};

StringToFixedPoint s
	| n<512+128
		= 512+128;
	| n>100<<8
		= 100<<8;
		= n;
	{}{
		n=string_to_fixed_point 0 0 s;
		
		string_to_fixed_point i v s
			| i>= size s
				= v<<8;
			| char>='0' && char<='9'
				= string_to_fixed_point (inc i) (v*10+(toInt char-48)) s;
			| char=='.'
				= (v<<8)+fraction (inc i) s;
				= v<<8;
			{}{
				char=s.[i];
			}
			
		fraction i s
			| i>= size s || char1<'0' || char1>'9'
				= 0;
			| inc i>= size s || char2<'0' || char2>'9'
				= ((toInt char1-48)<<8) / 10;
				= (((toInt char1-48)*10+(toInt char2-48))<<8)/100;
		{}{
			char1=s.[i];
			char2=s.[inc i];
		}
	}

FixedPointToString n
	| n<512+128
		= "2.5";
	| n>100<<8
		= "100";
	| second_digit<>0
		= toString (n>>8)+++"."+++toString first_digit+++toString second_digit;
	| first_digit<>0
		= toString (n>>8)+++"."+++toString first_digit;
		= toString (n>>8);
	{}{
		first_digit=fraction / 10;
		second_digit=fraction rem 10;
		fraction=toInt (toReal (n bitand 255) * 100.0 / 256.0);
	}	

AppFont	:: !Int ApplicationDialog !DialogInfo !ProgState !IO -> ProgIO;
AppFont myid astate=:{default_,project} dinfo prog io
	=  OpenModalDialog dialog prog io;
	where {
	dialog= CommandDialog DFontsID "Application Font" [] POKFID [st1,sl1,st2,sl2,bt0,bt1,bt2];
	st1 = StaticText	PSFontID	Left 				"Font";
	sl1 = ScrollingList PFontID (XOffset PSFontID (MM 1.0)) (MM 0.0) Able 8 cfont MakeFontItems ChangeAppSizesList;
	st2 = StaticText	PSFSizeID	(RightTo PFontID)	"Size";
	sl2 = ScrollingList PFSizeID (XOffset PSFSizeID (MM 1.0)) (MM 10.0) Able 8 (toString csize) (MakeSizeItems cfont) ChangeAppLazyFox;
	bt0	= DialogIconButton PFoxID Left ((0,0),FoxDim) (LazyFox cfont csize) Unable Cancel;
	bt1 = DialogButton 	PCancFID Right				"Cancel"	Able	(CancelAppFont astate);
	bt2 = DialogButton 	POKFID 	(RightTo PCancFID) 	"OK"		Able	(SetAppFont myid astate);
	cfont | usedefault	= default_.fn;
						= project.fn;
	csize | usedefault	= default_.fs;
						= project.fs;
	usedefault			= myid == RNAppID;
	};
	
ChangeAppSizesList :: !DialogInfo !(DialogState ProgState IO) -> DialogState ProgState IO;
ChangeAppSizesList ddef dstate
	=  ChangeSizesList PFoxID PFSizeID (GetAppFontDialogInfo ddef) dstate;

ChangeAppLazyFox :: !DialogInfo !(DialogState ProgState IO) -> DialogState ProgState IO;
ChangeAppLazyFox ddef dstate
	=  ChangeLazyFox PFoxID (GetAppFontDialogInfo ddef) dstate;

GetAppFontDialogInfo :: !DialogInfo -> EditOptions;
GetAppFontDialogInfo dialog =
	{ EditOptions | DefaultEditOptions & 	
		fontname	= GetScrollingListItem PFontID dialog,
		fontsize	= StringToInt (GetScrollingListItem PFSizeID dialog) };

CancelAppFont :: !ApplicationDialog !DialogInfo !ProgState !IO -> ProgIO;
CancelAppFont astate dialog editor io
	=  (editor, ActivateCurrentWindow (CloseActiveDialog io));
	
SetAppFont :: !Int !ApplicationDialog !DialogInfo !ProgState !IO -> ProgIO;
SetAppFont myid astate=:{default_,project} dialog prog io
	=  (prog,io`);
	where {
	io`					= ChangeDialog	DApplOptionsID
								[ 
								  // RWS app options
								  ChangeDialogFunction RNAppID (SetApplication RNAppID new),
								  // RWS app options
								  ChangeDialogFunction RNAppID (SetApplication RNAppID new),
								  // RWS app options
								  ChangeDialogFunction RTAppID (SetApplication RTAppID new),
								  // RWS app options
								  ChangeDialogFunction RTAppID (SetApplication RTAppID new),
								  ChangeButtonFunction POKAID (SetApplicationOptions new),
								  ChangeButtonFunction PFntID (AppFont myid new) ] io1;
	eo					= GetAppFontDialogInfo dialog;
	defopt`				= {default_ & fn = eo.EditOptions.fontname, fs = eo.EditOptions.fontsize};
	prjopt`				= {project & fn = eo.EditOptions.fontname, fs = eo.EditOptions.fontsize};
	new | usedefaults	= {astate & default_ = defopt`};
						= {ApplicationDialog | astate & project = prjopt`};
	usedefaults			= myid == RNAppID;
	io1					= ActivateCurrentWindow (CloseActiveDialog io);
	};
