//SilAA.bcpl -- File stuff


get "sysdefs.d"
get "Sil.defs"

static
[
AltS=0; fpAlt; InitS=0; fpSilInit
@AltFilePos =0; @LastAltFilePos =0; @AltLineCnt=0; @LastLineCnt=0
@AltXCoord=0; @AltYCoord=0
]

let FileOut(str) =valof
[
if not str then
[
if not FileName(true,"Output File: ") then resultis false
str = lv(FNameObject>>item.string.length)
]
let S = OpenSilFile(str,0,ksTypeWriteOnly,wordItem)
if S eq 0 then
[
FixFName("Bad Open:")
resultis false
]
//write password
if Changed ne 0 then RemoveBuildMark()
Puts(S,#34562+(VirginSinceBuild? 1,0))

//write out macros
for i = 0 to 127 do //font 4 macros (user) only
[
let link = Mact!i
until link eq 0 do
[
Puts(S,i) //the macro name
WriteItem(S,link)
link = link>>item.link
]
]
// end of macro definitions
let link = FirstItem
until link eq 0 do
[
if (link>>item.state le Selected)&(link>>item.ymin ge 0)&(link>>item.xmax le 2*ScreenXmax)&(link>>item.ymax le 2*ScreenYmax)&(link>>item.ymax gr link>>item.ymin)&(link>>item.xmax gr link>>item.xmin)&((link>>item.font ge 14)%(link>>item.string.length gr 0)) then //only write out good stuff
[
Puts(S,-1) //block header
WriteItem(S,link)
]
link = link>>item.link
]
Closes(S)
FixFName(" ")
resultis true
]

and WriteItem(s,link) be
[
for i = 1 to 4 do Puts(s,link!i)
if link>>item.font ls 14 then
for i = 5 to 5+(link>>item.string.length/2) do Puts(s,link!i)
]

and ReadItem(s) =valof
[
for i = 1 to 4 do NewItem!i = Gets(s)
NewItem>>item.state = Active
if NewItem>>item.font ls 14 then //read in the string
[
NewItem!5 = Gets(s)
if NewItem>>item.string.length gr 1 then
for j = 1 to (NewItem>>item.string.length)/2 do
NewItem!(5+j) = Gets(s)
]
resultis NewItem>>item.font
]


and FileIn(confirm) be
[
if not FileName(confirm,"Input From: ") then return

let stkend = NewItem //end of storage at start of input
let S = OpenSilFile(lv(FNameObject>>item.string.length),0,ksTypeReadOnly,wordItem)
if S eq 0 then
[
FixFName("Can’t Open File ") //remove filename
return
]
let pw = Gets(S)
if VirginSinceBuild then RemoveBuildMark()
VirginSinceBuild = false
test pw eq 34563B then VirginSinceBuild = true
or if pw ne 34562B then
[
Closes(S)
FixFName("Password not 34562B")
return
]
Changed = (NewItem ne SpaceBase)
// If reading in on top of something, changed.
let prev=(lv FirstItem)-offset item.link//find the end of current "Item" list
while prev>>item.link ne 0 do prev=prev>>item.link

until Endofs(S) do //read file
[
let mname = Gets(S)
let font = ReadItem(S) //reads item into NewItem
if (font ls 14)&(font gr 8) then//ck for any library macros used in this block
[
let mindex = Mact+(font-8)*128
for i = 1 to NewItem>>item.string.length do
if mindex!(NewItem>>item.string.char↑i) eq 0 then
mindex!(NewItem>>item.string.char↑i) = -1
]

test mname eq -1
ifso //this is a picture element.
[
if ((NewItem>>item.xmin eq NewItem>>item.xmax) % (NewItem>>item.ymin eq NewItem>>item.ymax)) % (NewItem>>item.ymin ls 0) then loop

//prev = AddToListEnd(prev)//this call inverts order of items read
//the following does the same as AddToList except the order
//of items will be inverted
//this stops SIL output/input from inverting the order of items
//The order is important in press mode so that backgrounds overlap right
test DisplayArea eq 0 //hardcopy mode or screen mode
ifso AddToList(prev) //normal read - dont invert order of items
ifnot //reading into screen mode - invert order of items
[
let l=NewItem
if Usc(l,SpaceTop) gr 0 then CallSwat("No Room")
NewItem>>item.link=0
prev>>item.link=NewItem
NewItem=l+Length(NewItem)
prev = l
//end of code substitute
]

loop
]

ifnot //this block is part of a macro definition in the user’s private macros
[
let m = Mact!mname
if (m ne 0)&(m ls stkend) then //there is a previous definition. We either flush it or loop

[
//for the moment, ALWAYS OVERWRITE CONFLICTING DEFS.

FlushList(m) //remove previous definition
Mact!mname = 0
]

//add the definition to the list
if ((NewItem>>item.xmin eq NewItem>>item.xmax) % (NewItem>>item.ymin eq NewItem>>item.ymax)) then loop
AddToList(lv (Mact!mname))
]
]

Closes(S)

//update any libraries required
for font = 9 to 13 do LibUpdate(font)

if DisplayArea ne 0 then ZapRebuilder() //rebuild the display
FixFName(" ")

]

and AddToList(lvptr) be
[
let l = Length(NewItem)+NewItem
if Usc(l,SpaceTop)gr 0 then
[
Paint(NewItem,toWhite)
Message = "Space Exhausted - item lost"
return
]
NewItem>>item.link = @lvptr
@lvptr = NewItem
NewItem=l
]

and FileName(confirm, str) =valof
[

if DisplayArea eq 0 then resultis true
let xHardCopy = HardCopy
HardCopy=0
Update(str)
Update(str)
FNameObject>>item.xmin = StatusObject>>item.xmax
FNameObject>>item.state = Active //show filename
DisplayObject(FNameObject)//show string
ReWriteObj(FNameObject)
let Doit = confirm? AddText(FNameObject,Gets(keys)), true
//ZapRebuilderItem(FNameObject)//repaint behind string
HardCopy = xHardCopy
if not Doit then
[
FixFName(" ")
resultis false
]
resultis true
]

// Remove the mark left by the BUILD program that indicates virgin drawing.

and RemoveBuildMark() be
[
let p = FirstItem
while p ne 0 do
[
if p>>item.font eq 14 &
p>>item.ymax eq BuildYmax & p>>item.ymin eq BuildYmax-7 then
[
Paint(p,toWhite)//Erase it
ZapRebuilderItem(p)
//And zap rebuilder
p>>item.state=Dead
]
p = p>>item.link
]
VirginSinceBuild = false
]

//now the code for handeling "Alternate text" files ( alias "Analize" files)
//and OpenAltText() =valof
//[
//let NameVec = vec FNameLength
//Zero(fpAlt,5)
//MoveBlock(NameVec,lv FNameObject>>item.string,FNameLength)
//test FileName(true, "Alternate input: ") ifnot Message = " " ifso
//[
//AltS=OpenSilFile(lv(FNameObject>>item.string),fpAlt,ksTypeReadOnly,charItem)
//Message = "Can’t Open File "//set incase open failed
//]
//MoveBlock(lv FNameObject>>item.string, NameVec,FNameLength)
//FixFName(Message) //remove filename
//if not AltS then resultis -1
//LastAltFilePos = 0
//LastLineCnt = 1
//resultis 0
//]


and FindAnalyzeLine() be
[
if AltLineCnt eq 0 do //no file open, so ask for name of file
[
let NameVec = vec FNameLength
Zero(fpAlt,5)
MoveBlock(NameVec,lv FNameObject>>item.string,FNameLength)
test FileName(true, "Alternate input: ") ifnot Message = " " ifso
[
AltS=OpenSilFile(lv(FNameObject>>item.string),fpAlt,ksTypeReadOnly,charItem)
Message = "Can’t Open File "//set incase open failed
]
MoveBlock(lv FNameObject>>item.string, NameVec,FNameLength)
FixFName(Message) //remove filename
if not AltS then return
LastAltFilePos = 0
LastLineCnt = 1
]
if AltS eq 0 do //stream must have been closed for I/O, so open it again
AltS = OpenSilFile(0,fpAlt,ksTypeReadOnly,charItem)
if CtrlShift then [ Message = 1; AltFilePos = LastAltFilePos; AltLineCnt = LastLineCnt ]
if Message eq 0 then [ LastAltFilePos = AltFilePos; LastLineCnt =AltLineCnt ]
[
test (Message eq 0) % (AltLineCnt eq 0)
ifso [ AltFilePos = FilePos(AltS); AltLineCnt = AltLineCnt+1 ]
ifnot SetFilePos(AltS,0,AltFilePos)

NewItem!0=0 //int message to empty
AltXCoord=-1 //init new coordinates to "don’t update"
AppendN(AltLineCnt,NewItem) //enter line number into string
AppendS(": ",NewItem)
let Char = ReadChar(0) //read the first character in the line

if Char eq true then
[
Closes(AltS); AltS=0; AltLineCnt=0
Message = "Done"
return //end of file, restore state
]
if Char eq $*n then loop
//don’t display blank lines
if Char eq $( then //get x,y coordinates if applicable
[ AltXCoord = ExtractVal(); AltYCoord = ExtractVal() ]
Char = ReadChar(true) //reads all remaining characters in current line
if (Char eq $;) then loop
//don’t display lines starting with ";"
//now display the line
if AltXCoord ge 0 then
[
mx=AltXCoord
my=AltYCoord
PushCoords(mx,my)
MoveObjectTo(MarkObject,mx,my)
]
Update(NewItem); Message = 0
return
] repeat
]
and ExtractVal() =valof //get the X,Y coordinates from a line
[
let val = 0
[
let char = ReadChar(0)
if char ls $0 % char gr $9 then resultis val//non zero if char ls 0 or gr 9
val = val*10 + char-$0
] repeat
]
//read the next character from the file, and append to the Message string if the length
//is small enough not to over run the StatusObject space allocation
and ReadChar(fullLine) =valof
[
if Endofs(AltS) then resultis true
let char =Gets(AltS)
if char eq $*n then resultis $*n
if (NewItem>>str.length le 128) & (char ge #40) then AppendC(char,NewItem)
unless fullLine then resultis char
] repeat

and FixFName(str) be //turn off filename
[
if DisplayArea then //don’t do this in press print mode
[
FNameObject>>item.state = 2
Paint(FNameObject,toWhite)
ZapRebuilderItem(FNameObject)
]
Message = str
]

and OpenSilFile(name,hint,direction,itemsize) =valof //turn off filename
[
if InitS ne 0 then [ Closes(InitS); InitS = 0 ]
if AltS ne 0 then [ Closes(AltS); AltS = 0 ]
resultis OpenFile(name,direction,itemsize,0,hint,0,SilZone)
]