-- TexIO.mesa -- last written by Doug Wyatt, January 3, 1980 1:56 PM DIRECTORY TexDefs: FROM "TexDefs", TexMathDefs: FROM "TexMathDefs", TexIODefs: FROM "TexIODefs", TexStringDefs: FROM "TexStringDefs" USING[AppendChar,AppendNumber], DisplayDefs: FROM "DisplayDefs" USING[SetFont], FontDefs: FROM "FontDefs" USING[FontHandle,CreateFont], ImageDefs: FROM "ImageDefs" USING[CleanupItem,CleanupMask,CleanupProcedure,AddCleanupProcedure], InlineDefs: FROM "InlineDefs" USING[LongMult,LongDiv,DIVMOD], SegmentDefs: FROM "SegmentDefs", StreamDefs: FROM "StreamDefs" USING[GetDefaultKey,GetDefaultDisplayStream]; TexIO: PROGRAM IMPORTS TexStringDefs, DisplayDefs,FontDefs,ImageDefs,InlineDefs,SegmentDefs,StreamDefs EXPORTS TexIODefs = BEGIN OPEN TexMathDefs,TexDefs,TexIODefs; in: StreamHandle; -- the current input stream out: StreamHandle; -- the current output stream disp: StreamHandle; -- the default display stream loc,dloc: CARDINAL; GetStream: PUBLIC PROCEDURE RETURNS[StreamHandle] = BEGIN RETURN[out] END; SetStream: PUBLIC PROCEDURE[stream: StreamHandle] = BEGIN IF out=disp THEN dloc←loc; out←stream; loc←0; END; UseDisplay: PUBLIC PROCEDURE = BEGIN out←disp; loc←dloc END; Wc: PUBLIC PROCEDURE[c: CHARACTER] = -- write a character BEGIN out.put[out,c]; IF c=CR THEN loc←0 ELSE loc←loc+1; END; Cr: PUBLIC PROCEDURE = BEGIN Wc[CR] END; -- write a carriage return Sp: PUBLIC PROCEDURE = BEGIN Wc[SP] END; -- write a space esc: CHARACTER←'\; SetEsc: PUBLIC PROCEDURE[c: CHARACTER] = BEGIN esc←c END; -- set esc Esc: PUBLIC PROCEDURE = BEGIN Wc[esc] END; -- write the escape char Loc: PUBLIC PROCEDURE RETURNS[CARDINAL] = -- return the current location BEGIN RETURN[loc] END; Tab: PUBLIC PROCEDURE[tloc: CARDINAL] = -- tab over to location tloc BEGIN WHILE loc<tloc DO Sp ENDLOOP END; Ws: PUBLIC PROCEDURE[s: STRING] = -- write a string BEGIN i: CARDINAL; FOR i IN[0..s.length) DO Wc[s[i]] ENDLOOP; END; Wss: PUBLIC PROCEDURE[s: STRING, i1,i2: CARDINAL] = -- write a substring BEGIN i: CARDINAL; FOR i IN[i1..MIN[i2,s.length]) DO Wc[s[i]] ENDLOOP; END; WNum: PROCEDURE[val: UNSPECIFIED, radix: CARDINAL, signed: BOOLEAN, columns: CARDINAL] = BEGIN OPEN TexStringDefs; fill: CHARACTER←(IF radix=10 THEN SP ELSE '0); s: STRING ← [7]; -- large enough if smallest radix is 8 IF signed AND INTEGER[val]<0 THEN BEGIN AppendChar[s,'-]; val←-val END; AppendNumber[s,val,radix]; THROUGH (s.length..columns] DO Wc[fill] ENDLOOP; Ws[s]; RETURN END; Wn: PUBLIC PROCEDURE[n: INTEGER] = -- write a signed decimal number BEGIN WNum[n,10,TRUE,0] END; Wnf: PUBLIC PROCEDURE[n: CARDINAL, f: CARDINAL] = -- unsigned decimal, f columns BEGIN WNum[n,10,FALSE,f] END; Wo: PUBLIC PROCEDURE[o: CARDINAL] = -- write an unsigned octal number BEGIN WNum[o,10B,FALSE,0] END; WFont: PUBLIC PROCEDURE[f: Font] = BEGIN Esc; Wc[':]; Wc['@+f]; END; WFChar: PUBLIC PROCEDURE[fc: FChar] = BEGIN WFont[fc.font]; Sp; Wc[fc.char]; END; WCode: PROCEDURE[x: UNSPECIFIED] = BEGIN Wc['']; WNum[x,8,FALSE,3]; END; mfname: ARRAY MFont OF STRING = ["rm","it","sy","ex"]; mfbias: ARRAY MFont OF CARDINAL = [0,200B,400B,600B]; WMFont: PUBLIC PROCEDURE[m: MFont] = BEGIN Ws[IF m IN MFont THEN mfname[m] ELSE "??"]; END; WMChar: PUBLIC PROCEDURE[mchar: MChar] = BEGIN WMFont[mchar.mfont]; WCode[mchar.char]; END; WMCharOctal: PUBLIC PROCEDURE[mchar: MChar] = BEGIN n: CARDINAL←LOOPHOLE[mchar.char]; mf: MFont; IF (mf←mchar.mfont) IN MFont THEN n←n+mfbias[mf]; WCode[n]; END; WDimn: PUBLIC PROCEDURE[d: Dimn] = -- write value of d in points BEGIN OPEN InlineDefs; neg: BOOLEAN←(d<0); hpts,frac: CARDINAL; pts: INTEGER; hpts←LongDiv[(LongMult[ABS[d],72*100]+2540/2),2540]; -- hundreths of points [pts,frac]←DIVMOD[pts,100]; Wn[IF neg THEN -pts ELSE pts]; Wc['.]; WNum[frac,10,FALSE,2]; END; -- input procedures ReadChar: PUBLIC PROCEDURE RETURNS[CHARACTER] = BEGIN RETURN[in.get[in]] END; ControlH: CHARACTER = 'H-100B; ControlQ: CHARACTER = 'Q-100B; ControlR: CHARACTER = 'R-100B; ControlV: CHARACTER = 'V-100B; ControlW: CHARACTER = 'W-100B; ControlX: CHARACTER = 'X-100B; DEL: CHARACTER = 177C; ReadLine: PUBLIC PROCEDURE[s: STRING] = BEGIN c: CHARACTER; Clear: PROCEDURE[c, oldc: CHARACTER] = --INLINE-- BEGIN WITH out SELECT FROM Display => BEGIN clearChar[out,oldc]; loc←loc-1 END; ENDCASE => Wc[c]; END; Appnd: PROCEDURE[c: CHARACTER] = --INLINE-- BEGIN TexStringDefs.AppendChar[s,c]; Wc[c]; END; c ← in.get[in]; s.length ← 0; UNTIL c=CR DO SELECT c FROM DEL,ControlH => -- clear character IF s.length>0 THEN BEGIN Clear[c, s[s.length-1]]; s.length ← s.length-1 END; ControlW => -- clear word BEGIN -- text to be backed up is of the form -- ...<li><v><ti>; the <v> and <ti> are to be removed. i: CARDINAL; state: {ti, v, li} ← ti; FOR i DECREASING IN [0..s.length) DO SELECT s[i] FROM IN['A..'Z],IN['a..'z],IN['0..'9] => IF state=ti THEN state←v; ENDCASE => IF state=v THEN state←li; IF state = li THEN GO TO Done; Clear[ControlH, s[i]]; REPEAT Done => s.length ← i+1; FINISHED => s.length ← 0; ENDLOOP; END; ControlX => -- clear line BEGIN WITH out SELECT FROM Display => BEGIN clearCurrentLine[out]; loc←0 END; ENDCASE => Wc[c]; s.length ← 0; END; -- ControlV => Appnd[in.get[in]]; ENDCASE => Appnd[c]; c ← in.get[in]; ENDLOOP; END; -- initialization font: FontDefs.FontHandle←NIL; GetTexFont: PROCEDURE[name: STRING] = BEGIN OPEN SegmentDefs; fh: FileHandle; seg: FileSegmentHandle; fh←NewFile[name, Read, OldFileOnly !FileNameError => GOTO NotThere]; seg←NewFileSegment[fh, DefaultBase, DefaultPages, Read]; font←FontDefs.CreateFont[seg]; EXITS NotThere => RETURN; END; IOCleanupItem: ImageDefs.CleanupItem ← [link:, proc: IOCleanupProc, mask: ImageDefs.CleanupMask[Restore]]; IOCleanupProc: ImageDefs.CleanupProcedure = BEGIN SELECT why FROM Restore => IF font#NIL THEN DisplayDefs.SetFont[font]; ENDCASE; END; IOInit: PROCEDURE = BEGIN in←StreamDefs.GetDefaultKey[]; out←disp←StreamDefs.GetDefaultDisplayStream[]; loc←dloc←0; GetTexFont["TexFont.al"]; ImageDefs.AddCleanupProcedure[@IOCleanupItem]; IOCleanupProc[Restore]; END; IOInit; END.