// P R E P R E S S U T I L // //Bcpl/f PrepressUtil.bcpl // //Last modified September 25, 1980 1:46 PM, PARC // Changed TEX face encooding/decoding to run backwards. // //Modified September 12, 1980 5:51 PM by Lyle Ramshaw, PARC // Made IXLength external. // //Modified April 22, 1980 9:32 AM by Lyle Ramshaw, PARC // Changed EncodeFace and DecodeFace to allow for CMU and TEX faces. // //Modified February 28, 1980 10:48 AM by Kerry A. LaPrade, XEOS // Put IllFormat call in ReadIX(). // //Modified January 22, 1980 7:18 PM (by LaPrade) // //Assorted utilities for PREPRESS. // // FSInit(StackSize) // Currently a hack to initialize McCreight's alloc. // FSGet(size, [even]) // Tries to get a block of size "size". Returns pointer or zero. // FSGetX(size, [even]) // Like FSGet, but complains if core unavailable. // FSGetBiggest(lvSize) // Gets biggest available block, returns it and sets @lvSize // FSPut(ptr) // Release block seized by FSGet or FSGetX // // DPCop(to,from) // Copies double precision number // DblShift(dp,amount) // Shift double precision number by "amount" (>0 is to the right) // MulDiv(a,b,c) // Returns a*b/c (rounded) // RoundDp(a) -- rounds double-precision integer & returns integer part get "ix.dfs" get "goodfoo.d" //for STRING only // outgoing procedures external [ FSInit FSGet FSGetX FSGetBiggest FSPut DPCop DblShift RoundDp RoundFP Scream IllCommand NoFile IllFormat TypeChar EncodeFace DecodeFace ReadIX WriteIX ReadIXTempFile WriteIXTempFile CompareIX PrintIX CheckAC IXLength GetPosRelative SetPosRelative ] // outgoing statics external [ @prePressZone ] static [ @prePressZone ] // incoming procedures external [ // OS InitializeZone Usc // WINDOW WindowGetPosition WindowSetPosition WindowRead WindowWrite WindowReadBlock WindowWriteBlock // SCAN ReadNumber PrintNumber TypeForm AppendChar StrCop // FLOAT DPSB; FSTV; FLDV; FAD; FSN; FNEG; FTR; FLD; FSTDP // PRESSML MulDiv ] // incoming statics //external // [ // ] // internal statics static [ @FSTrap //Set to adr of fs cell. ] //Free storage functions //********************************************************* let FSInit(StackSize) be //********************************************************* [ let first=@#335 //first free location let last=(lv first)-StackSize //Leave that much room let Size=last-first if Usc(Size, #77777) ge 0 then Size=#77776 @#335=first+Size+1 prePressZone=InitializeZone(first, Size, SysErr, 0) ] //********************************************************* and FSGet(Size, even; numargs n) = valof //********************************************************* [ if n eq 1 then even=false let ptr=Allocate(prePressZone, Size, -1, even) if FSTrap ne 0 & ptr eq FSTrap then CallSwat("Free Storage trap") resultis ptr ] //********************************************************* and FSGetX(Size, even; numargs n) = valof //********************************************************* [ if n eq 1 then even=false let p=FSGet(Size, even) if p eq 0 then Scream("Out of memory space. How big is your SysFont.AL?") resultis p ] //********************************************************* and FSGetBiggest(lvSize) = valof //********************************************************* [ Allocate(prePressZone, 77777b, lvSize) resultis Allocate(prePressZone, @lvSize) ] //********************************************************* and FSPut(ptr) be //********************************************************* [ if ptr eq FSTrap then CallSwat("Free Storage trap") Free(prePressZone, ptr) ] //Miscellaneous numerical functions //********************************************************* and DPCop(top,fromp) be //********************************************************* [ top!0 = fromp!0 top!1 = fromp!1 ] //********************************************************* and DblShift(dblwordlv,amount) = valof //********************************************************* [ test amount ls 0 then //Left shift [ amount=-amount let temp=(dblwordlv!1) rshift (16-amount) @dblwordlv=(@dblwordlv lshift amount)+temp dblwordlv!1=(dblwordlv!1) lshift amount ] or [ let temp=@dblwordlv lshift (16-amount) @dblwordlv=@dblwordlv rshift amount dblwordlv!1=((dblwordlv!1) rshift amount)+temp ] resultis dblwordlv!1 //low order 16 bits ] //********************************************************* and RoundDp(a)= valof //********************************************************* [ let half=vec 2; half!0=0; half!1=#100000 DoubleAdd(half,a) resultis half!0 ] //********************************************************* and RoundFP(fp) = valof //********************************************************* [ let sv=vec 4 FSTV(10, sv) FLD(10, fp) let negative=(FSN(10) eq -1) if negative then FNEG(10) FAD(10, table [ 40100b; 0 ] ) // 0.5 let a=FTR(10) FLDV(10, sv) resultis (negative? -a,a) ] //Miscellenous utilities: //********************************************************* and Scream(str) be //********************************************************* [ let strvec=vec 20 TypeForm("Scream: ",str,1,strvec) ] //********************************************************* and IllCommand() be //********************************************************* [ TypeForm("Illegal command.") finish ] //********************************************************* and IllFormat() be //********************************************************* [ Scream("Illegal file format.") finish ] //********************************************************* and NoFile(s) be TypeForm("File does not exist: ",s,0) //********************************************************* //********************************************************* and TypeChar(c) be //********************************************************* [ let foo=c+#400 //String, length 1 TypeForm(" Character: ",lv foo," (#",8,c,$)) ] //********************************************************* and CheckAC(p) be [ //********************************************************* if p>>CharWidth.W ge (1 lshift size FHEAD.ns) % p>>CharWidth.H ge (1 lshift size FHEAD.hw)*16 then Scream("Character too big for file format!!") ] // EncodeFace, DecodeFace //EncodeFace(str) => 8-bit face code. // If str will read as a number, then interpret as size in // logical points, and return byte form. Otherwise, take // the first up to four characters as weight, slope, expansion, // and character set, and enode them. Omitted characters // are defaulted to MRRX. Error return is -1. //DecodeFace(face, str) // Takes 8-bit face code and stores into the specified string // (which must have length at least 4) the descriptive // characters, or the number of logical points. //********************************************************* and EncodeFace(str) = valof //********************************************************* [ let nonnumeric=nil ReadNumber(str,1,lv nonnumeric) test nonnumeric ifnot [ // We round the floating point logical size // to units of half-points: let dptemp=vec 1 FSTDP(1,dptemp); DblShift(dptemp,-1) let logicalSize=RoundDp(dptemp) if (logicalSize ge 0) & (logicalSize le 200) then resultis 254-logicalSize resultis -1 ] ifso [ let weight,slope,expansion,charset=0,0,0,0 for i=Min(str>>STRING.length,4) by -1 to 1 do (lv weight)!(i-1)=str>>STRING.char↑i let w=(selecton weight into [ case 0: case $M: case $m: 0 case $B: case $b: 2 case $L: case $l: 4 default: -100 ]) + (selecton slope into [ case 0: case $R: case $r: 0 case $I: case $i: 1 default: -100 ]) + (selecton expansion into [ case 0: case $R: case $r: 0 case $C: case $c: 6 case $E: case $e: 12 default: -100 ]) + (selecton charset into [ case 0: case $X: case $x: 0 case $A: case $a: 18 case $O: case $o: 36 default: -100 ]) if w ls 0 then resultis -1 resultis w ] ] //********************************************************* and DecodeFace(face,str) be //********************************************************* [ if str>>STRING.length ls 4 then Scream("Can't decode face into string this short!") if face eq 255 then //escape value [ StrCop("********", str) //4 of the *'s are quotes return ] if (face le 254) & (face ge 54) then //TEX faces [ let logicalSize=254-face PrintNumber(str,logicalSize/2,10) if (logicalSize&1) ne 0 then [ AppendChar($., str) AppendChar($5, str) ] return ] if (face le 53) & (face ge 0) then //standard faces [ str>>STRING.char↑2=(table [ $R; $I ])!(face&1) face=face rshift 1 str>>STRING.char↑1=(table [ $M; $B; $L ])!(face rem 3) face=face/3 str>>STRING.char↑3=(table [ $R; $C; $E ])!(face rem 3) face=face/3 str>>STRING.char↑4=(table [ $X; $A; $O ])!(face rem 3) str>>STRING.length=3 if face then str>>STRING.length=4 return ] Scream("Face value exceeds one byte!") ] //Routines for dealing with "temporary" index files, IX entries, etc. //********************************************************* and ReadIX(w,v,tellTheTruth;numargs na) = valof //********************************************************* [ if na ls 3 then tellTheTruth=false //Read an IX entry into vector v. Return length let a=WindowRead(w) let l=a<<IXH.Length if l gr IXLMax then IllFormat() v!0=a WindowReadBlock(w,v+1,l-1) if tellTheTruth%(a<<IXH.Type ne IXTypeMultiChars) then resultis l //lie to me: replace the multi char structure with OrbitChars let curSA,curLen=vec 1,vec 1 MoveBlock(curSA,lv v>>IXM.segs↑1.sa,2) MoveBlock(curLen,lv v>>IXM.segs↑1.len,2) let resx=v>>IXM.resolutionx let resy=v>>IXM.resolutiony v>>IX.Type=IXTypeOrbitChars MoveBlock(lv v>>IX.sa,curSA,2) MoveBlock(lv v>>IX.len,curLen,2) v>>IX.resolutionx=resx v>>IX.resolutiony=resy ] //********************************************************* and WriteIX(w,typ,v; numargs nargs) be //********************************************************* [ if typ eq -1 then typ=v>>IXH.Type let a=nil if nargs eq 2 then v=lv a let len=IXLength(typ) v>>IXH.Length=len v>>IXH.Type=typ WindowWriteBlock(w,v,len) ] //********************************************************* and ReadIXTempFile(w,f,x) be //********************************************************* [ ReadIX(w,f) unless f>>IXH.Type eq IXTypeName then IllFormat() ReadIX(w,x) let t=x>>IXH.Type unless t eq IXTypeSplines % t eq IXTypeChars % t eq IXTypeWidths % t eq IXTypeOrbitChars % t eq IXTypeTexMetrics then IllFormat() let u=vec 5 ReadIX(w,u) unless u>>IXH.Type eq IXTypeEnd then IllFormat() ] //********************************************************* and WriteIXTempFile(w,f,x,len; numargs nargs) be //********************************************************* [ if nargs eq 4 then [ let p=lv x>>IX.len p!0=0; p!1=len ] let p=lv x>>IX.sa p!0=0 p!1=IXLName+IXLEnd+IXLength(x>>IXH.Type) WriteIX(w,IXTypeName,f) WriteIX(w,-1,x) WriteIX(w,IXTypeEnd) ] //********************************************************* and IXLength(typ) = //********************************************************* selecton typ into [ case IXTypeName: IXLName case IXTypeEnd: IXLEnd case IXTypeSplines: IXLSplines case IXTypeOrbitChars: IXLChars case IXTypeChars: IXLChars case IXTypeMultiChars: IXLMulti case IXTypeWidths: IXLWidths case IXTypeTexMetrics: IXLTexMetrics ] //********************************************************* and CompareIX(a,b) = valof //********************************************************* [ let sizDiff=a>>IX.siz-b>>IX.siz let aresx,aresy,bresx,bresy=nil,nil,nil,nil test a>>IX.Type eq IXTypeMultiChars then [ aresx=a>>IXM.resolutionx;aresy=a>>IXM.resolutiony] or [ aresx=a>>IX.resolutionx;aresy=a>>IX.resolutiony] test b>>IX.Type eq IXTypeMultiChars then [ bresx=b>>IXM.resolutionx;bresy=b>>IXM.resolutiony] or [ bresx=b>>IX.resolutionx;bresy=b>>IX.resolutiony] let charType=(a>>IX.Type eq IXTypeChars)% (a>>IX.Type eq IXTypeOrbitChars) % (a>>IX.Type eq IXTypeMultiChars) resultis (a>>IX.famface eq b>>IX.famface) & ((sizDiff ge -1)&(sizDiff le 1)) & (a>>IX.rotation eq b>>IX.rotation) & ( (not charType) % ((aresx eq bresx) & (aresy eq bresy)) ) ] //********************************************************* and PrintIX(ix,nameList;numargs na) be //********************************************************* [ //Print out an ix entry let nameStr=(na ls 2)?0,nameList!(ix>>IX.fam) test nameStr then TypeForm(nameStr) or TypeForm("Family: ",10,ix>>IX.fam,".") TypeForm(" Face: ") let faceStr=vec 5; faceStr>> STRING.length=9 DecodeFace(ix>>IX.face,faceStr) TypeForm(faceStr,". Size: ") let pointSize=MulDiv(ix>>IX.siz,72,2540) TypeForm(10,ix>>IX.siz," (",10,pointSize," points). Rotation: ",10,(ix>>IX.rotation)/60," degrees") let minutes=(ix>>IX.rotation) rem 60 if minutes then TypeForm(" ",10,minutes," minutes") TypeForm(". ",8,ix>>IX.bc,$:,8,ix>>IX.ec) if ix>>IXH.Type eq IXTypeMultiChars then [ TypeForm($*s,4,lv ix>>IXM.segs↑1.sa) TypeForm($*s,4,lv ix>>IXM.segs↑1.len,0) TypeForm(" Resolutions: ",10,ix>>IXM.resolutionx,$*s) TypeForm(10,ix>>IXM.resolutiony, ". The number of old width blocks is: ") let n=ix>>IXM.numSegs TypeForm(10,n-1,".",0) return ] TypeForm($*s,4,lv ix>>IX.sa,$*s,4,lv ix>>IX.len,0) if ix>>IXH.Type eq IXTypeWidths then return if ix>>IXH.Type eq IXTypeSplines then return if ix>>IXH.Type eq IXTypeTexMetrics then return TypeForm(" Resolutions: ",10,ix>>IX.resolutionx,$*s) TypeForm(10,ix>>IX.resolutiony,0) ] //********************************************************* and SetPosRelative(w,b,pos) be //********************************************************* [ let a=vec 1 DPCop(a,b) DoubleAdd(a,pos) WindowSetPosition(w,a) ] //********************************************************* and GetPosRelative(w,b,pos) be //********************************************************* [ WindowGetPosition(w,pos) DPSB(pos,b) ]