{$B+,D-,G-,I-,L-,N-,P+,Q-,R-,S-,T-,V-,X+,Z+}
program MakeFast;
  { Copyright (c)1993 by Softdesign Computer Software
                               written by Thomas Much }
  { wer sich eingehender mit den FastLoad-Flags besch„ftigen
    m”chte, sollte sich einmal das ST-STE-TT-Profibuch ansehen! }

  uses GObjects; { ObjectGEM immer als letzte Unit einbinden,
                   allerdings noch vor auf GObjects zugreifenden
                   Units! }

	const
	      {$I makefast.i}  { Konstanten fr die Dialogbox }

	      PH_FASTLOAD  = 1;       { die Fastload-Flags... }
	      PH_LOADALT   = 2;
	      PH_MALLOCALT = 4;

  type PH = record
							ph_branch  : word;     { Programmheader }
							ph_tlen    : longint;
							ph_dlen    : longint;
							ph_blen    : longint;
							ph_slen    : longint;
							ph_res1    : longint;
							ph_prgflags: longint;
							ph_absflag : word;
						end;

			 TMFApplication = object(TApplication)
			 										{ der neue Anwendungs-Objekt-TYP }
													procedure InitInstance; virtual;
  												procedure InitMainWindow; virtual;
  											end;

			 PMFDialog  = ^TMFDialog;
			 TMFDialog = object(TDialog)
			 							 { der eigentliche Dialog }
										 ttmem          : integer;
										 datei,pfad     : string;
										 st1,st2,st3    : PStatic;
										 cb1,cb2,cb3    : PCheckBox;
										 pb1,pb2,pb3,pb4: PButton;
										 pb5,pb6,pb7    : PButton;
										 phrec          : PH;
										 f              : file of PH;
										 procedure GetWindowClass(var AWndClass: TWndClass); virtual;
										 procedure SetupWindow; virtual;
										 function ExitDlg(AnIndx: integer): boolean; virtual;
										 function OK: boolean; virtual;
										 function Help: boolean; virtual;
										 { neue Routinen... }
										 procedure UpdateAmount; virtual;
										 procedure DisableAll; virtual;
										 procedure Load; virtual;
									 end;

  var MFApplication: TMFApplication;
  									 { das Anwendungs-Objekt;
  									   dies sollte das EINZIGE statische Objekt
  									   sein, alle anderen werden normalerweise
  									   dynamisch verwaltet! }


procedure MFResource; external; {$L mfrsc.o}
	{ die Resource wird ins Programm eingebunden (wichtig fr ACCs) }


procedure TMFApplication.InitInstance;

	begin
		{ wird eine Anwendung das erste Mal in den Speicher geladen,
		  wird die Methode InitApplication aufgerufen, die u.a. die
		  boolean-Variable FirstInstance setzt; danach wird InitInstance
		  aufgerufen;
		  wird die Anwendung ein zweites Mal geladen (z.B. zuerst als ACC
		  und dann als Prg), wird NUR diese Methode InitInstance von
		  dem Konstruktor Init aufgerufen! }
		InitResource(@MFResource,nil);
		{ die im Prg eingebundene Resource wird initialisiert;
		  soll das RSC-File nachgeladen werden, wird statt InitResource()
		  einfach LoadResource(datei) aufgerufen }
		TApplication.InitInstance
		{ Standard-Initialisierungen, setzt Schnittstellenobjekt fr
		  <Control>+<Q>-Tastenkombination und ruft InitMainWindow auf }
	end;


