// PressInstall.bcpl

// last modified by Ramshaw, November 29, 1983  10:18 AM
// - Add RavenPowerOnFlag as InstallPrompt #28.
// - PressInstall, put query for landscape mode (back?) in Versatec install - 4/6/81
// - PressInstall, have 15 extended rectangle BESizes - 10/15
// - SLOTScanLength and printerMaxBitsPerScan, make unsigned - 10/13
// - ResolutionB, ResolutionS, 1X instead of 10X - 10/13/80

//  errors 250
//
// PRESS INSTALLATION
//
//last InstallPrompt index used: 28

get "PressInternals.df"
get "PressParams.df"
get "AltoFileSys.d"
get "Disks.d"
get "Streams.d"
get "SysDefs.d"
get "BcplFiles.D"

// outgoing procedures
external
	[
	PressInstall
	]

// outgoing statics
external
	[	tridentVec
	]
static
	[	tridentVec
	]

// incoming procedures
external
	[
//PRESSINITUTILS
	GetFileName
	GetFileStatic
	IndexFile
	SetupDrive1
	CloseDrive1

//PRESS
	PressError

//PRESSML
	DoubleAdd
	Ugt
	MulDiv

//Used for initialization of files, etc. -- removed by Junta
	OpenFile
	DeleteFile
	Closes
	Gets
	Puts
	Endofs
	ReadBlock
	WriteBlock
	FileLength
	Resets
	PositionPage
	SetFilePos

//WINDOW
	WindowInit
	WindowClose
	WindowWriteBlock

//SCAN
	TypeForm
	ReadNumber

//FLOAT
	FLDI; FDV; FML; FTR; FAD; FSB;

//ALLOC
	InitializeZone
	Allocate

//OS
	MoveBlock
	Zero

//TFS
	TFSInit
	TFSClose
	TFSCreateDDMgr
	TFSDiskModel
	]

// incoming statics
external
	[
	MeterFile
	BitsFile
	tridentUsed

	PaperSpeedInches
	printerDevice
    RavenPowerOnFlag
	printerForward
	portrait
	ResolutionS	
	ResolutionB	
	PaperDimensionS
	PaperDimensionB
	VersatecMsSl
	VersatecFF
	printerMaxBitsPerScan
	nPrinterColors

	DPzero
	BESizes
	DoFileMeter
	DoFaultMeter
	DoMeter
	Debug
	SoftScan	//true if no ORbit use
	blockBitsFile
	UseMicroCode
	DoEtherReport

	OverlayTable
	OverlayReloc

	sysDisk
	PressZone

	ScreenModulus
	ScreenMagnitude
	ScreenAngle

	SLOTScanLength
	ScanLengthInches
	SLOTBitMarginAdjust
	SLOTScanMarginAdjust
	SLOTDouble
	SLOTTimeOut
	]

// internal statics
static
	[
	defaultVec
	]

// File-wide structure and manifest declarations.

manifest nDefaults=40		//Only need change in this file!!

structure STR[
	length byte
	char↑1,255 byte
	]

// Procedures

