//mtv.bcpl

get "streams.d"

external [
// OS
	Wss; Puts; Resets; CallSwat

// MSYMB
	TVtoString

// MCMD
	DisplayError

// Defined here
	StreamFromTextName

// Defined here for init only
	TVSpareTVs; TVSpareTVec; PutTVs; ResetTVs; CloseTVs; BadTVsCall
]

structure TVS :
[	@ST
	NoteP	word
	NoteArg	word
]

static [ TVSpareTVs; TVSpareTVec ]


// Text Vec procedures

// procedures made external

let StreamFromTextName(Act, TV, DotExt, ksType, ItemSize) = valof
[	if TV!0 le 0 then DisplayError("Bad file name")
	Resets(TVSpareTVs)
	let DotFlag = false
	for I = 1 to TV!0 do
	[ let C = TV!I; if (C ge $a) & (C le $z) then C = C & 137B
	  Puts(TVSpareTVs, C); if C eq $.  then DotFlag = true
	]

	if (not DotFlag) & (((DotExt!0) & #377) eq $.)
	  then Wss(TVSpareTVs, DotExt)

	let S = Act(TVtoString(TVSpareTVec), ksType, ItemSize)

	if S eq 0 then DisplayError("unable to open file")
	resultis S
]


//
// local procedures
//

and PutTVs(Stream, Item) be
[	let TV = Stream>>TVS.par1
	let MaxX = Stream>>TVS.par2
	if TV eq 0 then return
	let X = TV!0
	if X < MaxX then
	[ X = X + 1
	  TV!X = Item
	  TV!0 = X
	]
	if Stream>>TVS.NoteP ne 0 then
	  (Stream>>TVS.NoteP)(Stream, Stream>>TVS.NoteArg)
]


and ResetTVs(Stream, TV, N, NoteP, Arg; numargs Nargs) be
[	test Nargs ge 3
	ifso
	[ TV!0 = 0
	  Stream>>TVS.par1 = TV
	  Stream>>TVS.par2 = N
	]
	ifnot
	[ let TV = Stream>>TVS.par1
	  if TV ne 0 then TV!0 = 0
	  if Stream>>TVS.NoteP ne 0 then
	    (Stream>>TVS.NoteP)(Stream, Stream>>TVS.NoteArg)
	]
	if Nargs eq 5 then
	[ Stream>>TVS.NoteP = NoteP
	  Stream>>TVS.NoteArg = Arg
	]
]


and CloseTVs(S) be
[	S>>TVS.par1 = 0
	S>>TVS.par2 = 0
	S>>TVS.NoteP = 0
]


and BadTVsCall(Stream) be CallSwat()