procedure TMFApplication.InitMainWindow;
	var p: PMFDialog;

	begin
		{ InitMainWindow legt ein "ganz einfaches" GEM-Fenster an und wird
		  deshalb eigentlich immer berschrieben, um ein abgeleitetes Fenster-
		  objekt zu installieren;
		  dieser Aufruf ist insofern besonders, als daž wir kein FENSTER,
		  sondern einen DIALOG als "MainWindow" anmelden; dieser wird zwar
		  normalerweise in einem Fenster dargestellt, sollte allerdings kein
		  Fenster-Handle mehr verfgbar sein, macht ObjectGEM daraus auto-
		  matisch (zur Laufzeit) einen MODALEN Dialog! }
		p:=new(PMFDialog,Init(nil,'ObjectGEM MakeFast',MFDLG));
		{ der Dialog tr„gt sich selbst„ndig in die Fensterliste ein;
		  MainWindow zeigt immer auf das erste installierte TWindow-Objekt
		  (in diesem Fall auf einen Nachfahren);
		  dem Konstruktor wird das Parent-Objekt (in diesem Fall nil, es
		  existiert also kein Parent), der Fenstertitel und der Index des
		  Dialogbaums bergeben }
		if (MainWindow=nil) or (ChkError<em_OK) then Status:=em_InvalidMainWindow
			{ irgendwas ist schiefgelaufen => nicht initialisieren;
			  ObjectGEM prft dann, wie und ob (ACCs!) das Programm
			  verlassen wird }
		else
			begin
				{ p zeigt auf den Dialog; nun werden die Schnittstellen-
				  objekte initialisiert; diese tragen sich in die Liste
				  der TControl-Objekte im Dialog-Objekt ein und werden
				  dadurch beim freigeben des Dialogs automatisch mitge-
				  l”scht }
				{ die Rckgabe-Pointer werden gespeichert, um sp„ter die
				  Objekte mit ihren eigenen Methoden zu modifizieren! }
				p^.st1:=new(PStatic,Init(p,MFMINDT,0,false,'Gibt an, wieviel TT-RAM (Alternate|RAM) dem Programm gengt, wenn mehr|ST-RAM als TT-RAM vorhanden ist.'));
				p^.st2:=new(PStatic,Init(p,MFAMOUNT,8,false,'Gibt an, wieviel TT-RAM (Alternate|RAM) dem Programm gengt, wenn mehr|ST-RAM als TT-RAM vorhanden ist.'));
				p^.st2^.Style:=p^.st2^.Style and not(sts_Fill);
				{ einfacher Text, bergeben wird u.a. die max. L„nge des Textes+1
				  (Nullbyte), einen boolean-Wert, der angibt, ob der Text unter-
				  strichen wird, und der String fr BubbleHelp (!);
				  bringen Sie den Mauscursor doch mal ber einen Button und
				  drcken Sie dann <Help> ...!?!!! }
				p^.st3:=new(PStatic,Init(p,MFVER,39,false,'ObjectGEM MakeFast ist Freeware,|d.h. Sie drfen das Programm|kostenlos kopieren und benutzen.|Žnderungen am Programm sind|nicht erlaubt!'));
				p^.cb1:=new(PCheckBox,Init(p,MFFAST,true,'Bestimmt das FastLoad-Flag.|Ist es gesetzt, wird beim Programm-|start nur die BSS gel”scht. Das|Flag sollte bei mindestens je einem|Auto-Ordner-Programm und Accessory|NICHT gesetzt sein!'));
				{ ankreuzbare Box; der boolean-Wert gibt an, ob die CheckBox
				  im "neuen" Stil gezeichnet wird; ist in der Resource das
				  CROSSED-Attribut gesetzt, wird statt des H„kchens ein
				  Kreuzchen verwendet }
				p^.cb2:=new(PCheckBox,Init(p,MFPROG,true,'Das Programm darf in das (schnelle)|TT-RAM geladen werden. Vorsicht, wenn|das Programm z.B. den Bildschirm-|speicher verschiebt!'));
				p^.cb3:=new(PCheckBox,Init(p,MFMEM,true,'Malloc()-Anforderungen des Programms|drfen aus dem TT-RAM bedient werden.|Vorsicht bei Programmen, die z.B. den|Bildschirmspeicher verschieben!'));
				p^.pb1:=new(PButton,Init(p,MFDATEI,id_No,true,'W„hlt ein neues Programm|zum Bearbeiten aus.'));
				{ ein PushButton }
				p^.pb2:=new(PButton,Init(p,MFMAKE,id_No,true,'Schreibt die neuen Werte in|das ausgew„hlte Programm.'));
				p^.pb3:=new(PButton,Init(p,MFOK,id_OK,true,'Verl„žt MakeFast.'));
				{ id_OK bedeutet, daž dies der OK-Button ist;
				  beim Anklicken wird dadurch die TDialog.OK-Methode aufgerufen }
				p^.pb4:=new(PButton,Init(p,MFLESS,id_No,false,'Vermindert den TT-RAM-Bedarf|um 128 KB.'));
				p^.pb5:=new(PButton,Init(p,MFMORE,id_No,false,'Erh”ht den TT-RAM-Bedarf|um 128 KB.'));
				p^.pb6:=new(PButton,Init(p,MFHELP,id_Help,false,'Zeigt einen allg. Hilfstext an.'));
				p^.pb7:=new(PButton,Init(p,MFNAME,id_No,false,'Zeigt den Namen des Programms an.|Durch Anklicken erh„lt man den|vollen Namen incl. Pfad.'));
				p^.st3^.SetText('VERSION 1.3 VOM 25.07.1993 (FREEWARE!)');
				{ Text setzen (TStatic-Methode) }
				p^.UpdateAmount;
				p^.DisableAll;
				if AppFlag then p^.MakeWindow
				{ wenn wir kein ACC sind, wird das Fenster sofort
				  ge”ffnet, sonst wartet ObjectGEM auf das Eintreffen
				  einer AC_OPEN-Message }
			end
	end;


