implementation module EdProjectMenu;

//	The commands of the Project menu

import StdInt, StdString, StdBool, StdArray;
import deltaEventIO, deltaDialog, deltaIOState, deltaFileSelect;

import	EdProgramState, EdDialogs, EdWindows, EdSupport, EdFiles, EdPath,
		EdProject, EdProjectUtils, EdMenuItems, EdTextWindow, EdWindowsMenu;
from EdFileMenu import OpenFile;

CancelID	:== 1;
OKID		:== 2;

// Device function for the NewProject Command
	
NewProject	:: !ProgState !IO -> ProgIO;
NewProject prog=:{editor={editwindows,defaults={edit,cgo,ao,po,linkOptions}}} io
	= OpenProjectWindow projectpath project prog io;
	where {
	project			= PR_NewProject pathname weo wco cgo ao po Nil linkOptions;
	(_,front)		= GetFrontWindow editwindows;
	wco				= front.wstate.WinState.co;
	weo				= {edit & eo = EW_GetEditOptions front};
	pathname		= front.wstate.pathname;
	projectpath		= MakeProjectPathname pathname;
	};

// Device function for the OpenProject Command

OpenProject	:: !ProgState !IO -> ProgIO;
OpenProject ps io0
	| not open
		= (ps2,io1);
		= OpenProjectFile pathname ps2 io1;
	where {
		(open,pathname,ps2,io1)	= EdSelectInputFile ps io0;
	};

OpenProjectFileIfNoProjectSet :: !String !ProgState !IO -> ProgIO;
OpenProjectFileIfNoProjectSet newProjectPath prog=:{editor={Editor|project, editwindows}} io
	| PR_ProjectSet project
		| currentProjectPath == newProjectPath
			= (prog, io)
		// otherwise
			# (buttonId, prog,io) 
				=	OpenNotice (Notice ["Close current project \"" +++  RemovePath currentProjectPath +++ "?\""]
								(NoticeButton OKID "Close") [NoticeButton CancelID "Cancel"]) prog io;
			| buttonId == OKID
				# (prog, io)
					=	CloseProject prog io
				=	OpenProjectFile newProjectPath prog io;
			// otherwise
				=	(prog, io)
//			= AlertDialog ["Cannot open this project","a project is already open "] prog io;
	// otherwise
		= OpenProjectFile newProjectPath prog io;
	where
	{
		currentProjectPath
			=	MakeProjectPathname (GetWindow ProjectWdID editwindows).wstate.pathname;
	}

OpenProjectFile :: !String !ProgState !IO -> ProgIO;
OpenProjectFile pathname prog=:{editor=ed=:{defaults={paths=defpaths},startupinfo={startupdir}}} io
	| not projectfile
		= AlertDialog ["The file \"" +++  name +++ "\" is not a project file."] prog io;
	| not good
		= AlertDialog ["The file \"" +++  name +++ "\" could not be opened."] prog io0;
		= OpenProjectWindow pathname project1 prog1 io1;
	where {
		((project,good),io0)		= accFiles (ReadProjectFile pathname defpaths startupdir) io;
		prog0						= {prog & editor={Editor | ed & project=project}};
		(prio1,project1)			= OpenModuleWindows modules project prog0 io0;
		(prog1,io1)					= prio1;
		modules						= PR_GetModulenames False IclMod project;
		name						= RemovePath pathname;
		projectfile					= IsPrjPathname pathname;
	};
		
OpenModuleWindows :: !(List Modulename) !Project !ProgState !IO -> (!ProgIO,!Project);
OpenModuleWindows Nil project prog io =  ((prog, io), project);
OpenModuleWindows (mn:!rest) project prog io
	=  OpenModuleWindows rest project` prog` io`;
	where {
	(prog`,io`)			= prio`;
	(prog1,io1)			= prio1;
	(prio`,project`)	= OpenModuleWindow DclMod mn project1 prog1 io1;
	(prio1,project1)	= OpenModuleWindow IclMod mn project prog io;
	};

OpenModuleWindow :: !Def_and_Imp !Modulename !Project !ProgState !IO -> (!ProgIO, !Project);
OpenModuleWindow defwin mn project prog=:{editor={defaults={edit},editwindows}} io
	| winclosed
		= ((prog,io), project);
	| window_already_open
		= ((prog,io), projecta);
		{
			projecta					= PR_UpdateModule mn updatea project;
			updatea minfo | defwin		= {minfo & defeo = eo, compilerOptions = compilerOptions};
										= {minfo & impeo = eo, compilerOptions = compilerOptions};
		}
	| good
		# (prog`, io)
			=	CheckMixedNewlines pathname mixed prog io`
		= (OpenEditWindow pathname peo.pos_size {EditOptions | peo.eo & newlines=newlines} pco EmptyTSel nrlines text prog` io, project);
		= ( pio, projectb);
		{
			pio = AlertDialog ["The file \"" +++  name +++ "\" could not be opened." ] prog io`;
		}
	where {
	((good,text,nrlines,(mixed,newlines)),io`)= accFiles (ReadFile pathname) io;
	(window_already_open,id)	= IsExistingPathname pathname editwindows;
	oldwd						= GetWindow id editwindows;
	projectb					= PR_UpdateModule mn updateb project;
	updateb minfo | defwin		= {minfo & defopen=False};
								= {minfo & impopen=False};
	(_,poptions)				= PR_GetModuleInfo mn project;
	peo | defwin				= poptions.defeo;
								= poptions.impeo;
	pco							= poptions.ModInfo.compilerOptions;
	dir							= poptions.dir;
	name | defwin				= MakeDefPathname mn;
								= MakeImpPathname mn;
	pathname					= MakeFullPathname dir name;
	winclosed					= defwin && not poptions.defopen || not defwin && not poptions.impopen;
	eo							= {edit & eo = EW_GetEditOptions oldwd};
	compilerOptions				= oldwd.wstate.WinState.co;
	};

// Device function for the SetProject Command

SetProject :: !ProgState !IO -> ProgIO;
SetProject prog=:{editor={project,defaults={edit},editwindows}} io
// RWS	| not ok		= (p2, io);
					= UpdateProjectWindowAndSaveProjectFile project` prog io;
	where {
	(_,front)	= GetFrontWindow editwindows;
	project`	= PR_SetRoot pathname weo wco project;
	weo			= {edit & eo = EW_GetEditOptions front};
	wco			= front.wstate.WinState.co;
	pathname	= front.wstate.pathname;
/* RWS don't ask confirmation
	name		= RemovePath pathname;
	notice		= Notice	[line]
							(NoticeButton OKID "OK")
							[NoticeButton CancelID "Cancel"];
	line		= "Make \'" +++ name +++ "\' the Main Module?";
	ok			= id == OKID;
	(id,p2,io`)	= OpenNotice notice prog io;
*/
	};

// Device function for the CloseProject Command

CloseProject :: !ProgState !IO -> ProgIO;	
CloseProject prog io
	=  CloseWindow "closing" ProjectWdID prog io;

OpenFileOrProjectFile :: !String !ProgState !IO -> ProgIO;
OpenFileOrProjectFile file_name ps io
	| file_name % (file_name_length-4,file_name_length-1)==".prj"
		= OpenProjectFileIfNoProjectSet file_name ps io;
		= OpenFile file_name ps io;
	{}{
		file_name_length= size file_name;
	}
