//parsetitle.bcpl
//Look for "title" information at the bottom of the drawing
//
//ParseTitle(0, v, len) -- initializes parser with state vector v of length len
//ParseTitle(1, v, item) -- passes in item to be considered for parsing
//
-- returns 0 if not an interesting entry, otherwise
//
1 for File, 2 for Rev, 3 for Date, or 4 for Page
//ParseTitle(2, v, n, str) -- appends to str the string for thing n (if str exists)
//
returns pointer to string for thing n in any case, or 0 if it does not exist
//
(n=5 implies a "comment string" -- combination of all 4)
//ParseTitle(3, v, stream) -- issue complaints about missing entries
//ParseTitle(4, v) -- returns true if Reference only otherwise 0

get "ana.defs"

manifest nKeywords=4

structure P:
[
lenword
nextGS word
ref word
index↑1,nKeywords word
xloc↑1,nKeywords word
yloc↑1,nKeywords word
dist↑1,nKeywords word
]

structure GS:
[
x word
y word
string: @str
]

let ParseTitle(what, v, a1, a2; numargs na) = valof switchon what into
[
case 0:
[
Zero(v, (size P/16))
v>>P.len=a1; v>>P.nextGS=(size P/16)+v
resultis nil
]

case 1:
[
let font=a1>>item.txtfont
let ix=a1>>item.xmin
let iy=a1>>item.ymin
let ist=lv a1>>item.string
unless iy ge 720 & (font eq 0 % font eq 2 % (font eq 1 & a1>>item.italic eq 1)) then resultis 0
// First, see if the string is a keyword
let keyword=false
for i=nKeywords+1 to nKeywords+3 do if StEq(ist, NameStr(i), nil) then
[ v>>P.ref = i; resultis 0 ]
for i=1 to nKeywords do if StEq(ist, NameStr(i), nil) then
[


v>>P.xloc↑i=ix
v>>P.yloc↑i=iy
keyword=true
break
]
let ourp=-1
unless keyword then ourp=valof
[
// First look to see if already there (for 2 pass operation)
let p=v+(size P/16)
let ns=v>>P.nextGS
while p ne ns do
[
if StEq(ist, lv p>>GS.string) &
ix eq p>>GS.x & iy eq p>>GS.y then resultis p
//Found it
p=p+p>>GS.string.length/2+3
]

// Must make a new string entry in the vector
let len=ist>>str.length/2+3
ns=p+len
if ns-v gr v>>P.len then CallSwat("Too many title strings")
v>>P.nextGS=ns
MoveBlock(lv p>>GS.string, ist, len-2)
p>>GS.x=ix
p>>GS.y=iy
resultis p
]

// Now, look to see if new matches can be made, or if we are already matched
Zero(lv v>>P.index↑1, nKeywords)
SetBlock(lv v>>P.dist↑1, 1000, nKeywords)
let p = v+(size P/16)
while p ne v>>P.nextGS do
[
let mindist=80; let besti=0
for i=1 to nKeywords do
[
let tx,ty=(p>>GS.x-v>>P.xloc↑i),(p>>GS.y-v>>P.yloc↑i)
let dist=(tx+ty)
if tx ge 0 & ty ge 0 & dist le mindist
then [ besti=i; mindist=dist ]
]
if besti ne 0 & mindist le v>>P.dist↑besti then
[
v>>P.index↑besti = p
v>>P.dist↑besti = mindist
]
p=p+p>>GS.string.length/2+3
]
for i=1 to nKeywords do if v>>P.index↑i eq ourp then resultis i
resultis 0
]

case 2:
[
let iMin,iMax=a1,a1; if a1 eq nKeywords+1 then iMin,iMax=1,nKeywords
for i=iMin to iMax do
[
let p=v>>P.index↑i
if p then p=p+(offset GS.string/16)
if na eq 3 then resultis p
if p then
[
AppendS(NameStr(i), a2)
AppendS("=", a2)
AppendS(p, a2)
AppendS(" ", a2)
]
]
if (a1 eq nKeywords+1) & (v>>P.ref ne 0) then
[ AppendS(NameStr(v>>P.ref), a2); AppendS(" ", a2) ]
resultis nil
]

case 3:
[
for i=1 to nKeywords do if v>>P.index↑i eq 0 then
[
Wss(a1, "*nUnable to find title entry for ")
Wss(a1, NameStr(i))
]
resultis nil
]
case 4: resultis v>>P.ref? true,false
]

and NameStr(n) = selecton n into
[
case 1: "File"
case 2: "Rev"
case 3: "Date"
case 4: "Page"
case 5: "Documentation"
case 6: "Reference"
]