procedure TMFDialog.GetWindowClass(var AWndClass: TWndClass);

	begin
		TDialog.GetWindowClass(AWndClass);
		{ initialisiert die Dialog-Klasse;
		  wenn Sie dies vergessen, werden Sie die seltsamsten
		  Systemabstrze erleben (vertrauen Sie mir, ich weiž,
		  was ich erlebt habe...);
		  bei OOP kommt es oft vor, daž Vorfahren aufgerufen
		  werden; wann dies geschehen kann, muž oder unterbleiben
		  sollte, wird in der ObjectGEM-Dokumentation (bzw. in der
		  Online-Help) beschrieben sein }
		AWndClass.Style:=AWndClass.Style or cs_CreateOnAccOpen
		{ da wir einen Dialog als "Hauptfenster" verwenden, mssen
		  wir ObjectGEM sagen, daž dieser Dialog bei einer AC_OPEN-
		  Message (also bei Anwahl des Accessory-Meneintrags) ge-
		  ”ffnet werden soll; normalerweise werden in diesem Fall nur
		  Fenster ge”ffnet, da es recht st”rend ist, wenn alle irgend-
		  wann verwendeten Dialoge automatisch ge”ffnet werden;
		  andererseits k”nnen Sie natrlich auch Fenster vom auto-
		  matischen ™ffnen ausnehmen, indem Sie das Flag in der Fenster-
		  Klasse l”schen }
	end;


procedure TMFDialog.SetupWindow;

	begin
		{ diese Methode wird vom Init-Konstruktor des Dialogs aufgerufen }
		TDialog.SetupWindow;
		{ initialisiert Schnittstellenobjekte fr <Control>+<F>,
		  <Control>+<U> und <Control>+<W> }
		ttmem:=0;
		{ TT-RAM-Bedarf = minimal }
		datei:='';
		pfad:=''
		{ zu Anfang ist keine Datei geladen }
	end;


function TMFDialog.ExitDlg(AnIndx: integer): boolean;

	begin
		{ beim Anklicken eines PushButtons wird die EndDlg-Methode
		  aufgerufen; diese versucht, den Button einem Schnittstellen-
		  objekt zuzuordnen (z.B. wird beim OK-Button [id_OK] auto-
		  matisch die OK-Methode [s.u.] aufgerufen);
		  konnte kein solches Schnittstellenobjekt gefunden werden,
		  wird diese ExitDlg-Methode aufgerufen;
		  liefert sie true zurck, wird der Dialog daraufhin verlassen }
		case AnIndx of
			MFNAME: Application^.Alert(@self,1,NO_ICON,'Datei:|"'+pfad+datei+'"','  &OK  ');
			MFLESS: if ttmem>0 then
								begin
									dec(ttmem);
									{ TT-RAM-Bedarf um 128 KB verringern... }
									UpdateAmount
									{ ... und Bedarf anzeigen }
								end;
			MFMORE: if ttmem<15 then
								begin
									inc(ttmem);
									{ TT-RAM-Bedarf erh”hen }
									UpdateAmount
								end;
			MFDATEI: { neue Datei ausw„hlen, laden und anzeigen... }
							 if FileSelect(@self,'PRG,ACC,TOS ETC. AUSWŽHLEN','',pfad,datei,true) then Load;
			MFMAKE: begin
								with phrec do
									begin
										ph_prgflags:=ph_prgflags and $0ffffff8;
										{ FastLoad-Flags zun„chst ausmaskieren (l”schen)... }
										if cb1^.GetCheck=bf_Checked then
											ph_prgflags:=ph_prgflags or PH_FASTLOAD;
										if cb2^.GetCheck=bf_Checked then
											ph_prgflags:=ph_prgflags or PH_LOADALT;
										if cb3^.GetCheck=bf_Checked then
											ph_prgflags:=ph_prgflags or PH_MALLOCALT;
										PByte(@ph_prgflags)^:=PByte(@ph_prgflags)^ or (ttmem shl 4)
										{ ... und dann evtl. wieder setzen }
									end;
								reset(f);
								write(f,phrec);
								close(f);
								{ Datei aktualisieren }
								DisableAll
								{ nun ist keine Datei mehr aktiv }
							end
		end;
		ExitDlg:=false
		{ Dialog NICHT verlassen }
	end;


