DIRECTORY Ascii, BasicTime, Buttons, Commander USING [CommandProc, Register], Containers USING [ChildXBound, ChildYBound, Container, Create], Convert, FS, IO, MessageWindow, PrintFormsDefs, RefText, Rope, Rules USING [Create, Rule], SafeStorage, SirPress, TSFont, TSTypes, TypeScript, VFonts, ViewerClasses USING [Viewer, ViewerClassRec], ViewerIO USING [CreateViewerStreams], ViewerOps USING [CreateViewer, PaintViewer], ViewerTools USING [GetContents, MakeNewTextViewer, SetSelection]; PrintForms: CEDAR PROGRAM IMPORTS BasicTime, Buttons, Commander, Containers, Convert, FS, IO, MessageWindow, RefText, Rope, Rules, SafeStorage, SirPress, TSFont, TSTypes, TypeScript, VFonts, ViewerIO, ViewerOps, ViewerTools = BEGIN OPEN PrintFormsDefs; Problem: PUBLIC ERROR = CODE; MakeTool: Commander.CommandProc = BEGIN rule: Rules.Rule; my: Handle _ NEW[MyRec]; my.outer _ Containers.Create[[-- construct the outer container name: "Forms Printer", -- name displayed in the caption iconic: TRUE, -- so tool will be iconic (small) when first created column: left, -- initially in the left column scrollable: FALSE ]]; -- inhibit user from scrolling contents MakeCommands[my]; -- build each (sub)viewer in turn rule _ Rules.Create [[parent: my.outer, wy: my.height, ww: my.outer.cw, wh: 2]]; Containers.ChildXBound[my.outer, rule]; my.height _ my.height + entryHeight + 2; -- interline spacing MakeTypescript[my]; ViewerOps.PaintViewer[my.outer, all]; -- reflect above change END; faceNormal: CARDINAL = 0; faceItalic: CARDINAL = 1; faceBold: CARDINAL = 2; faceBoldItalic: CARDINAL = 3; LookupFonts: PROC [handle: Handle] = { DoFont: PROC [class: FontClass, family: ROPE, size: INT, face: CARDINAL _ faceNormal, rotation: INT _ 5400] = { handle.fontCode[class] _ handle.press.GetFontCode[ family: family, size: size, rotation: rotation, face: face]; handle.fontInfo[class] _ TSFont.Lookup[ (SELECT face FROM faceItalic => Rope.Concat[family, "I"], faceBold => Rope.Concat[family, "B"], faceBoldItalic => Rope.Concat[family, "BI"], ENDCASE => family), TSTypes.IntDimn[size, TSTypes.bp]]; }; DoFont[f0, "TimesRoman", 12, faceBold]; DoFont[f1, "Helvetica", 10]; DoFont[f2, "TimesRoman", 10, faceBold]; DoFont[f3, "TimesRoman", 10]; DoFont[f4, "Helvetica", 8]; DoFont[f5, "Helvetica", 8, faceNormal, 0]; DoFont[f6, "Helvetica", 10, faceItalic]; DoFont[bodyItalic, "TimesRoman", 10, faceItalic]; DoFont[symbols, "Math", 10]; }; MakeTypescript: PROC [handle: Handle] = BEGIN handle.height _ handle.height + entryVSpace; -- space down from the top of the viewer handle.ts _ TypeScript.Create[ info: [name: "PrintForms.ts", wy: handle.height, parent: handle.outer, border: FALSE ]]; [handle.tsIn, handle.tsOut] _ ViewerIO.CreateViewerStreams [ name: "PrintForms.ts", viewer: handle.ts, backingFile: "PrintForms.ts", editedStream: FALSE]; Containers.ChildXBound[handle.outer, handle.ts]; Containers.ChildYBound[handle.outer, handle.ts]; END; MakeCommands: PROC [handle: Handle] = BEGIN initialData: Rope.ROPE = NIL; wx: INT _ 0; NewLine: PROC = {handle.height _ handle.height + entryHeight + entryVSpace; wx _ 0}; LabeledItem: PROC [label: ROPE, width: INT, data: ROPE _ NIL] RETURNS [v: ViewerClasses.Viewer] = { ph: PromptHandle _ NEW [PromptRec _ [handle: handle]]; t: Buttons.Button _ Buttons.Create[ info: [ name: Rope.Concat[label, ":"], wy: handle.height, wh: entryHeight, -- specify rather than defaulting so line is uniform wx: wx, parent: handle.outer, border: FALSE ], proc: Prompt, clientData: ph]; -- this will be passed to our button proc wx _ wx + t.ww + entryHSpace; v _ ViewerTools.MakeNewTextViewer[ [ parent: handle.outer, wx: wx, wy: handle.height, ww: width*VFonts.CharWidth['0], wh: entryHeight, data: data, scrollable: FALSE, border: FALSE]]; ph.viewer _ v; wx _ wx + v.ww + entryHSpace}; Cmd: PROC [label: ROPE, proc: Buttons.ButtonProc] = { t: Buttons.Button _ Buttons.Create[ info: [ name: label, wx: wx, wy: handle.height, wh: entryHeight, -- specify rather than defaulting so line is uniform parent: handle.outer, border: TRUE ], proc: proc, clientData: handle]; -- this will be passed to our button proc wx _ wx + t.ww + entryHSpace}; Bool: PROC [label: ROPE, initial: BOOL] RETURNS [flag: REF BOOL] = { t: Buttons.Button; flag _ NEW[BOOL _ initial]; t _ Buttons.Create[ info: [ name: label, wx: wx, wy: handle.height, wh: entryHeight, -- specify rather than defaulting so line is uniform parent: handle.outer, border: TRUE ], proc: ToggleBool, clientData: flag]; -- this will be passed to our button proc Buttons.SetDisplayStyle[ button: t, style: IF initial THEN $WhiteOnBlack ELSE $BlackOnWhite, paint: FALSE]; wx _ wx + t.ww + entryHSpace}; NewLine[]; Cmd["Print", DoIt]; NewLine[]; handle.cmd.inputFile _ LabeledItem["input", 50, "///FUMC/"]; NewLine[]; handle.cmd.pressFile _ LabeledItem["press", 50, "///FUMC/"]; NewLine[]; handle.cmd.firstCaller _ LabeledItem["first caller", 5, "20"]; handle.cmd.callers _ LabeledItem["callers", 40, "///FUMC/CallerNames.txt"]; NewLine[]; END; Prompt: Buttons.ButtonProc -- [parent: REF ANY, clientData: REF ANY _ NIL, mouseButton: Menus.MouseButton _ red, shift: BOOL _ FALSE, control: BOOL _ FALSE] -- = BEGIN ph: PromptHandle _ NARROW[clientData]; ViewerTools.SetSelection[ph.viewer]; -- force the selection END; ToggleBool: Buttons.ButtonProc = { switch: REF BOOL _ NARROW [clientData]; switch^ _ ~switch^; Buttons.SetDisplayStyle[ button: NARROW[parent], style: IF switch^ THEN $WhiteOnBlack ELSE $BlackOnWhite]; }; DoIt: Buttons.ButtonProc -- [parent: REF ANY, clientData: REF ANY _ NIL, mouseButton: Menus.MouseButton _ red, shift: BOOL _ FALSE, control: BOOL _ FALSE] -- = BEGIN handle: Handle _ NARROW[clientData]; -- get our data BEGIN ENABLE { UNWIND => {IF handle.in # NIL THEN handle.in.Close[]; handle.in _ NIL}; Problem, ABORTED => {handle.tsOut.PutText[" aborted"]; GO TO done}}; fName: ROPE = ViewerTools.GetContents[handle.cmd.inputFile]; pName: ROPE = ViewerTools.GetContents[handle.cmd.pressFile]; count: CARDINAL _ 0; Val: PROC [v: ViewerClasses.Viewer, default: INT] RETURNS [n: INT] = { n _ Convert.IntFromRope[ViewerTools.GetContents[v] ! SafeStorage.NarrowFault => {n _ default; GO TO gub}; Convert.Error => { MessageWindow.Append[message: "invalid number", clearFirst: TRUE]; n _ default; GO TO gub}; ]; EXITS gub => NULL; }; IF fName = NIL OR pName = NIL THEN { handle.tsOut.Put[[rope["specify input file name"]], [character['\n]]]; RETURN}; handle.in _ OpenFile[fName]; IF handle.in # NIL THEN handle.eof _ FALSE; IF pName # NIL AND Rope.Length[pName] # 0 THEN { handle.out _ FS.StreamOpen[fileName: pName, accessOptions: $create]; handle.press _ SirPress.Create[outputStream: handle.out, fileNameForHeaderPage: pName]; handle.date _ Convert.RopeFromTime[BasicTime.Now[], $years, $days]; handle.press.SetPageSize[110, 85]; LookupFonts[handle]; handle.callerName _ ParseCallerNames[handle]; handle.firstCaller _ Val[handle.cmd.firstCaller, 20]; handle.entryY _ firstY; handle.entriesOnPage _ 0; handle.prevCaller _ 0; handle.affiliateThisPage _ FALSE; } ELSE Quit[handle, "No output file"]; handle.tsOut.PutText["Processing:"]; WHILE ~handle.eof DO ProcessEntry[handle]; count _ count + 1; IF count MOD 50 = 0 THEN handle.tsOut.PutChar['.]; ENDLOOP; IF handle.press # NIL THEN { FinishPage[handle]; handle.press.ClosePress[]; handle.press _ NIL}; EXITS done => NULL; END; -- of Enable IF handle.in # NIL THEN handle.in.Close[]; IF handle.out # NIL THEN handle.out.Close[]; handle.tsOut.Put[[character['\n]], [rope["done"]], [character['\n]]]; END; MWidth: PROC [h: Handle, s: ROPE, class: FontClass] RETURNS [INT] = { w: TSTypes.Dimn _ [0]; ref: TSFont.Ref _ h.fontInfo[class]; IF ref = NIL THEN RETURN [0]; FOR i: INT IN [0..Rope.Length[s]) DO w _ [w + TSFont.Width[ref, Rope.Fetch[s, i]]]; ENDLOOP; RETURN [TSTypes.DimnInt[w, TSTypes.mica]]; }; SplatRope: PUBLIC PROCEDURE [h: Handle, x, y: INT, f: FontClass, s: ROPE] = { h.press.SetFontFromCode[h.fontCode[f]]; SirPress.PutText[ -- rotated 90 degrees p: h.press, textString: s, xCoordinateOfLeftEdge: pageWidth-y, yCoordinateOfBaseline: x]}; DrawBox: PUBLIC PROCEDURE [h: Handle, x, y, width, height: INT] = { SirPress.PutRectangle[ -- rotated 90 degrees p: h.press, xstart: pageWidth-y-height, ystart: x, xlen: height, ylen: width]}; RJString: PROCEDURE [h: Handle, x, y: INT, f: FontClass, s: ROPE, width: INT] = { SplatRope[h: h, x: x + width - MWidth[h, s, f], y: y, f: f, s: s]}; LJString: PROCEDURE [h: Handle, x, y: INT, f: FontClass, s: ROPE] = { SplatRope[h: h, x: x, y: y, f: f, s: s]}; CenterString: PROCEDURE [h: Handle, x, y: INT, f: FontClass, s: ROPE, width: INT] = { delta: INT = width - MWidth[h, s, f]; SplatRope[h: h, x: x + delta/2, y: y, f: f, s: s]}; Place: TYPE = RECORD [x, y: INT]; callerNamePlace: Place = [x: 5094, y: 19910]; recruiterNamePlace: Place = [x: 5094, y: 19483]; callerPhonePlace: Place = [x: 14341, y: 19910]; recruiterPhonePlace: Place = [x: 14341, y: 19483]; datePlace: Place = [x: 23942, y: 2057]; firstY: INT = 17883; activityX: INT = 969; levelX: INT = 1396; dinnerX: INT = 1823; ageX: INT = 2249; phoneX: INT = 2676; nameX: INT = 5237; addrX: INT = 12207; commentX: INT = 21026; entryDelta: INT = 1565; lineDelta: INT = 427; PrintBoilerplate: PUBLIC PROC [h: Handle] = { SplatRope[h: h, x: 827, y: 20514, f: f0, s: "First United Methodist Church, Palo Alto"]; SplatRope[h: h, x: 22022, y: 20514, f: f0, s: "1985 Financial Campaign"]; SplatRope[h: h, x: 2818, y: 19910, f: f1, s: "Caller name:"]; SplatRope[h: h, x: 12776, y: 19910, f: f1, s: "Phone:"]; SplatRope[h: h, x: 2818, y: 19483, f: f1, s: "Reports to:"]; SplatRope[h: h, x: 12776, y: 19483, f: f1, s: "Phone:"]; SplatRope[h: h, x: 22947, y: 19127, f: f1, s: "Comments"]; SplatRope[h: h, x: 3245, y: 18701, f: f1, s: "Phone"]; SplatRope[h: h, x: 8082, y: 18701, f: f1, s: "Name"]; SplatRope[h: h, x: 14127, y: 18701, f: f1, s: "Address"]; SplatRope[h: h, x: 1396, y: 2200, f: f1, s: "Activity level"]; SplatRope[h: h, x: 4668, y: 2200, f: f1, s: "Contribution in 1984"]; SplatRope[h: h, x: 9504, y: 2200, f: f1, s: "Expected Campaign contact mode"]; SplatRope[h: h, x: 16190, y: 2200, f: f1, s: "Age range"]; SplatRope[h: h, x: 1396, y: 1880, f: f4, s: "a"]; SplatRope[h: h, x: 1680, y: 1880, f: f4, s: "= active"]; SplatRope[h: h, x: 4668, y: 1880, f: f4, s: "p"]; SplatRope[h: h, x: 4952, y: 1880, f: f4, s: "= pledge"]; SplatRope[h: h, x: 9504, y: 1880, f: f4, s: "d"]; SplatRope[h: h, x: 9789, y: 1880, f: f4, s: "= dinner"]; SplatRope[h: h, x: 16190, y: 1880, f: f4, s: "k"]; SplatRope[h: h, x: 16474, y: 1880, f: f4, s: "= middle/ high school"]; SplatRope[h: h, x: 1396, y: 1559, f: f4, s: "b"]; SplatRope[h: h, x: 1680, y: 1559, f: f4, s: "= infrequent"]; SplatRope[h: h, x: 4668, y: 1559, f: f4, s: "c"]; SplatRope[h: h, x: 4952, y: 1559, f: f4, s: "= contribution"]; SplatRope[h: h, x: 9504, y: 1559, f: f4, s: "h"]; SplatRope[h: h, x: 9789, y: 1559, f: f4, s: "= home visit"]; SplatRope[h: h, x: 16190, y: 1559, f: f4, s: "y"]; SplatRope[h: h, x: 16474, y: 1559, f: f4, s: "= college to age 30"]; SplatRope[h: h, x: 1396, y: 1239, f: f4, s: "c"]; SplatRope[h: h, x: 1680, y: 1239, f: f4, s: "= inactive"]; SplatRope[h: h, x: 4668, y: 1239, f: f4, s: "0"]; SplatRope[h: h, x: 4952, y: 1239, f: f4, s: "= no traceable contribution"]; SplatRope[h: h, x: 9504, y: 1239, f: f4, s: "i"]; SplatRope[h: h, x: 9789, y: 1239, f: f4, s: "= inactive"]; SplatRope[h: h, x: 16190, y: 1239, f: f4, s: "a"]; SplatRope[h: h, x: 16474, y: 1239, f: f4, s: "= 30 to 70"]; SplatRope[h: h, x: 1396, y: 919, f: f4, s: "-"]; SplatRope[h: h, x: 1680, y: 919, f: f4, s: "= no data"]; SplatRope[h: h, x: 4668, y: 919, f: f4, s: "-"]; SplatRope[h: h, x: 4952, y: 919, f: f4, s: "= no data"]; SplatRope[h: h, x: 9504, y: 919, f: f4, s: "-"]; SplatRope[h: h, x: 9789, y: 919, f: f4, s: "= no data"]; SplatRope[h: h, x: 16190, y: 919, f: f4, s: "s"]; SplatRope[h: h, x: 16474, y: 919, f: f4, s: "= post 70"]; SplatRope[h: h, x: 20386, y: 635, f: bodyItalic, s: "Italic name = Constituent"]; SplatRope[h: h, x: 16190, y: 599, f: f4, s: "-"]; SplatRope[h: h, x: 16474, y: 599, f: f4, s: "= no data"]; SplatRope[h: h, x: 969, y: 20194, f: f5, s: "Activity"]; SplatRope[h: h, x: 1396, y: 20194, f: f5, s: "'84 Contrib"]; SplatRope[h: h, x: 1823, y: 20194, f: f5, s: "Exp. Mode"]; SplatRope[h: h, x: 2249, y: 20194, f: f5, s: "Age"]; SplatRope[h: h, x: 17790, y: 20194, f: f5, s: "count - came"]; SplatRope[h: h, x: 18110, y: 20194, f: f5, s: "Dinner date/"]; SplatRope[h: h, x: 18786, y: 20194, f: f5, s: "date/time"]; SplatRope[h: h, x: 19106, y: 20194, f: f5, s: "Home visit"]; SplatRope[h: h, x: 20600, y: 20194, f: f5, s: "Inactive"]; SplatRope[h: h, x: 19746, y: 19696, f: f5, s: "rec'd"]; SplatRope[h: h, x: 20102, y: 20194, f: f5, s: "Date pledge"]; DrawBox[h: h, x: 791, y: 20265, width: 25925, height: 71]; DrawBox[h: h, x: 2534, y: 19305, width: 14936, height: 36]; DrawBox[h: h, x: 791, y: 18274, width: 25925, height: 71]; DrawBox[h: h, x: 17470, y: 17171, width: 996, height: 36]; DrawBox[h: h, x: 791, y: 16745, width: 25925, height: 36]; DrawBox[h: h, x: 17470, y: 15607, width: 996, height: 36]; DrawBox[h: h, x: 791, y: 15180, width: 25925, height: 36]; DrawBox[h: h, x: 17470, y: 14042, width: 996, height: 36]; DrawBox[h: h, x: 791, y: 13615, width: 25925, height: 36]; DrawBox[h: h, x: 17470, y: 12477, width: 996, height: 36]; DrawBox[h: h, x: 791, y: 12050, width: 25925, height: 36]; DrawBox[h: h, x: 17470, y: 10912, width: 996, height: 36]; DrawBox[h: h, x: 791, y: 10486, width: 25925, height: 36]; DrawBox[h: h, x: 17470, y: 9348, width: 996, height: 36]; DrawBox[h: h, x: 791, y: 8921, width: 25925, height: 36]; DrawBox[h: h, x: 17470, y: 7783, width: 996, height: 36]; DrawBox[h: h, x: 791, y: 7356, width: 25925, height: 36]; DrawBox[h: h, x: 17470, y: 6218, width: 996, height: 36]; DrawBox[h: h, x: 791, y: 5791, width: 25925, height: 36]; DrawBox[h: h, x: 17470, y: 4653, width: 996, height: 36]; DrawBox[h: h, x: 791, y: 4227, width: 25925, height: 36]; DrawBox[h: h, x: 17470, y: 3089, width: 996, height: 36]; DrawBox[h: h, x: 791, y: 2626, width: 25996, height: 71]; DrawBox[h: h, x: 791, y: 2697, width: 71, height: 17639]; DrawBox[h: h, x: 1254, y: 2697, width: 36, height: 17639]; DrawBox[h: h, x: 1680, y: 2697, width: 36, height: 17639]; DrawBox[h: h, x: 2107, y: 2697, width: 36, height: 17639]; DrawBox[h: h, x: 2534, y: 2697, width: 36, height: 17639]; DrawBox[h: h, x: 5094, y: 2697, width: 36, height: 16643]; DrawBox[h: h, x: 12065, y: 2697, width: 36, height: 16643]; DrawBox[h: h, x: 17470, y: 2697, width: 36, height: 17639]; DrawBox[h: h, x: 18466, y: 2697, width: 36, height: 17639]; DrawBox[h: h, x: 19462, y: 2697, width: 36, height: 17639]; DrawBox[h: h, x: 20457, y: 2697, width: 36, height: 17639]; DrawBox[h: h, x: 20884, y: 2697, width: 36, height: 17639]; DrawBox[h: h, x: 26716, y: 2697, width: 71, height: 17639]; }; UC: PROC [c: CHAR] RETURNS [CHAR] = { RETURN[IF c IN ['a..'z] THEN VAL[c.ORD - ORD['a] + ORD['A]] ELSE c]}; PressNames: PROC [h: Handle, name: ARRAY [0..4) OF ROPE] = { PTH: PROC [t: ROPE, f: FontClass] = { h.press.SetFontFromCode[h.fontCode[f]]; SirPress.PutTextHere[p: h.press, textString: t]}; NameBreak: IO.BreakProc = { RETURN [SELECT char FROM '&, ', => break, '\t => sepr, -- blanks are allowed in names ENDCASE => other]}; default: FontClass _ nameFont; ns: STREAM _ NIL; GetName: PROC RETURNS [r: ROPE, cl: FontClass, affiliate: BOOLEAN, brk: CHAR] = { cl _ default; affiliate _ FALSE; [] _ ns.SkipWhitespace[]; IF ns.EndOf[] THEN RETURN [NIL, cl, FALSE, 0C]; SELECT ns.PeekChar[] FROM '+ => {h.affiliateThisPage _ affiliate _ TRUE; [] _ ns.GetChar[]}; '* => {cl _ bodyItalic; [] _ ns.GetChar[]}; ENDCASE; r _ GetTokenRope[ns, NameBreak].token; IF ns.EndOf[] THEN brk _ 0C ELSE brk _ ns.GetChar[]}; t: ROPE; bk: CHAR; affiliate: BOOLEAN; x: INT _ nameX; y: INT _ h.entryY; fc: FontClass; ns _ IO.RIS[name[0]]; [t, default, affiliate, bk] _ GetName[]; -- last name IF affiliate THEN { SplatRope[h: h, s: "!", x: x, y: y, f: symbols]; x _ x + MWidth[h, "!", symbols]}; SplatRope[h: h, s: t, x: x, y: y, f: default]; PTH[", ", default]; DO [t, fc, affiliate, bk] _ GetName[]; IF t = NIL THEN EXIT; IF affiliate THEN PTH["!", symbols]; PTH[t, fc]; SELECT bk FROM '& => PTH["& ", default]; ', => PTH[", ", default]; ENDCASE; ENDLOOP; FOR i: CARDINAL IN [1..4) WHILE name[i] # NIL DO y _ y - lineDelta; x _ nameX; ns _ IO.RIS[name[i], ns]; [t, fc, affiliate, bk] _ GetName[]; IF t = NIL THEN LOOP; IF affiliate THEN { SplatRope[h: h, s: "!", x: x, y: y, f: symbols]; x _ x + MWidth[h, "!", symbols]}; SplatRope[h: h, s: t, x: x, y: y, f: fc]; DO SELECT bk FROM '& => PTH["& ", default]; ', => PTH[", ", default]; ENDCASE; [t, fc, affiliate, bk] _ GetName[]; IF t = NIL THEN EXIT; IF affiliate THEN PTH["!", symbols]; PTH[t, fc]; ENDLOOP; ENDLOOP; }; PressPhone: PROC [h: Handle, phone: ARRAY [0..4) OF ROPE] = { y: INT _ h.entryY; FOR i: INT IN [0..4) WHILE phone[i] # NIL DO p: ROPE = phone[i]; x: INT _ phoneX; IF UC[Rope.Fetch[p, 0]] = 'X THEN x _ phoneX + 2540/4; SplatRope[h: h, s: p, x: x, y: y, f: bodyFont]; y _ y - lineDelta; ENDLOOP}; PressEntry: PROC [h: Handle, e: Entry] = { flagged: BOOLEAN; Flag: PROC = { IF flagged THEN RETURN; flagged _ TRUE; h.tsOut.Put[[character['\n]], [rope[e.name[0]]]]}; y: INT; PTH: PROC [t: ROPE, f: FontClass] = { h.press.SetFontFromCode[h.fontCode[f]]; SirPress.PutTextHere[p: h.press, textString: t]}; IF h.prevCaller = 0 THEN h.prevCaller _ e.caller; IF h.entriesOnPage = 10 OR h.prevCaller # e.caller THEN { FinishPage[h]; h.prevCaller _ e.caller}; SplatRope[h: h, s: Rope.FromChar[e.activity], x: activityX, y: h.entryY, f: bodyFont]; IF e.level IN ['1..'9] THEN e.level _ 'p; SplatRope[h: h, s: Rope.FromChar[e.level], x: levelX, y: h.entryY, f: bodyFont]; SplatRope[h: h, s: Rope.FromChar[e.dinner], x: dinnerX, y: h.entryY, f: bodyFont]; SplatRope[h: h, s: Rope.FromChar[e.age], x: ageX, y: h.entryY, f: bodyFont]; PressPhone[h, e.phone]; PressNames[h, e.name]; y _ h.entryY; FOR i: CARDINAL IN [0..4) DO IF e.addr[i] = NIL THEN EXIT; SplatRope[h: h, s: e.addr[i], x: addrX, y: y, f: bodyFont]; y _ y - lineDelta; ENDLOOP; IF e.town # NIL THEN { PL: PROC [t: ROPE] = {SplatRope[h: h, s: t, x: addrX, y: y, f: bodyFont]}; SELECT TRUE FROM Rope.Equal[e.town, "PA"] => PL["Palo Alto, CA "]; Rope.Equal[e.town, "MP"] => PL["Menlo Park, CA "]; Rope.Equal[e.town, "S"] => PL["Stanford, CA "]; Rope.Equal[e.town, "LA"] => PL["Los Altos, CA "]; Rope.Equal[e.town, "LAH"] => PL["Los Altos Hills, CA "]; Rope.Equal[e.town, "C"] => PL["Cupertino, CA "]; Rope.Equal[e.town, "Svl"] => PL["Sunnyvale, CA "]; Rope.Equal[e.town, "A"] => PL["Atherton, CA "]; Rope.Equal[e.town, "EPA"] => PL["Palo Alto, CA "]; Rope.Equal[e.town, "RC"] => PL["Redwood City, CA "]; Rope.Equal[e.town, "MV"] => PL["Mountain View, CA "]; Rope.Equal[e.town, "SC"] => PL["Santa Clara, CA "]; Rope.Equal[e.town, "SJ"] => PL["San Jose, CA "]; Rope.Equal[e.town, "W"] => PL["Woodside, CA "]; Rope.Equal[e.town, "PV"] => PL["Portola Valley, CA "]; Rope.Equal[e.town, "LG"] => PL["Los Gatos, CA "]; Rope.Equal[e.town, "SF"] => PL["San Francisco, CA "]; Rope.Equal[e.town, "SM"] => PL["San Mateo, CA "]; ENDCASE => {Flag[]; PL["???? "]}; }; IF e.zip # NIL THEN { PTH[t: " ", f: bodyFont]; PTH[t: e.zip, f: bodyFont]}; IF e.comment # NIL THEN { SplatRope[h: h, s: e.comment, x: commentX, y: h.entryY, f: bodyItalic]}; h.entryY _ h.entryY - entryDelta; h.entriesOnPage _ h.entriesOnPage + 1; }; FinishPage: PROC [h: Handle] = { caller: CallerNumber = h.prevCaller; recruiter: CallerNumber = h.callerName[caller].recruiter; -- do caller stuff IF h.affiliateThisPage THEN { SplatRope[h: h, x: 22022, y: 1275, f: symbols, s: "!"]; SplatRope[h: h, x: 22235, y: 1275, f: f1, s: "= Affiliate Member"]}; SplatRope[ h: h, x: callerNamePlace.x, y: callerNamePlace.y, s: h.callerName[caller].name, f: nameFont]; SplatRope[ h: h, x: recruiterNamePlace.x, y: recruiterNamePlace.y, s: h.callerName[recruiter].name, f: nameFont]; SplatRope[ h: h, x: callerPhonePlace.x, y: callerPhonePlace.y, s: h.callerName[caller].phone, f: bodyFont]; SplatRope[ h: h, x: recruiterPhonePlace.x, y: recruiterPhonePlace.y, s: h.callerName[recruiter].phone, f: bodyFont]; SplatRope[ h: h, x: datePlace.x, y: datePlace.y, s: h.date, f: f1]; PrintBoilerplate[h]; h.press.WritePage[]; h.entryY _ firstY; h.affiliateThisPage _ FALSE; h.entriesOnPage _ 0; }; MyBreak: IO.BreakProc -- [char: CHAR] RETURNS [IO.CharClass] -- = { RETURN [SELECT char FROM '\\, '|, '}, '\n => break, '\t, ', ' => sepr, ENDCASE => other]; }; OpenFile: PROC [name: ROPE] RETURNS [st: STREAM] = { st _ FS.StreamOpen[name, $read ! FS.Error => IF error.group # bug THEN CONTINUE]}; ProcessEntry: PROC [handle: Handle] = { e: Entry; IF handle.eof THEN RETURN; IF handle.in = NIL THEN { MessageWindow.Append[ message: "Please open a file first", clearFirst: TRUE]; MessageWindow.Blink[ ]; ERROR ABORTED}; [] _ handle.in.SkipWhitespace[]; IF handle.in.EndOf[] THEN {handle.eof _ TRUE; GO TO done}; e _ ReadEntry[handle]; IF handle.press # NIL AND e.caller >= handle.firstCaller THEN PressEntry[handle, e]; EXITS done => NULL; }; ReadEntry: PROC [handle: Handle] RETURNS [e: Entry] = { ENABLE IO.EndOfStream => {handle.eof _ TRUE; Quit[handle, "Syntax error "]}; st: STREAM _ handle.in; ch: CHAR; caller: ROPE; i: CARDINAL; IF (ch _ st.GetChar[]) # '{ THEN Quit[handle, "Syntax error "]; caller _ GetTokenRope[st, MyBreak].token; IF caller # NIL THEN e.caller _ Convert.IntFromRope[caller ! Convert.Error => Quit[handle, "bad caller #"]]; IF (ch _ st.GetChar[]) # '| THEN Quit[handle, "Syntax error "]; BEGIN -- get campaign info IF (ch _ st.GetChar[]) = '| THEN GO TO done; e.activity _ ch; IF (ch _ st.GetChar[]) = '| THEN GO TO done; e.level _ ch; IF (ch _ st.GetChar[]) = '| THEN GO TO done; e.dinner _ ch; IF (ch _ st.GetChar[]) = '| THEN GO TO done; e.age _ ch; IF (ch _ st.GetChar[]) # '| THEN Quit[handle, "Syntax error "]; EXITS done => NULL; END; i _ 0; DO e.phone[i] _ GetTokenRope[st, MyBreak].token; SELECT (ch _ st.GetChar[]) FROM '\\ => IF i = 2 THEN Quit[handle, "Syntax error "]; '| => EXIT; '} => RETURN; ENDCASE => Quit[handle, "Syntax error "]; i _ i + 1; ENDLOOP; i _ 0; DO e.name[i] _ GetTokenRope[st, MyBreak].token; SELECT (ch _ st.GetChar[]) FROM '\\ => IF i = 3 THEN Quit[handle, "Syntax error "]; '| => EXIT; '} => RETURN; ENDCASE => Quit[handle, "Syntax error "]; i _ i + 1; ENDLOOP; i _ 0; DO e.addr[i] _ GetTokenRope[st, MyBreak].token; SELECT (ch _ st.GetChar[]) FROM '\\ => IF i = 3 THEN Quit[handle, "Syntax error "]; '| => EXIT; '} => RETURN; ENDCASE => GO TO badsyntax; i _ i + 1; ENDLOOP; e.town _ GetTokenRope[st, MyBreak].token; IF st.GetChar[] = '} THEN RETURN; e.zip _ GetTokenRope[st, MyBreak].token; IF st.GetChar[] = '} THEN RETURN; e.mailing _ GetTokenRope[st, MyBreak].token; IF st.GetChar[] = '} THEN RETURN; e.comment _ GetTokenRope[st, MyBreak].token; IF st.GetChar[] # '} THEN Quit[handle, "Syntax error "]; EXITS badsyntax => Quit[handle, "Syntax error "]; }; ParseCallerNames: PROC [h: Handle] RETURNS [n: REF CallerNameRec] = { cnfile: ROPE _ ViewerTools.GetContents[h.cmd.callers]; ch: CHAR; r: INT _ 0; index: INT; c, p: ROPE; st: STREAM; n _ NEW[CallerNameRec _ ALL[[NIL, NIL, 0]]]; st _ OpenFile[cnfile]; IF st = NIL THEN Quit2[h, st, "No caller names"]; WHILE ~st.EndOf[] DO ENABLE IO.Error => Quit2[h, st, "invalid callernames"]; c _ p _ NIL; [] _ st.SkipWhitespace[]; IF st.EndOf[] THEN RETURN; index _ st.GetInt[]; IF NOT (index IN [0..100)) THEN Quit2[h, st, "Index invalid in callernames"]; IF st.GetChar[] # '\t THEN Quit2[h, st, "Missing tab in callernames"]; c _ GetTokenRope[st, MyBreak].token; BEGIN IF ~st.EndOf[] THEN SELECT (ch _ st.GetChar[]) FROM '\n => GO TO done; '| => NULL; ENDCASE => Quit2[h, st, "Syntax error in callernames"]; p _ GetTokenRope[st, MyBreak].token; IF ~st.EndOf[] THEN SELECT (ch _ st.GetChar[]) FROM '\n => GO TO done; '| => NULL; ENDCASE => Quit2[h, st, "Syntax error in callernames"]; [] _ st.SkipWhitespace[]; IF st.EndOf[] THEN RETURN; r _ st.GetInt[]; IF st.GetChar[] # '\n THEN Quit2[h, st, "Missing CR in callernames"]; EXITS done => NULL; END; n[index] _ [name: c, phone: p, recruiter: r]; ENDLOOP; st.Close[]}; Quit: PROC [handle: Handle, reason: ROPE _ NIL] = { loc: INT = handle.in.GetIndex[]; handle.in.Close[]; handle.in _ NIL; handle.eof _ TRUE; handle.tsOut.Put[[rope[reason]], [integer[loc]], [character['\n]]]; ERROR Problem}; Quit2: PROC [handle: Handle, st: STREAM, reason: ROPE _ NIL] = { loc: INT = st.GetIndex[]; st.Close[]; handle.tsOut.Put[[rope[reason]], [character[' ]]]; handle.tsOut.Put[[integer[loc]], [character['\n]]]; ERROR Problem}; GetToken: PROC [stream: STREAM, breakProc: IO.BreakProc, buffer: REF TEXT] RETURNS[token: REF TEXT, charsSkipped: INT] = { quit, include: BOOL _ FALSE; anySeen: BOOL _ FALSE; charsSkipped _ 0; buffer.length _ 0; DO char: CHAR _ stream.GetChar[ ! IO.EndOfStream => IF buffer.length > 0 THEN EXIT ELSE REJECT]; SELECT breakProc[char] FROM break => {include _ FALSE; quit _ TRUE}; sepr => {include _ FALSE; quit _ anySeen }; other => {include _ TRUE; quit _ FALSE; anySeen _ TRUE}; ENDCASE => ERROR; IF include THEN buffer _ RefText.InlineAppendChar[buffer, char] ELSE IF quit THEN stream.Backup[char] ELSE charsSkipped _ charsSkipped + 1; IF quit THEN EXIT; ENDLOOP; RETURN[buffer, charsSkipped]; }; GetTokenRope: PUBLIC PROC [stream: STREAM, breakProc: IO.BreakProc] RETURNS [token: ROPE, charsSkipped: INT] = { buffer: REF TEXT = RefText.ObtainScratch[100]; { ENABLE UNWIND => RefText.ReleaseScratch[buffer]; tokenText: REF TEXT; [tokenText, charsSkipped] _ GetToken[stream, breakProc, buffer]; token _ IF tokenText.length = 0 THEN NIL ELSE Rope.FromRefText[tokenText]; }; RefText.ReleaseScratch[buffer]; RETURN [token, charsSkipped]; }; Commander.Register[key: "PrintForms", proc: MakeTool, doc: "Create a campaign forms printer" ]; [ ] _ MakeTool[NIL]; -- and create an instance END. άPrintForms.mesa; Last Edited by: Sweet, October 8, 1984 2:01:09 pm PDT The Containers interface is used to create an outer envelope or "container" for the different sections below. For uniformity, we define some standard distances between entries in the tool. default the width so that it will be computed for us -- default the width so that it will be computed for us -- default the width so that it will be computed for us -- force the selection into the user input field force the selection into the user input field Copied from Castilleja output end of copy do I have to close ns? NO. one should SkipWhitespace before calling (and check for eof) copied from IOSearchImpl because it didn't handle empty tokens properly Κ– "Cedar" style˜Iproc– "Cedar" stylešœ™J™5unitšΟk ˜ Lšœ˜J˜ Jšœ˜Jšœ œ˜(Jšœ œ/˜?J˜Jšœ˜Jšœ˜J˜J˜J˜Jšœ˜Jšœœ˜J˜ J˜ J˜J˜J˜ J˜Jšœœ˜-Jšœ œ˜%Jšœ œ˜,Jšœ œ0˜A—šœ œœ˜Jšœ9œ…˜Η—Lšœœ˜Jšœ½™½J˜Jšœ  œœ˜šœ"˜'Jšœ˜Jšœ œ˜emphasisšœΟcœ˜>Jšœž ˜7Jšœœž4˜DJšœž˜0Jšœ œœž'˜>—Jšœž!˜4JšœP˜PJšœ'˜'Jšœ)ž˜=Jšœ˜Jšœ)ž˜@Jšœ˜—J˜Jšœ œ˜Jšœ œ˜Jšœ œ˜Jšœœ˜J˜šΟn œœ˜&š Ÿœœœœ œœ ˜pšœ2˜2J˜J˜ J˜J˜ —˜(˜J˜'J˜%J˜,J˜—J˜#—J˜—J˜'Jšœ˜Jšœ'˜'Jšœ˜Jšœ˜Jšœ*˜*Jšœ(˜(Jšœ1˜1Jšœ˜Jšœ˜—šŸœœœ˜.Jšœ-ž(˜Ušœ˜JšœOœ˜X—šœ<˜Jšœ%˜%Jšœœ ˜6šœ#˜#šœ˜Jšœ˜Jšœ˜Jšœ7™7Jšœž4˜EJšœ˜Jšœ˜Jšœœ˜—Jšœ ˜ Jšœž)˜:—Jšœ˜šœ$˜$Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ ˜ Jšœ œ˜Jšœœ˜—J˜Jšœ˜—šŸœœ œ˜5šœ#˜#šœ˜Jšœ ˜ J˜Jšœ˜Jšœ7™7Jšœž4˜EJšœ˜Jšœœ˜—Jšœ ˜ Jšœž(œ˜>—Jšœ˜—šŸœœ œ œœœœ˜DJ˜Jšœœœ ˜šœ˜šœ˜Jšœ ˜ J˜Jšœ˜Jšœ7™7Jšœž4˜EJšœ˜Jšœœ˜—Jšœ˜Jšœž(œ˜<—J•StartOfExpansion[]š œ,œ œœœ˜lJšœ˜—J˜Jšœ ˜ J˜J˜Jšœ ˜ Jšœ<˜˜>JšœK˜KJ˜Jšœ ˜ J˜Jšœ˜—–† -- [parent: REF ANY, clientData: REF ANY _ NIL, mouseButton: Menus.MouseButton _ red, shift: BOOL _ FALSE, control: BOOL _ FALSE] -- šœΠck…œ˜©Jšœ-™-Jšœœ ˜&Jšœ&ž˜