// F I L E O P S (PREPRESS)
// BCPL/F Filops.Bcpl
//
// Extract(f) Performs extract operation on file f.
// Rename(f) Performs rename operation on file f.
// WidthCalc(f) Perform width merge from file f.
// List(f) Make a listing of a file.
//Modified December 2, 1980 9:33 PM by Lyle Ramshaw:
// Fixed but in Width command processor. It used to compute
// the font bounding box information incorrectly, setting
// FBBdx and FBBdy to the maxima of BBdx and BBdy respectively.
// Instead, one must find the maxima of the coordinates of the
// upper-right corner of the character bounding boxes, and let
// that determine the font bounding box.
//Modified July 6, 1980 9:41 PM by Lyle Ramshaw:
// Moved the patch of Oct. 26, 1979 to FillIX routine from its
// old location in the Extract code, since the bug (GRRR!!!)
// showed up in the delete command, which uses FillIx.
//Modified May 8, 1980 10:56 PM by Lyle Ramshaw, PARC:
// Added Tex Metric IXType. Removed some of the carriage
// returns from List. Restored the FileName/B feature
// for driving List and Extract from the command line.
// Added a MultiChars case to the List command.
// Removed the WriteNewHeaders procedure, which the
// MergeDelete module doesn't need.
//Modified March 11, 1980 10:09 AM by Kerry LaPrade (XEOS)
// Increased List capacity from 100 to 200 names.
//Modified January 11, 1980 1:05 PM (by LaPrade)
// Fixed bug in List() case: IXTypeWidths so that chars
// greater than 277b list correctly.
//Edited by Lyle Ramshaw on Oct. 26, 1979 to patch a bug in
// the Extract command. The "proto" IX which is built up had
// a non-initizlized "type" field. And, if that type should just
// happen, by the luck of the stack, to be the type-code for
// MultiChars, then the CompareIX routine doesn't work, since it
// takes the resolutions from the wrong words.
get "Ix.dfs"
get "Streams.d"
// outgoing procedures
external
[
Extract
Rename
WidthCalc
List
FillIX
]
// incoming procedures
external
[
PrePressWindowInit
//WINDOW
WindowSetPosition
WindowGetPosition
WindowReadBlock
WindowWriteBlock
WindowRead
WindowWrite
WindowCopy
WindowEnd
WindowClose
//UTIL
FSGetX
FSPut
Zero; SetBlock; MoveBlock
ReadIX
WriteIX
CompareIX
PrintIX
ReadIXTempFile
WriteIXTempFile
TypeChar
CheckParams
Scream
IllFormat
IllCommand
//FONTWIDTH
DecodeFace
//SCAN
StrEq
StrCop
TypeForm
//OS
Closes
OpenFile
Puts
//FLOAT
FLD;FST;FTR;FLDI;FNEG;FAD;FSB;FML;FDV;FCM;FSN
FLDV;FSTV;FLDDP;FSTDP;DPAD;DPSB
DPCop
]
// incoming statics
external
[
@fam
@face
@siz
@rotation
@resolutionx
@resolutiony
@params
@outstream
@bigfilename
]
// File-wide structure and manifest declarations.
manifest
[
maxFontNames = 200
]
// Procedures
let
//Extract a font from a file f (AC or SD)
Extract(f,outName,dictName;numargs na) be
[ if na eq 1 then
[ if CheckParams(gotname) eq false then IllCommand()
outName=-f //SDtemp,ACtemp,or WDtemp
dictName=f //SD,CD,or WD
if bigfilename!0 then dictName=bigfilename //or FileName/B
]
let proto=vec IXLMax
FillIX(proto) //Fill in from parameters read
let famseen=false //No code seen yet
let fn=vec IXLName
let d=vec IXLMax
let w=PrePressWindowInit(dictName,false)
if w eq 0 then
[
Scream("Dictionary file does not exist!")
return
]
[ ReadIX(w,d) //Get an entry
switchon d>>IXH.Type into
[
case IXTypeEnd:
TypeForm("No such font in the file*N")
return
case IXTypeName:
[
if StrEq(fam,lv d>>IXN.Name) then
[
famseen=true
proto>>IX.fam=d>>IXN.Code
MoveBlock(fn,d,IXLName)
]
]
endcase
default: if famseen & CompareIX(d,proto) then break
]
] repeat
let ow=PrePressWindowInit(outName,true)
WindowSetPosition(w,lv d>>IX.sa) //Go get it.
WriteIXTempFile(ow,fn,d)
WindowCopy(w,ow,lv d>>IX.len)
WindowClose(w)
WindowClose(ow,-1)
]
and
//Rename -- install new features in a "temp" file.
Rename(f) be [
let wf=PrePressWindowInit(f,true) //Get the file, RW
let fn=vec IXLName //Place for name
let ix=vec IXLMax //and thing.
ReadIXTempFile(wf,fn,ix)
if (params&gotname) ne 0 then
[
Zero(fn,IXLName)
StrCop(fam,lv fn>>IXN.Name)
ix>>IX.fam=0
]
if (params&gotface) ne 0 then ix>>IX.face=face
if (params&gotsize) ne 0 then ix>>IX.siz=siz
if (params&gotrotation) ne 0 then ix>>IX.rotation=rotation
if (params&gotresolution) ne 0 then
[
ix>>IX.resolutionx=resolutionx
ix>>IX.resolutiony=resolutiony
]
WindowSetPosition(wf,table [ 0;0 ])
WriteIXTempFile(wf,fn,ix)
WindowClose(wf,0)
]
and
//LIST command processor. File f is listed.
List(f, fullList, dictName;numargs na) be
[ if na eq 2 then
[
dictName=f //SD,CD, or WD
if bigfilename!0 then dictName=bigfilename //or FileName/B
]
let strp=nil
let sw=PrePressWindowInit(dictName,false,lv strp)
if sw eq 0 then
[ Scream("Dictionary file does not exist");return]
let oa=vec 1; oa!0=0; oa!1=0
outstream=OpenFile("Prepress.Lst", ksTypeWriteOnly, 1) //redirect output
TypeForm("File: ",strp,0)
// let nameList=vec 100
// Zero(nameList,100)
let nameList = vec (maxFontNames - 1)
Zero(nameList, maxFontNames)
[ WindowSetPosition(sw,oa)
let sx=vec IXLMax
ReadIX(sw,sx,true) //If its MultiChars, so be it!!
WindowGetPosition(sw,oa) //So we may get back.
let bc=sx>>IX.bc
let ec=sx>>IX.ec
let nc=ec-bc+1
switchon sx>>IXH.Type into
[
case IXTypeEnd: break
case IXTypeName:
[ if sx>>IXN.Code gr maxFontNames then [ Scream("Name overflow in List");endcase]
let nWords=(sx>>IXN.Name rshift 9)+1
let thisName=FSGetX(nWords)
MoveBlock(thisName,lv sx>>IXN.Name,nWords)
nameList!(sx>>IXN.Code)=thisName
TypeForm("Name: ",lv sx>>IXN.Name,". Code: ",10,sx>>IXN.Code,0)
]
endcase
case IXTypeSplines:
[
TypeForm("Splines: ")
PrintIX(sx,nameList)
if fullList then
[
WindowSetPosition(sw,lv sx>>IX.sa)
for c=bc to ec do
[
let p=vec SplineWidthsize
WindowReadBlock(sw,p,SplineWidthsize)
let pw=lv p>>SplineWidth.WX
unless pw!0 eq 0 & pw!1 eq -1 then
[ //Char exists.
TypeChar(c)
let q=pw
for i=0 to 5 do
[
TypeForm(2,q,$*s); q=q+2
]
TypeForm(0)
if (params&gotsize) ne 0 then
[
FLDI(1, siz); FLDI(2, resolutionx); FLDI(3, 25400)
FML(1,2); FDV(1,3)
TypeForm(" ")
let q=pw
for i=0 to 5 do
[
FLD(2, q); FML(2, 1)
TypeForm(2,2,$*s); q=q+2
]
TypeForm(0)
]
]
]
]
]
endcase
case IXTypeOrbitChars: TypeForm("ORbit Format ")
case IXTypeChars:
[
TypeForm("Characters: ")
PrintIX(sx,nameList)
if fullList then
[
WindowSetPosition(sw,lv sx>>IX.sa)
for c=bc to ec do
[
let p=vec CharWidthsize
WindowReadBlock(sw,p,CharWidthsize)
unless p>>CharWidth.H eq HNonExCode then
[ //Char exists
TypeChar(c)
TypeForm(3,lv p>>CharWidth.WX,#40,3,lv p>>CharWidth.WY,$*s)
TypeForm(10,p>>CharWidth.XL,$*s,10,p>>CharWidth.YB,$*s)
TypeForm(10,p>>CharWidth.W,$*s,10,p>>CharWidth.H,0)
]
]
]
]
endcase
case IXTypeMultiChars:
[
TypeForm("MultiWidth ORbit Char's: ")
PrintIX(sx,nameList)
if fullList then
[
WindowSetPosition(sw,lv sx>>IXM.segs↑1.sa)
for c=bc to ec do
[
let p=vec CharWidthsize
WindowReadBlock(sw,p,CharWidthsize)
unless p>>CharWidth.H eq HNonExCode then
[ //Char exists
TypeChar(c)
TypeForm(3,lv p>>CharWidth.WX,#40,3,lv p>>CharWidth.WY,$*s)
TypeForm(10,p>>CharWidth.XL,$*s,10,p>>CharWidth.YB,$*s)
TypeForm(10,p>>CharWidth.W,$*s,10,p>>CharWidth.H,0)
]
]
]
]
endcase
case IXTypeWidths:
[
TypeForm("Widths: ")
PrintIX(sx,nameList)
if fullList then
[
WindowSetPosition(sw,lv sx>>IX.sa)
let s=vec size WTB/16
WindowReadBlock(sw,s,(size WTB/16))
TypeForm(" Box: ")
for i=0 to 3 do TypeForm(10,s!i,#40)
for what=0 to 1 do
[
TypeForm((what? "*NY: ","*NX: "))
test ((what)? s>>WTB.YWidthFixed, s>>WTB.XWidthFixed)
then TypeForm(10,WindowRead(sw),0)
or [ for c=bc to ec do
[
// if c gr #37 then TypeForm(c)
if c gr #37 then Puts(outstream, c)
TypeForm("(#",8,c,") ")
let wid=WindowRead(sw)
test wid eq #100000
ifso TypeForm("xxx; ")
ifnot TypeForm(10,wid,"; ")
if (c&3) eq 3 then TypeForm(0)
]
TypeForm(0)
]
]
]
]
endcase
case IXTypeTexMetrics:
TypeForm("TEX Metrics: ")
PrintIX(sx,nameList)
endcase
] //Switchon
TypeForm(0)
] repeat
Closes(outstream)
outstream=0 //No more redirection
WindowClose(sw)
]
and
//WIDTH command processor. Build a file WDtemp that contains width
// information. Width information is extracted from file f.
WidthCalc(inputName,outputName;numargs na) be
[ if na eq 1 then
[ inputName=-inputName
outputName=-3
]
let w=PrePressWindowInit(inputName,false)
let ww=PrePressWindowInit(outputName,true)
let fn=vec IXLName
let e=vec IXLMax
ReadIXTempFile(w,fn,e)
WindowSetPosition(w,lv e>>IX.sa)
let t=e>>IXH.Type
let bc=e>>IX.bc
let ec=e>>IX.ec
let nc=ec-bc+1
let fwt=vec size WTB/16 //For font width block.
//We will store the coordinates of the upper right corner of
//the bounding box instead of the bounding box width and height,
//so that we can compute the font bounding box correctly.
MoveBlock(fwt,table [ 16000;16000;-16000;-16000 ],4)
let wx=vec 256*3; SetBlock(wx,#100000,256*3) //All non-existent
let wy=wx+256
let absent=wy+256
test (t eq IXTypeChars)%(t eq IXTypeOrbitChars)
ifso [
FLDI(1,25400);FLDI(2,e>>IX.resolutionx);FDV(1,2)
FLDI(2,25400);FLDI(3,e>>IX.resolutiony);FDV(2,3)
for c=bc to ec do
[
let p=vec CharWidthsize
WindowReadBlock(w,p,CharWidthsize)
unless p>>CharWidth.H eq HNonExCode then
[
absent!c=false
let c2=c*2
FLDDP(3,lv p>>CharWidth.WX);FML(3,1); wx!c=FTRound(3)
FLDDP(3,lv p>>CharWidth.WY);FML(3,2); wy!c=FTRound(3)
FLDI(3,p>>CharWidth.XL);FLDI(4,p>>CharWidth.YB)
FLDI(5,p>>CharWidth.W);FLDI(6,p>>CharWidth.H)
FAD(5,3); FAD(6,4) //convert to upper right corner coords
FontMinMax(1,2,fwt)
]
]
]
ifnot [
FLDI(1,1000)
for c=bc to ec do
[
let p=vec SplineWidthsize
WindowReadBlock(w,p,SplineWidthsize)
let pw=lv p>>SplineWidth.WX
unless pw!0 eq 0 & pw!1 eq -1 then
[
absent!c=false
FLD(2,lv p>>SplineWidth.WX);FML(2,1); wx!c=FTRound(2)
FLD(2,lv p>>SplineWidth.WY);FML(2,1); wy!c=FTRound(2)
FLD(3,lv p>>SplineWidth.XL); FLD(4,lv p>>SplineWidth.YB)
FLD(5,lv p>>SplineWidth.XR); FLD(6,lv p>>SplineWidth.YT)
FontMinMax(1,1,fwt)
]
]
]
WindowClose(w)
//Reset the last two entries of the fwt to be width and height, instead
//of coords of the upper right corner.
fwt!2=fwt!2-fwt!0
fwt!3=fwt!3-fwt!1
//Now decide if either x or y widths are the same
let xwv,ywv=wx!bc,wy!bc
let xsame,ysame=true,true
for c=bc to ec do unless absent!c then
[
if wx!c ne xwv then xsame=false
if wy!c ne ywv then ysame=false
]
fwt>>WTB.XWidthFixed=xsame
fwt>>WTB.YWidthFixed=ysame
//Now write the file
e>>IXH.Type=IXTypeWidths
WriteIXTempFile(ww,fn,e,
(size WTB/16)+((xsame)? 1,nc)+((ysame)? 1,nc))
WindowWriteBlock(ww,fwt,(size WTB/16))
test xsame then WindowWrite(ww,xwv) or
WindowWriteBlock(ww,wx+bc,nc)
test ysame then WindowWrite(ww,ywv) or
WindowWriteBlock(ww,wy+bc,nc)
WindowClose(ww,-1)
]
and
FontMinMax(sx,sy,minmax) be [
for i=0 to 3 do
[
let ac=3+i
FML(ac,(((i&1) eq 0)? sx,sy))
let v=FTR(ac)
test i le 1 then
[ if v ls minmax!i then minmax!i=v ]
or
[ if v gr minmax!i then minmax!i=v ]
]
]
and
FillIX(s) be [
//the Type doesn't really matter, as long as it isn't
//IXTypeMultiChars, since this will make CompareIx screw up.
//But we have to say something...
s>>IX.Type=IXTypeChars
s>>IX.Length=IXLChars
//fill in the other stuff from global variables
s>>IX.face=face
s>>IX.siz=siz
s>>IX.rotation=rotation
s>>IX.resolutionx=resolutionx
s>>IX.resolutiony=resolutiony
]
and FTRound(ac) = valof [
FLDDP(31, table [ 0; #100000 ] ) //.5
FAD(31, ac)
resultis FTR(31)
]