function TMFDialog.OK: boolean;

	begin
		Application^.Quit;
		{ Anwendung beenden (sobald der aktuelle Message-Loop
		  beendet ist)... }
		OK:=true
		{ ... und vorher den Dialog verlassen }
	end;


function TMFDialog.Help: boolean;

	begin
		Application^.Alert(@self,1,NOTE,'Bringen Sie den Mauscursor ber|das gewnschte Dialogelement und|drcken Sie die <Help>-Taste|(oder die rechte Maustaste...).','  &OK  ');
		{ dies ist die neue ObjectGEM-Alert-Routine! }
		Help:=false
		{ Dialogbox nicht verlassen }
	end;


procedure TMFDialog.UpdateAmount;
	const atxt : array [0..15] of string[7] =
							('128 KB','256 KB','384 KB','512 KB','640 KB','768 KB',
							 '896 KB','1 MB','1152 KB','1280 KB','1408 KB','1536 KB',
							 '1664 KB','1792 KB','1920 KB','2 MB');

	begin
		st2^.SetText(atxt[ttmem])
		{ TT-RAM-Bedarf anzeigen;
		  die TStatic-Methode SetText ruft automatisch die
		  von TControl geerbte Paint-Methode auf, die das Dialog-
		  element neu zeichnet, wenn der Dialog sichtbar ist }
	end;


procedure TMFDialog.DisableAll;

	begin
		pb7^.SetText('');
		pb7^.Disable;
		{ ... Dateinamen l”schen }
		st1^.Disable;
		st2^.Disable;
		cb1^.Disable;
		cb2^.Disable;
		cb3^.Disable;
		pb2^.Disable;
		pb4^.Disable;
		pb5^.Disable
		{ ... und alle Buttons etc. nicht anw„hlbar machen }
	end;


procedure TMFDialog.Load;
	var cmp: string[4];

	begin
		{ nur bearbeiten, wenn die Datei existiert! }
		cmp:=StrPRight(datei,4);
		{ falscher Dateityp? }
		if (cmp<>'.PRG') and (cmp<>'.APP') and (cmp<>'.TOS') and (cmp<>'.TTP') and (cmp<>'.ACC') and (cmp<>'.GTP') then
			if Application^.Alert(@self,WAIT,2,' Sind Sie sicher, daž| "'+pfad+datei+'"| ein ausfhrbares Programm ist?','&Ja| &Nein ')<>1 then exit;
		pb7^.Enable;
		pb7^.SetText('Date&i: '+datei);
		{ Datei ”ffnen und aktuelle Werte auslesen... }
		assign(f,pfad+datei);
		reset(f);
		read(f,phrec);
		close(f);
		ttmem:=PByte(@phrec.ph_prgflags)^ shr 4;
		st1^.Enable;
		st2^.Enable;
		{ Texte aktivieren... }
		UpdateAmount;
		{ ... und neue Werte anzeigen }
		cb1^.Enable;
		if bTst(phrec.ph_prgflags,PH_FASTLOAD) then cb1^.Check
		else
			cb1^.Uncheck;
		{ es gibt zwar auch eine SetCheck-Methode, aber so
		  ist es doch recht bersichtlich! }
		cb2^.Enable;
		if bTst(phrec.ph_prgflags,PH_LOADALT) then cb2^.Check
		else
			cb2^.Uncheck;
		cb3^.Enable;
		if bTst(phrec.ph_prgflags,PH_MALLOCALT) then cb3^.Check
		else
			cb3^.Uncheck;
		pb2^.Enable;
		pb4^.Enable;
		pb5^.Enable
	end;


begin
  MFApplication.Init('MFST','MakeFast');
  { Anwendung initialisieren;
    bergeben wird ein Cookie (alle ObjectGEM-Anwendungen tragen sich
    nach M”glichkeit fr die Dauer ihrer Ausfhrung in den Cookie-Jar
    ein) und ein String, der bei einem ACC als Meneintrag verwendet
    wird }
  MFApplication.Run;
  { Programm ausfhren... }
  MFApplication.Done
  { ... und korrekt verlassen! }
end.