// P A R T S   
// errors 300
//
//Stuff for dealing with "parts" of windows.
//
// SetPartBounds(window,frec,nrecs)
//	Sets bounds on "window" starting at Press record # frec,
//	and going for nrecs.
// GetPositioninPart(window,dp [, itemSize])
//	Returns dp position within bounds.
// SetPositioninPart(window,dp [, itemSize])
//	Sets position relative to bounds.
// SetBytePositioninPart(window,bdp)
//	bdp is BYTE position relative to bounds.
// SkipinPart(window,how,n)
//	Skips n "things"
//	how=0	n in bytes
//	how=1	n in words
//	how=2	n is dp word count
//	how=3	n is dp byte count
//

get "Spruce.d"
get "Sprucefiles.d"

// outgoing procedures
external
	[
	SetPartBounds
	GetPositioninPart
	SetPositioninPart
	SetBytePositioninPart
	SkipinPart
	]

// incoming procedures
external
	[
//WINDOW,FILES
	WindowCreateStream
	WindowClose
	WindowGetPosition
	WindowSetPosition
	WindowReadBlock
	WindowReadByte
	WindowFlush
	WindowSetBounds
	WindowGetBounds
	WindowFile
	FileLeng

//SPRUCE
	SpruceError
	SpruceCondition
	DblShift

//OS
	MoveBlock

//SPRUCEML
	MulDiv
	DoubleAdd; DoubleSub; DoubleCop
	]

// Procedures

//"Part" functions

let SetPartBounds(w, frec, nrecs) be
 [
   let fileCode = w>>SS.spruceFile>>SPruceFile.fileCode
//Get file size
   let fsiz=vec 1
   FileLeng(WindowFile(w), fsiz)		//Get file size
//Now convert to Press records
   DblShift(fsiz, LogPressRecordSize)
   if fsiz!0 then SpruceCondition(300, ECFileTerminate, fileCode)	//Too big
   let nPressRecs=fsiz!1		//All for this

   if frec ls 0 % nrecs ls 1 % frec+nrecs-1 ge nPressRecs then
	SpruceCondition(301, ECFileTerminate, fileCode)		//Part bounds wrong

//Record part starting position
	let gsiz=vec 1
   gsiz!0=0
   gsiz!1=frec
   DblShift(gsiz, -LogPressRecordSize)
//Record part length
   fsiz!1=nrecs
   DblShift(fsiz, -LogPressRecordSize)
   DoubleAdd(fsiz, gsiz)		//End of area.
//Set up the bounds
	WindowSetBounds(w, gsiz, fsiz)
 ]


and GetPositioninPart(w, p, itemSize; numargs na) be
 [
   if na < 3 then itemSize = wordItem
   WindowGetPosition(w, p, itemSize)
   let bsiz =vec 1
   WindowGetBounds(w, bsiz, 0, itemSize)
   DoubleSub(p, bsiz)
 ]

and SetPositioninPart(w,p, itemSize; numargs na) be
 [
   if na<3 then itemSize = wordItem
   let bpos=vec 1
   let epos=vec 1
   WindowGetBounds(w, bpos, epos, itemSize)
//Condition is: len-position => 0
   DoubleSub(epos, bpos)	// epos=length
   DoubleSub(epos, p);
   let fileCode = w>>SS.spruceFile>>SPruceFile.fileCode
   if p!0 ls 0 % epos!0 ls 0 then SpruceCondition(302, ECFileTerminate, fileCode)
   DoubleAdd(bpos, p)
   WindowSetPosition(w, bpos, itemSize)
 ]

and SetBytePositioninPart(w, p) be SetPositioninPart(w, p, charItem)

and SkipinPart(w, how, n) be
 [
//Get current byte pos.
   let t=vec 1
   GetPositioninPart(w, t, charItem)
//Convert n to bytes
   let s=vec 1
   s!0=0; s!1=n
   if how ne 0 then
     [
      if how ge 2 then DoubleCop(s, n)
      if how ne 3 then DblShift(s, -1)
     ]
//Now set position to pos+n
   DoubleAdd(s, t)
   SetBytePositioninPart(w, s)
 ]

// DCS, July 27, 1977  11:29 PM, simplify part-position
//   modifications via SpruceFile features
// August 7, 1977  10:14 AM, modify error managemento
// June 14, 1978  8:44 PM, add how=3 to SkipInPart
//