// F E D I T F I L E (PREPRESS) // catalog number ??? // // FEDIT -- font editor for low resolution fonts. // Filing stuff. // //Comments about the format of the CDedits file. First comes the usual preamble // stuff to a CDtemp file (i.e. read and written with ReadIXTempFile,...). Then // comes a collection of characters, followed by a -1 (end of the update file). // Each character is the CharWidth structure (containing width goodies) followed // by the bit map (in CDtemp format, i.e. FHEAD is first). // The CharWidth structure may have H=HNonExCode, in which case // we are to delete the character from the font. get "ix.dfs" get "fedit.dfs" // outgoing procedures external [ EFileStart EFileFinish EditFindChar IndexCDFile MergeEdits EditWriteChar EditUnWriteChar EditReadChar ] // outgoing statics //external // [ // ] //static // [ // ] // incoming procedures external [ ReadCharBit WriteCharBit PaintRectangle PaintWidthMarker //UTIL FSGetX FSPut Zero; SetBlock; MoveBlock //PREPRESS IllCommand PrePressWindowInit ReadIXTempFile WriteIXTempFile SetPosRelative GetPosRelative //WINDOW WindowRead WindowReadBlock WindowWrite WindowWriteBlock WindowGetPosition WindowSetPosition WindowEnd WindowCopy WindowFlush WindowClose DeleteFile //FLOAT FLDI; FLDDP; FSTDP; DPAD DPCop FML;FAD;FDV;FTR //SCAN StrEq TypeForm CompareIX ] // incoming statics external [ ViewForeground //View parameters for foreground stuff ViewBackground //View parameters for background char. DisAdr //Address of display buffer start WidthMarker //Vector of width information (index by border #) bits //bits!0=#100000 UnsampledWX //Width of background character (in Alto units). UnsampledWY // " EFactorX //Enlargement factor of background EFactorY BackgroundArea //Number of 1 bits in background bigfilename //Edit file name string left by command scanner. ] // internal statics static [ EscratchFile //EFILE structures for the files. EbackgroundFile EeditFile LastCharCodeWritten //State of the scratch file. LastPos //File pos where char began. TrailerPos //Position of -1 trailer in file. PreviousWPos //File pos of current char previous to this edit PreviousBPos DPzero //Double-precision zero. ] // File-wide structure and manifest declarations. structure STR: [ length byte char↑1,255 byte ] // Procedures let //Start up all file aspects of the edit. // NoBackground is true if we are not to use background. // There are three files involved: // xxxx/B Edit file. // CDedits File of changes, deleted at end normally. // CDtemp Background file. // Returns reduction factor for background (0 if no background). EFileStart(NoBackground) = valof [ DPzero=table [ 0;0 ] //Set up edit file. if bigfilename!0 eq 0 then IllCommand() //CROCK CROCK having to do with window stuff -- need better opening control //Open read-only to be sure it exists: let s=PrePressWindowInit(2, false) WindowClose(s) //Now open read-write: s=PrePressWindowInit(2) let fn=vec IXLName let ix=vec IXLMax ReadIXTempFile(s, fn, ix) //Get info. EeditFile=IndexCDFile(s, 3) //Set up scratch file. let sc=nil [ sc=PrePressWindowInit("CDedits", true) if WindowEnd(sc) then break //No previous version! let str=vec 10 TypeForm("Edits recorded during the last use of the EDIT command appear not to",0) TypeForm("have been merged into the edit file. Do you wish to merge them?",1,str) if str>>STR.length gr 0 & (str>>STR.char↑1 eq $n % str>>STR.char↑1 eq $N) then break WindowClose(sc) MergeEdits() //Assumes editfile indexed. FSPut(EeditFile) //No longer indexed EeditFile=IndexCDFile(s, 2) // so redo it TypeForm("Merge finished.*N") ] repeat EscratchFile=IndexCDFile(sc,1) //Index it. LastPos=table [ 0;0 ] TrailerPos=table [ 0;0 ] PreviousWPos=table [ 0;0 ] PreviousBPos=table [ 0;0 ] LastCharCodeWritten=-1 WriteIXTempFile(sc, fn, ix) //Write header. WindowGetPosition(sc, TrailerPos) WindowWrite(sc,-1) //Write trailer. WindowFlush(sc) // and make sure on disk. //Set up CDtemp (background) file. EbackgroundFile=0 let factor=0 unless NoBackground then [ let cd=PrePressWindowInit(-1) //CDtemp. let fnb=vec IXLName let ixb=vec IXLMax ReadIXTempFile(cd, fnb, ixb) test ix>>IX.resolutionx eq ixb>>IX.resolutionx & ix>>IX.resolutiony eq ixb>>IX.resolutiony & StrEq(lv fn>>IXN.Name, lv fnb>>IXN.Name) then [ factor=(ixb>>IX.siz+1)/ix>>IX.siz ] or [ TypeForm("Illegal background file*N") factor=1 ] EbackgroundFile=IndexCDFile(cd, 2) //Index it. ] resultis factor ] and EFileFinish() be [ WindowClose(EscratchFile>>EFILE.window) MergeEdits() let s=EeditFile>>EFILE.window WindowSetPosition(s, DPzero) let fn=vec IXLName let ix=vec IXLMax ReadIXTempFile(s, fn, ix) DPAD(lv ix>>IX.sa, lv ix>>IX.len) WindowClose(s, lv ix>>IX.sa) ] and //Write the current character on the working file. Arguments are // c (character code). If this code is equal to the one that is at // the end of the scratch file, then just re-write it. This is like // a "checkpoint" facility, but is (currently) essential to the way // the words of text are re-displayed -- they use the scratch file // copies of edited (and the current) characters. EditWriteChar(c, delflag; numargs na) be [ if na eq 1 then delflag=0 let s=EscratchFile>>EFILE.window let bc=EscratchFile>>EFILE.bc let wpointer=EscratchFile>>EFILE.wp+(c-bc)*2 let bpointer=EscratchFile>>EFILE.bp+(c-bc)*2 test c eq LastCharCodeWritten ifso [ WindowSetPosition(s, LastPos) //Back to start of char ] ifnot [ WindowSetPosition(s, TrailerPos) DPCop(LastPos, TrailerPos) //Remember it. LastCharCodeWritten=c //This is the end. DPCop(PreviousWPos, wpointer) //Previous values for this char DPCop(PreviousBPos, bpointer) ] let xo=1000 //Minimum values. let yo=1000 let xmax=-1000 //Maximum values. let ymax=-1000 //Find out max dimensions of character for x=0 to ViewForeground>>VIEW.Xnum-1 do for y=0 to ViewForeground>>VIEW.Ynum-1 do if ReadCharBit(ViewForeground, x, y) then [ let x1,y1=x-WidthMarker!3,y-WidthMarker!1 //Relocate if x1 ls xo then xo=x1 if x1 gr xmax then xmax=x1 if y1 ls yo then yo=y1 if y1 gr ymax then ymax=y1 ] let xw=xmax-xo+1 let yw=ymax-yo+1 if xo eq 1000 then [ xo=0; yo=0; xw=0; yw=0 ] //For space!! //Now xw,yw have max width in bits. xo,yo have offset values. let v=vec CharWidthsize Zero(v, CharWidthsize) DPLDI(lv v>>CharWidth.WX, WidthMarker!4-WidthMarker!3) DPLDI(lv v>>CharWidth.WY, WidthMarker!2-WidthMarker!1) v>>CharWidth.XL=xo v>>CharWidth.YB=yo v>>CharWidth.W=xw v>>CharWidth.H=yw if delflag then [ Zero(v, CharWidthsize); v>>CharWidth.H=HNonExCode ] WindowWrite(s,c) //Write character code. WindowGetPosition(s, wpointer) WindowWriteBlock(s, v, CharWidthsize) //and width info WindowGetPosition(s, bpointer) test delflag then WindowWrite(s, 0) or [ let a=nil a<<FHEAD.hw=(yw+15)/16 a<<FHEAD.ns=xw WindowWrite(s, a) //Write header for bit map. for x=0 to xw-1 do [ let p=vec 100 Zero(p, 100) for y=0 to yw-1 do if ReadCharBit(ViewForeground, x+xo+WidthMarker!3, y+yo+WidthMarker!1) then [ let yw=y rshift 4 p!yw=p!yw% (bits!(y)) ] WindowWriteBlock(s, p, (yw+15)/16) ] ] WindowGetPosition(s, TrailerPos) WindowWrite(s, -1) //Termination. WindowFlush(s) //Make sure on disk. ] and //Cancel the last character on the end of the scratch file. EditUnWriteChar(c) be [ if c ne LastCharCodeWritten then return LastCharCodeWritten=-1 //So cannot back up further. let s=EscratchFile>>EFILE.window let bc=EscratchFile>>EFILE.bc let wpointer=EscratchFile>>EFILE.wp+(c-bc)*2 let bpointer=EscratchFile>>EFILE.bp+(c-bc)*2 DPCop(wpointer, PreviousWPos) DPCop(bpointer, PreviousBPos) DPCop(LastPos, TrailerPos) //place for trailer. WindowWrite(s, -1) WindowFlush(s) ] and //Find out where a character is. c is character code; w is vector // to be filled with CharWidth entry; a is: // 1 to look in scratch file // 2 to look in original edit file // 3 to look in background file (CDtemp) // Returns window to use, or 0 if no such character. Also fills // up w. Leaves window positioned at bit map. (Ready to call EditReadChar) EditFindChar(c, w, a) = valof [ let b=EditCharExists(c, a) if b eq 0 then resultis 0 let n=c-b>>EFILE.bc let p=n*2+b>>EFILE.wp //Posn of width entry. let q=n*2+b>>EFILE.bp //Posn of bit map. let s=b>>EFILE.window WindowSetPosition(s, p) //Read CharWidth thing. WindowReadBlock(s, w, CharWidthsize) WindowSetPosition(s, q) //Ready to read bit map encoding. resultis s ] and //Find out whether character c exists in file a (as for EditFindChar) // Returns 0 if character does not exist // Else returns proper EFILE structure EditCharExists(c, a) = valof [ let b=selecton a into [ case 1: EscratchFile case 2: EeditFile case 3: EbackgroundFile ] if b eq 0 then resultis 0 if c ls b>>EFILE.bc % c gr b>>EFILE.ec then resultis 0 let n=c-b>>EFILE.bc let q=n*2+b>>EFILE.bp //Posn of bit map. if q!0 eq -1 then resultis 0 //No such char. resultis b ] and //Read a character from a file. S is the window on the file; it is // positioned at the bitmap; w is the CharWidth structure for the // character. View is the view to use when writing; if the offset // values are missing, they are computed, and furthermore stored // as width values. EditReadChar(view, s, w, offx, offy; numargs n) be [ WriteCharBit(view) //Clear the bit map. if n eq 1 then return let ox=WidthMarker!3 let oy=WidthMarker!1 if n eq 3 then //Compute best position. [ let expnd(x, y, v) be [ x=x*v!4 y=y*v!5 if x ls v!0 then v!0=x if x gr v!1 then v!1=x if y ls v!2 then v!2=y if y gr v!3 then v!3=y ] //Following 6 must be in order (see expnd, above): let xl=1000 let xr=-1000 let yb=1000 let yt=-1000 let sx=view>>VIEW.Xunit let sy=view>>VIEW.Yunit //Figure in the black spots on the character: let v=lv xl let axl=w>>CharWidth.XL let ayb=w>>CharWidth.YB expnd(axl, ayb, v) expnd(w>>CharWidth.W+axl-1, w>>CharWidth.H+ayb-1, v) //And both "width" points: let wr=DpRound(lv w>>CharWidth.WX) let wt=DpRound(lv w>>CharWidth.WY) expnd(wr, wt, v) expnd(0, 0, v) //xl,xr and yb,yt now have max limits. ox=(BoxXSiz-(xr-xl+1))/2-xl oy=(BoxYSiz-(yt-yb+1))/2-yb ox=ox/ViewForeground>>VIEW.Xunit oy=oy/ViewForeground>>VIEW.Yunit PaintWidthMarker(3, ox) PaintWidthMarker(1, oy) offx=0 offy=0 ] let wx=DpRound(lv w>>CharWidth.WX) let wy=DpRound(lv w>>CharWidth.WY) // TypeForm("Read: ",10,ox,32,10,oy,0) //@ test view eq ViewForeground then [ PaintWidthMarker(2, wy+oy) //Set widths from old vals. PaintWidthMarker(4, wx+ox) ] or [ BackgroundArea=0 ox=ox*EFactorX oy=oy*EFactorY FLDI(5, ViewBackground>>VIEW.Xunit) FLDDP(1, lv w>>CharWidth.WX) FML(1,5); UnsampledWX=FTR(1) PaintWidthMarker(6, UnsampledWX) FLDI(5, ViewBackground>>VIEW.Yunit) FLDDP(1, lv w>>CharWidth.WY) FML(1,5); UnsampledWY=FTR(1) PaintWidthMarker(5, UnsampledWY) ] let a=WindowRead(s) let p=vec 100 let x=w>>CharWidth.XL for sc=1 to a<<FHEAD.ns do [ let hw=a<<FHEAD.hw WindowReadBlock(s, p, hw) let y=w>>CharWidth.YB for pc=0 to hw-1 do [ let w=p!pc for i=0 to 15 do [ if (w𘚠) ne 0 then [ if view eq ViewBackground then BackgroundArea=BackgroundArea+1 WriteCharBit(view, x+ox+offx, y+oy+offy, -1) ] y=y+1 w=w lshift 1 ] ] x=x+1 ] ] and //Index a CD-like file by building an EFILE structure for it. Argument // is window and the code (as above). If code=1 (scratch file), builds // dummy entries to start with. IndexCDFile(s, code)= valof [ WindowSetPosition(s, DPzero) let bc,ec=0,255 let fn=vec IXLName let ix=vec IXLMax if code ne 1 then [ ReadIXTempFile(s, fn, ix) bc=ix>>IX.bc ec=ix>>IX.ec ] let nc=ec-bc+1 let wc=nc*4+(size EFILE/16) let a=FSGetX(wc) SetBlock(a, -1, wc) //All chars undefined. a>>EFILE.window=s a>>EFILE.bc=bc a>>EFILE.ec=ec let p=a+(size EFILE/16) a>>EFILE.wp=p let q=p+nc*2 a>>EFILE.bp=q if code ne 1 & (WindowEnd(s) eq 0) then [ let t=lv ix>>IX.sa for i=0 to nc-1 do [ DPCop(p+i*2,t) DPAD(t, table [ 0;CharWidthsize ] ) ] WindowSetPosition(s, t) WindowReadBlock(s, q, nc*2) //Read CD entries for i=0 to nc-1 do if q!(i*2) ne -1 then DPAD(q+i*2, t) ] resultis a ] and //MergeEdits -- merge the edited characters recorded in the scratch (CDedits) file // with the original version in the edit file. Save the results on a // new edit file; delete the CDedits file. // Assumes edit file is open and indexed. Leaves edit file open, // but index will have been destroyed. MergeEdits() be [ let exists=vec 256 Zero(exists, 256) //0 => not mentioned let scd=EeditFile>>EFILE.window WindowSetPosition(scd, DPzero) let fn=vec IXLName let ix=vec IXLMax ReadIXTempFile(scd, fn, ix) let scr=PrePressWindowInit("CDedits", false) if scr eq 0 then return //Build an index for the CDedits file. let a=IndexCDFile(scr, 1) //Just get dummy entries. let fne=vec IXLName let ixe=vec IXLMax ReadIXTempFile(scr, fne, ixe) //Read header. unless StrEq(lv fn>>IXN.Name, lv fne>>IXN.Name) & CompareIX(ix, ixe) then [ TypeForm("CDedits and ",bigfilename," do not match! Update aborted.*N") finish ] let edited=false [ let c=WindowRead(scr) //Char code. if c eq -1 then break edited=true let n=c-a>>EFILE.bc WindowGetPosition(scr, n*2+a>>EFILE.wp) //Width pos. let w=vec CharWidthsize WindowReadBlock(scr, w, CharWidthsize) exists!c=(w>>CharWidth.H eq HNonExCode)? -1,1 WindowGetPosition(scr, n*2+a>>EFILE.bp) let b=WindowRead(scr) let d=vec 1; d!0=0; d!1=b<<FHEAD.ns*b<<FHEAD.hw+1 SetPosRelative(scr, d, n*2+a>>EFILE.bp) ] repeat EscratchFile=a if edited then [ //Some edited chars! let bc,ec=255,-1 for c=0 to 255 do [ if (exists!c eq 0 & EditCharExists(c, 2)) % exists!c eq 1 then [ if c ls bc then bc=c if c gr ec then ec=c ] ] ixe>>IX.bc=bc //Update char ranges. ixe>>IX.ec=ec //Now build new edit file. let nc=ec-bc+1 let CD=FSGetX(nc*2) SetBlock(CD, -1, nc*2) let WD=FSGetX(nc*CharWidthsize) Zero(WD, nc*CharWidthsize) let p=WD for i=1 to nc do [ p>>CharWidth.H=HNonExCode; p=p+CharWidthsize ] let sout=PrePressWindowInit(0) //Scratch file! WriteIXTempFile(sout, fne, ixe) WindowGetPosition(sout, lv ixe>>IX.sa) WindowWriteBlock(sout, WD, nc*CharWidthsize) //dummy let off=vec 1 WindowGetPosition(sout, off) //Offset WindowWriteBlock(sout, CD, nc*2) for c=bc to ec do [ let w=vec CharWidthsize let a=EditFindChar(c, w, 1) //Look on scratch file. if a eq 0 then a=EditFindChar(c, w, 2) //Look on original CDtemp file. if a then [ //Write it out! MoveBlock(WD+(c-bc)*CharWidthsize,w,CharWidthsize) if w>>CharWidth.H ne HNonExCode then [ GetPosRelative(sout, off, CD+(c-bc)*2) let b=WindowRead(a) //FHEAD WindowWrite(sout, b) let d=vec 1; d!0=0; d!1=b<<FHEAD.ns*b<<FHEAD.hw WindowCopy(a, sout, d) //Copy encoding. ] ] ] WindowClose(scr) //CDedits. FSPut(EscratchFile) let tl=vec 1 WindowGetPosition(sout, tl) //Total length GetPosRelative(sout, lv ixe>>IX.sa, lv ixe>>IX.len) //get length WindowSetPosition(sout, DPzero) WriteIXTempFile(sout, fne, ixe) WindowWriteBlock(sout, WD, nc*CharWidthsize) WindowWriteBlock(sout, CD, nc*2) FSPut(CD); FSPut(WD) WindowSetPosition(sout, DPzero) WindowSetPosition(scd, DPzero) //Critical section::::: WindowCopy(sout, scd, tl) //Copy entire scratch // file to new edit file. ] //Some edited chars. DeleteFile("CDedits") //Done ::::: ] and DpRound(a)= valof [ let b=vec 1 DPCop(b, a) DPAD(b, table [ 0;#100000 ]) resultis b!0 ] and DPLDI(a,b) be [ FLDI(1, b) FSTDP(1, a) ]