let PressInstall(cfa, hintState) be
[
	Zero(hintState, lFP)
	let st=OpenFile("Press.State",0,0,0,hintState)
	hintState!lFP=@#430			//Get real time clock bits

//First thing in the file is the "time stamp":
	Puts(st, hintState!lFP)

//Second thing in the state file is a list of default values of various things,
// up to nDefaults of them.  Read into defaults vector:
	let defaults=vec nDefaults+1
	Zero(defaults, nDefaults+1)
	defaultVec=defaults+1		//defaultVec!-1=true if defaults valid
	test Endofs(st) then
	   [ Puts(st, nDefaults); WriteBlock(st, defaults, nDefaults) ] or
	   [ Gets(st); ReadBlock(st, defaultVec, nDefaults); defaultVec!-1=true ]

//Various statics
	DoMeter=InstallPrompt("General installation parameters:*n   Record metering information",0)
	DoFileMeter=InstallPrompt("   Meter each file transfer",1)
	DoFaultMeter=InstallPrompt("   Meter each character fault",2)
	UseMicroCode=InstallPrompt("   Normally use microcode",3)
	DoEtherReport=InstallPrompt("   Log statistics on MAXC",4)
	SaveStatic(st, lv DoMeter)
	SaveStatic(st, lv DoFileMeter)
	SaveStatic(st, lv DoFaultMeter)
	SaveStatic(st, lv UseMicroCode)
	SaveStatic(st, lv DoEtherReport)

// Set output device stuff.  Printer codes are defined in PressInternals.df
	printerDevice=InstallPrompt("Printer parameters:*n   Output device (Dover,Sequoia,Pimlico,Penguin,Puffin,Durango,Slot,Versatec,Hg)",5,3)
	if printerDevice eq printerSlot then 
     RavenPowerOnFlag=InstallPrompt("  Is Slot really a Raven", 28)   
    ResolutionB = InstallPrompt("   Resolution in bits/inch", 6, 1);
	ResolutionS = InstallPrompt("   Resolution in scans/inch", 7, 1);
	printerForward=true
	portrait=true
	blockBitsFile=false
	printerMaxBitsPerScan=10000
	SoftScan=printerDevice ge printerDurango	//true if no ORbit
	SaveStatic(st,lv SoftScan)
	nPrinterColors=1
	switchon printerDevice into
	 [ case printerPimlico:
		case printerSequoia:
	   case printerDover: 
		case printerPuffin:
		PaperSpeedInches=InstallPrompt("   Paper speed (inches/second)",26,2)
	   case printerSlot:
		[
		if (printerDevice eq printerPimlico)%
			(printerDevice eq printerPuffin)%
			(printerDevice eq printerSlot) do 
			nPrinterColors=InstallPrompt("   Number of printer colors",27,1)
		blockBitsFile=true
		printerForward=InstallPrompt("   Does the first page printed emerge at the top of a stack",8)
		portrait=InstallPrompt("   Does the Slot run in portrait mode",9)
		SLOTScanLength=InstallPrompt("   Scan line length in bits (for Slot)",10,1)
		if SLOTScanLength eq 0 then  // overflowed?
		   [
		   FLDI(2, #77777); FSB(1,2); SLOTScanLength = FTR(1);
		   if SLOTScanLength eq 0 then PressError(254);  // too long!
		   SLOTScanLength = SLOTScanLength + #77777;
		   ]
		printerMaxBitsPerScan=SLOTScanLength
		SLOTScanMarginAdjust=InstallPrompt("   Scan margin adjustment",11,1)
		SLOTBitMarginAdjust=InstallPrompt("   Bit margin adjustment",12,1)

		if printerDevice ne printerSlot then endcase
		SLOTDouble=InstallPrompt("   Do you want scan-lines doubled",13)
		SLOTTimeOut=InstallPrompt("   How many seconds before timing out printer (10 secs suggested)",25,1)
		endcase
		]
	case printerVersatec:
		[
		portrait=InstallPrompt("   Should top of Press page emerge first (as opposed to left edge)",9)
		printerMaxBitsPerScan=InstallPrompt("   Total number of bits per scan-line",22,1)
		let ffBefore=InstallPrompt("   Number of form-feeds prior to printing",23,1)
		let ffAfter=InstallPrompt("   Number of form-feeds after printing",24,1)
		VersatecFF=256*ffBefore+ffAfter
		endcase
		]
	 ]
	SaveStatic(st, lv nPrinterColors)
	SaveStatic(st, lv PaperSpeedInches)
	SaveStatic(st, lv printerDevice)
    SaveStatic(st, lv RavenPowerOnFlag)
	SaveStatic(st, lv ResolutionB)
	SaveStatic(st, lv ResolutionS)
	SaveStatic(st, lv printerForward)
	SaveStatic(st, lv portrait)
	SaveStatic(st, lv SLOTScanLength)
	SaveStatic(st, lv SLOTScanMarginAdjust)
	SaveStatic(st, lv SLOTBitMarginAdjust)
	SaveStatic(st, lv SLOTDouble)
	SaveStatic(st, lv SLOTTimeOut)
	SaveStatic(st, lv VersatecMsSl)
	SaveStatic(st, lv VersatecFF)
	SaveStatic(st, lv blockBitsFile)
	SaveStatic(st, lv printerMaxBitsPerScan)

//Paper sizes.  Will have to exchange if portrait mode.
	PaperDimensionB=InstallPrompt("Paper parameters:*n   Long dimension",14,2)
	PaperDimensionS=InstallPrompt("   Short dimension",15,2)
	if portrait then
	  [ let t=PaperDimensionB; PaperDimensionB=PaperDimensionS; PaperDimensionS=t ]
	ScanLengthInches = MulDiv(SLOTScanLength, 10, ResolutionB);
	SaveStatic(st, lv PaperDimensionB)
	SaveStatic(st, lv PaperDimensionS)
	SaveStatic(st, lv ScanLengthInches)

//Halftone parameters
	ScreenModulus=
	   InstallPrompt("Halftone parameters:*n   Screen frequency <lines per inch>",16,1)
	ScreenMagnitude=InstallPrompt("   Screen amplitude <% of dynamic range>",17,1)
	ScreenAngle=InstallPrompt("   Screen angle",18,1)
	SaveStatic(st, lv ScreenModulus)
	SaveStatic(st, lv ScreenMagnitude)
	SaveStatic(st, lv ScreenAngle)

//See what disks he wants:
	let z=vec 3000
	PressZone=InitializeZone(z, 3000)
	let tv=vec 8*3;tridentVec=tv
	Zero(tridentVec,8*3)

	tridentUsed=InstallPrompt("Disk information:*n   Do you want to use Trident disk(s)",19)
	if tridentUsed then
		[
		//there are Trident drive nos 0-7, each with up to 3 file systems
		//allow user to grab any or all
		let ddmgr=TFSCreateDDMgr(PressZone)
		let noTrident=true
		for t=0 to 8*3-1 do
		 [ tridentVec!t=
				TFSInit(PressZone,true,(2-(t rem 3))*#400 + (7-(t/3)),ddmgr)
			if tridentVec!t ne 0 then noTrident=false
		 ]
		if noTrident then TypeForm("Cannot operate any Trident disk!*n")
		]
	if InstallPrompt("   Do you want to use drive 1 of the Model 31",21) then
		if SetupDrive1() eq 0 then TypeForm("Cannot operate the second drive!*n")

//Now initialize all the known files:
	let p=vec 3000
	for f=0 to 7 do
	   [
	   let len=IndexFile(p, f, GetFileName(f))
	   if len eq 0 then PressError(250)
	   let a=GetFileStatic(f)
		if a eq lv BitsFile then //test for T80 or T300
		 [ let disk=p>>F.Device
			if disk ge 2 then tridentUsed =
				(TFSDiskModel(tridentVec!(disk-2)) eq 80)?5,19	//nHeads
		 ]
	   @a=p
	   SaveStatic(st, a, len)
	   if f eq FILEMeter then
		[
		//Meter file needs initializing
		let a=WindowInit(MeterFile)
		WindowWriteBlock(a, (table [ 0;2 ] ),2)	//Current length
		WindowClose(a)
		]
	   ]

	SaveStatic(st, lv tridentUsed)
	CloseDrive1()
	if tridentUsed then 
		for t=0 to 8*3-1 do 
			if tridentVec!t ne 0 then TFSClose(tridentVec!t,true)

//Set up table that gives sizes of all BE entries:
	BESizes=p
	BESizes!BESyncH=size BESync/16
	BESizes!BECopyH=size BECopy/16
	BESizes!BERectangleH=size BERectangle/16
	BESizes!BELineH=size BELine/16
	BESizes!BESplineH=size BESpline/16
	BESizes!BEEndObjectH=size BEEndObject/16
	BESizes!BEDotsH=size BEDots/16
	BESizes!BEEndH=size BEEnd/16
	for i = BEExtendedRectangleH to BELastRectangleH do
	 BESizes!i = size BERectangle / 16;
	SaveStatic(st, lv BESizes, BEMaxH+1)

//Now go down the Press.Run file and find all the overlays (page numbers)

	let ovTab=vec 20
	let ovNum=0
	let s=OpenFile("Press.Run", ksTypeReadWrite)
	let pn=cfa>>CFA.fa.pageNumber
	   [
		PositionPage(s, pn)
		if Endofs(s) then break
		let v=vec 15
		ReadBlock(s, v, 16)
		if v!2 ne 1 % v!5 ne pn-1 then PressError(251)
		ovTab!ovNum=pn
		ovNum=ovNum+1
		pn=pn+(v!4 + 255)/256
	   ] repeat
	OverlayTable=ovTab
	SaveStatic(st, lv OverlayTable, ovNum)

//Now ramble down Press.Run and plug in the hintState
	Resets(s)
	let v=vec (size BLV/16)+(size SV.H/16)
	ReadBlock(s, v, (size BLV/16)+(size SV.H/16))
	let ns=(size BLV/16)+(size SV.H/16)+#300
	ns=ns+v>>SV.BLV.endOfStatics-v>>SV.BLV.startOfStatics+1
	ns=ns+hintState-v>>SV.BLV.startOfCode
	SetFilePos(s, 0, ns*2)
	WriteBlock(s, hintState, lFP+1)	//Write in the magic fp.
	Closes(s)

	OverlayReloc=v>>SV.BLV.relPairTable
	SaveStatic(st, lv OverlayReloc)

//Save sysDisk, because it will be Junta'ed away
	SaveStatic(st, lv sysDisk, (size DSK/16)+lKDHeader)

//Any other state to be saved goes here.....
	Puts(st, 0)		//Termination
	SetFilePos(st, 0, 1*2)
	Puts(st, nDefaults)
	WriteBlock(st, defaultVec, nDefaults)
	Closes(st)

	finish
]

//InstallPrompt(string, defaultIndex, type)
//	type=0 (default) Yes/No
//	type=1 simple number
//	type=2 number*10
//	type=3 lookup a string and return its index

and InstallPrompt(str, defaultIndex, type; numargs n) = valof
[	let GetInstallString(i) = selecton i into
	 [	case printerDover: "Dover"
		case printerSequoia: "Sequoia"
		case printerPimlico: "Pimlico"
		case printerPenguin: "Penguin"
		case printerPuffin: "Puffin"
		case printerDurango: "Durango"
		case printerSlot: "Slot"
		case printerVersatec: "Versatec"
		case printerHg: "Hg" 
	]

	if n eq 2 then type=0
	if defaultIndex ge nDefaults then PressError(253)
	let defVal=defaultVec!defaultIndex
	TypeForm(str);
	if defaultVec!-1 then	//Defaults valid
	[
	TypeForm($();
	switchon type into
		[
		case 0: TypeForm((defVal? "Yes","No"))
			endcase
		case 1: TypeForm(10, defVal)
			endcase
		case 2: FLDI(1, defVal)
			FLDI(2,10); FDV(1,2)
			TypeForm(2,1)
			endcase
		case 3: TypeForm(GetInstallString(defVal))
		]
	TypeForm($))
	]
	let ans=vec 20
	TypeForm((type eq 0? $?, $:),1,ans)
	if ans>>STR.length eq 0 then resultis defVal
	let res=nil
	switchon type into [
	case 0: [
		let c=ans>>STR.char↑1
		res=( c eq $y % c eq $Y)
		endcase
		]
	case 3: [
		let match=nil
		[
		for i=0 to 9 do
			[
			let s=GetInstallString(i)
			match=true
			for j=1 to ans>>STR.length do
			   [
			   if ((ans>>STR.char↑j xor s>>STR.char↑j)&(not #40)) ne 0 then
				match=false
			   ]
			if match then [ res=i; break ]
			]
		if match then break
		TypeForm("Invalid response, try again: ",1,ans)
		] repeat
		endcase
		]
	default: [
		res=ReadNumber(ans)
		if type eq 2 then
			[
			FLDI(2,20); FML(1,2)
			res=(FTR(1)+1)/2	//Round
			]
		endcase
		]	
	]
	defaultVec!defaultIndex=res
	resultis res
]

// State saving and restoring for static values (and vectors)

and SaveStatic(stream, staticAdr, len; numargs n) be
[
	if n ne 3 then len=0
	Puts(stream, staticAdr)
	Puts(stream, len)
	test len eq 0 then Puts(stream, staticAdr!0)
	       or WriteBlock(stream, staticAdr!0, len)
]