-- Print Labels.mesa -- Edited by Sweet, 2-Oct-82 21:45:30 DIRECTORY AltoFileDefs, Ascii, Inline, IODefs, ImageDefs, MiscDefs, PressDefs, PressUtilities, SegmentDefs, Storage, StreamDefs, String; PrintLabels: PROGRAM IMPORTS ImageDefs, Inline, IODefs, MiscDefs, PressDefs, PressUtilities, SegmentDefs, Storage, StreamDefs, String = BEGIN OPEN IODefs, PressDefs, String, StreamDefs; in: StreamHandle; Label: TYPE = BASE POINTER TO LabelBody; RelLabel: TYPE = Label RELATIVE POINTER TO StringBody; LabelBody: TYPE = RECORD [ count, last: [0..256), lines: ARRAY [0..8) OF RelLabel]; nextRP: RelLabel; AddLine: PROC = BEGIN s: STRING = @buffer[nextRP]; s↑ ← [length: 0, maxlength: line.length, text: NULL]; String.AppendString[s, line]; buffer.lines[buffer.count] ← nextRP; nextRP ← nextRP + String.WordsForString[line.length]; WHILE s.length # 0 AND s[s.length-1] = Ascii.SP DO s.length ← s.length - 1; ENDLOOP; IF ~slashSeen AND line[0] = '/ THEN { slashSeen ← TRUE; buffer.last ← buffer.count}; buffer.count ← buffer.count + 1; END; StartLabel: PROC = BEGIN buffer.count ← 0; buffer.last ← 0; slashSeen ← FALSE; nextRP ← LOOPHOLE[SIZE[LabelBody]]; END; slashSeen: BOOLEAN; pfdBody: PressFileDescriptor; pfd: POINTER TO PressFileDescriptor = @pfdBody; Mica: TYPE = CARDINAL; MBox: TYPE = RECORD [x,y,w,h: Mica]; CharHeight: Mica; CharWidth: POINTER TO ARRAY CHARACTER OF Mica; TextCharWidth: ARRAY CHARACTER OF Mica; TextCharHeight: Mica; PointsToMicas: PROC [points: CARDINAL] RETURNS [Mica] = {RETURN [Inline.LongDiv[Inline.LongMult[points, MicasPerInch],72]]}; StringWidth: PROC [s: STRING] RETURNS [l: Mica] = BEGIN l ← 0; FOR i: CARDINAL IN [0..s.length) DO l ← l + CharWidth[s[i]]; ENDLOOP; END; LineY: PROC [box: POINTER TO MBox, line, of: CARDINAL, lead: Mica ← 0] RETURNS [Mica] = BEGIN h: Mica = CharHeight; bottom: Mica; line ← of-1-line; -- count from top bottom ← (box.h- of*h - (of-1)*lead)/2; RETURN [box.y + bottom + (line-1)*(h+lead)]; END; LJLine: PROC [s: STRING, box: POINTER TO MBox, line, of: CARDINAL, lead: Mica ← 1] = BEGIN y: Mica = LineY[box: box, line: line, of: of, lead: lead]; PutText[pfd, s, box.x, y]; END; P1: Mica = PointsToMicas[1]; P2: Mica = PointsToMicas[2]; M1: Mica = MicasPerInch; M12: Mica = MicasPerInch/2; M14: Mica = MicasPerInch/4; M34: Mica = (3*MicasPerInch)/4; M38: Mica = (3*MicasPerInch)/8; TextFont: PROC = BEGIN SetFont[p: pfd, Name: "Helvetica", PointSize: outPointSize, Face: 0]; CharHeight ← TextCharHeight; CharWidth ← @TextCharWidth; END; outPointSize: CARDINAL ← 10; DigestFonts: PROC = BEGIN [] ← PressUtilities.FindFontWidths[ family: "Helvetica"L, points: outPointSize, weight: medium, slope: regular, widths: LOOPHOLE[@TextCharWidth]]; TextCharHeight ← PointsToMicas[outPointSize]; END; commandStream: StreamHandle; SetUpCommands: PROCEDURE = BEGIN cfa: POINTER TO AltoFileDefs.CFA ← MiscDefs.CommandLineCFA[]; cfile: SegmentDefs.FileHandle ← SegmentDefs.InsertFile[@cfa.fp,Read]; commandStream ← NIL; commandStream ← CreateByteStream[cfile,Read ! SegmentDefs.InvalidFP => CONTINUE]; IF commandStream # NIL THEN BEGIN JumpToFA[commandStream,@cfa.fa]; WHILE commandStream.get[commandStream ! StreamError => GOTO nocommands] <= SP DO NULL ENDLOOP; SetIndex[commandStream,ModifyIndex[GetIndex[commandStream],-1]]; EXITS nocommands => BEGIN commandStream.destroy[commandStream]; commandStream ← NIL END; END; END; ReadName: PROCEDURE [s: STRING] = BEGIN c: CHARACTER; IF commandStream = NIL THEN ReadID[s] ELSE BEGIN s.length ← 0; DO IF (c←commandStream.get[commandStream ! StreamError => GOTO endoffile]) <= SP THEN BEGIN IF s.length # 0 THEN EXIT END ELSE BEGIN String.AppendChar[s,c]; WriteChar[c] END; REPEAT endoffile => BEGIN commandStream.destroy[commandStream]; commandStream ← NIL END; ENDLOOP; END; END; GetFile: PROCEDURE [prompt: STRING, access: AccessOptions, switches: STRING ← NIL] RETURNS [StreamHandle] = BEGIN name: STRING ← [40]; WriteString[prompt]; ReadName[name]; IF switches # NIL THEN FOR i:CARDINAL IN[0..name.length) DO IF name[i] = '/ THEN BEGIN FOR j: CARDINAL IN (i..name.length) DO String.AppendChar[switches,name[j]] ENDLOOP; name.length ← i; EXIT; END; ENDLOOP; WriteChar[CR]; IF name.length = 0 THEN ImageDefs.StopMesa[]; RETURN[NewByteStream[name,access]] END; ReadLabel: PROC = BEGIN StartLabel[]; DO ReadLine[]; IF line.length = 0 AND (buffer.count # 0 OR in.endof[in]) THEN EXIT; IF line.length # 0 THEN AddLine[]; ENDLOOP; IF ~slashSeen THEN buffer.last ← buffer.count; END; ReadLine: PROC = BEGIN c: CHARACTER; n: CARDINAL ← 0; line.length ← 0; BEGIN DO c ← in.get[in ! StreamError => EXIT]; IF c = CR THEN EXIT; IF n = line.maxlength-1 THEN GO TO tooLong; line[n] ← c; n ← n + 1; ENDLOOP; line.length ← n; EXITS tooLong => { IODefs.WriteLine["Line truncated:"L]; IODefs.WriteLine[line]; line.length ← n}; END; END; line: STRING ← [200]; row, col: CARDINAL; LWidth: Mica = (8*M1 + M12)/3; LHeight: Mica = M1; yDelta: Mica ← 0; scaleFactor: CARDINAL ← 100; Scale: PROC [d: Mica] RETURNS [Mica] = { -- d must be > 0 RETURN [Inline.LongDiv[Inline.LongMult[d, scaleFactor], 100]]}; PressLabel: PROC [p: Label] = BEGIN name: STRING = [100]; l1: STRING = @p[p.lines[0]]; comma: CARDINAL ← l1.length; j: CARDINAL; box: MBox; IF row = 11 THEN {row ← 0; col ← col + 1}; IF col = 3 THEN {WritePage[pfd]; col ← 0}; box.x ← M38 + col * LWidth; box.y ← yDelta + 10*M1 - Scale[row*LHeight]; box.w ← LWidth - M38; box.h ← M1; FOR i: CARDINAL IN [0..l1.length) DO IF l1[i] = ', THEN {comma ← i; EXIT}; ENDLOOP; j ← comma + 1; WHILE j < l1.length AND l1[j] = Ascii.SP DO j ← j + 1; ENDLOOP; FOR i: CARDINAL IN [j..l1.length) DO String.AppendChar[name, l1[i]]; ENDLOOP; IF name.length # 0 AND name[name.length-1] # Ascii.SP THEN String.AppendChar[name, Ascii.SP]; FOR i: CARDINAL IN [0..comma) DO String.AppendChar[name, l1[i]]; ENDLOOP; LJLine[s: name, box: @box, line: 0, of: p.last]; FOR i: CARDINAL IN [1..p.last) DO LJLine[s: @p[p.lines[i]], box: @box, line: i, of: p.last]; ENDLOOP; row ← row + 1; END; InitPressThings: PROC = BEGIN InitPressFileDescriptor[pfd, "Labels.press"]; DigestFonts[]; TextFont[]; row ← col ← 0; END; buffer: Label; makePress, paginateList: BOOLEAN ← FALSE; DoIt: PROC = BEGIN c: CHARACTER; switches: STRING ← [20]; BEGIN i: CARDINAL; GetSwitchNumber: PROC RETURNS [INTEGER] = BEGIN neg: BOOLEAN ← FALSE; n: CARDINAL ← 0; i ← i+1; IF switches[i] = '- THEN {neg ← TRUE; i ← i+1}; WHILE switches[i] IN ['0..'9] DO n ← n * 10 + (switches[i] - '0); i ← i+1; ENDLOOP; i ← i-1; -- since loop increments at bottom IF neg THEN RETURN [-INTEGER[n]] ELSE RETURN [n]; END; in ← GetFile["input: "L, StreamDefs.Read, switches ! SegmentDefs.FileNameError => GO TO cantFind]; i ← 0; WHILE i < switches.length DO SELECT (c ← switches[i]) FROM 's, 'S => scaleFactor ← GetSwitchNumber[]; 'y, 'Y => yDelta ← GetSwitchNumber[]; 'p, 'P => outPointSize ← GetSwitchNumber[]; ENDCASE => GO TO badSwitch; i ← i+1; ENDLOOP; buffer ← Storage.Pages[3]; InitPressThings[]; -- go through list of names, calling PressLabel DO ReadLabel[]; IF buffer.count = 0 THEN EXIT; PressLabel[buffer]; ENDLOOP; in.destroy[in]; WritePage[pfd]; ClosePressFile[pfd]; Storage.FreePages[buffer]; IODefs.WriteLine["--done"L]; EXITS cantFind => WriteLine[" file not found"L]; badSwitch => WriteLine[" bad switch"L]; END; END; SetUpCommands[]; DoIt[]; ImageDefs.StopMesa[]; END.