DIRECTORY Ascii, Buttons, Commander USING [CommandProc, Register], Containers USING [ChildXBound, Container, Create], Convert, FS, IO, LandPrintDefs, MessageWindow, RefText, Rope, Rules USING [Create, Rule], SafeStorage, SirPress, TSFont, TSTypes, ViewerClasses USING [Viewer, ViewerClassRec], ViewerOps USING [PaintViewer], ViewerTools USING [GetContents]; LandPrintDirB: CEDAR PROGRAM IMPORTS Commander, Containers, Convert, FS, IO, LandPrintDefs, MessageWindow, RefText, Rope, Rules, SafeStorage, SirPress, TSFont, TSTypes, ViewerOps, ViewerTools EXPORTS LandPrintDefs = BEGIN OPEN LandPrintDefs; entryHeight: CARDINAL = 15; -- how tall to make each line of items entryVSpace: CARDINAL = 8; -- vertical leading space between lines entryHSpace: CARDINAL = 10; -- horizontal space between items in a line dash: CHAR = Ascii.ControlV; frontMatterPages: CARDINAL _ 2; PromptRec: TYPE = RECORD [ handle: Handle, viewer: ViewerClasses.Viewer _ NIL]; PromptHandle: TYPE = REF PromptRec; MakeTool: Commander.CommandProc = BEGIN rule: Rules.Rule; my: Handle _ NEW[MyRec]; my.outer _ Containers.Create[[-- construct the outer container name: "Landscape Directory 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; DoIt: PUBLIC 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]; nSheets: CARDINAL; 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; handle.pageNumber _ 1; IF pName # NIL AND Rope.Length[pName] # 0 THEN { nameAddr, fumcWidth: INT; handle.out _ FS.StreamOpen[fileName: pName, accessOptions: $create]; handle.press _ SirPress.Create[outputStream: handle.out, fileNameForHeaderPage: pName]; handle.dim.yLead _ Val[handle.cmd.yLead, 8]; handle.dim.fontSize _ Val[handle.cmd.fontSize, 10]; handle.dim.lineHeight _ Val[handle.cmd.lineHeight, 12]; handle.dim.pageWidth _ Val[handle.cmd.pageWidth, 612]; handle.dim.pageHeight _ Val[handle.cmd.pageHeight, 792]; handle.dim.topMargin _ Val[handle.cmd.topMargin, 72]; handle.dim.bottomMargin _ Val[handle.cmd.bottomMargin, 60]; handle.dim.leftMargin _ Val[handle.cmd.leftMargin, 54]; handle.dim.rightMargin _ Val[handle.cmd.rightMargin, 72]; handle.dim.fudgePoints _ Val[handle.cmd.fudgePoints, 6]; handle.dim.displayHeight _ Val[handle.cmd.displayHeight, 18]; handle.dim.tabHeight _ Val[handle.cmd.tabHeight, 8]; handle.dim.nameIndent _ Val[handle.cmd.nameIndent, 18]; handle.press.SetPageSize[110, 85]; LookupFonts[handle]; handle.yTop _ handle.dim.pageHeight - handle.dim.topMargin; handle.phoneX _ handle.dim.leftMargin; handle.phoneX2 _ handle.phoneX + PWidth[handle, "(415) ", body]; handle.nameX _ handle.phoneX + PWidth[handle, "(415) 321-9039", body] + 12; handle.zipX _ handle.dim.pageWidth - handle.dim.rightMargin - PWidth[handle, "94303", body]; handle.townX _ handle.zipX - PWidth[handle, "EPA", body] - 9; nameAddr _ handle.townX - handle.nameX; handle.addrX _ handle.nameX; handle.addrPWidth _ handle.townX - handle.addrX; fumcWidth _ PWidth[handle, "FUMPA", headingLarge] + PWidth[handle, "IRST NITED ETHODIST, ALO LTO", headingSmall]; handle.fumcX _ RightX[handle, fumcWidth]; handle.prevInitial _ 0C; handle.prevZip _ NIL; handle.firstOnPage _ NIL; handle.affiliateThisPage _ FALSE; handle.entry _ NEW[EntrySeqBody[1000]]; handle.page _ NEW[PageDataSeqBody[100]]; FOR j: CARDINAL IN [0..100) DO handle.page[j] _ []; ENDLOOP; handle.page.count _ frontMatterPages; -- for front matter handle.page[frontMatterPages] _ [start: 0, number: 1]; handle.reallyPrinting _ FALSE; } ELSE Quit[handle, "No output file"]; handle.tsOut.PutText["Reading:"]; WHILE ~handle.eof DO InputEntry[handle]; ENDLOOP; IF handle.firstOnPage # NIL THEN { handle.entry.count _ handle.entry.count + 1; FinishPage[handle]}; handle.reallyPrinting _ TRUE; handle.pageParity _ 0; handle.pageLoc _ R90T; handle.tsOut.PutText["Printing:"]; PrintCover[handle]; IF handle.perfectBind^ THEN { FOR k: CARDINAL IN [0..handle.page.count) DO ReprintPage[handle, k]; ReprintPage[handle, k]; ENDLOOP; } ELSE { nSheets _ (handle.page.count +3)/4; FOR k: CARDINAL IN [0..nSheets) DO ReprintPage[handle, 2*k]; ReprintPage[handle, 4*nSheets - 2*k -1]; ReprintPage[handle, 2*k + 1]; ReprintPage[handle, 4*nSheets - 2*k -2]; ENDLOOP; }; 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]]]; handle.entry _ NIL; handle.page _ NIL; END; PrintCover: PROC [h: Handle] = { PT: PROC [t: ROPE, x, y: INT] = {PrintText[h, t, x, y]}; PTH: PROC [t: ROPE, f: FontClass] = {SetFont[h, f]; PrintHere[h, t]}; SF: PROC [class: FontClass] = {SetFont[h, class]}; y: INT _ h.dim.pageHeight - h.dim.topMargin - h.dim.displayHeight; CenterText[h, y, "MEMBERSHIP DIRECTORY", display]; y _ y - 2*h.dim.lineHeight; CenterText[h, y, "September 15, 1985", display]; y _ h.dim.bottomMargin + 7 * h.dim.lineHeight; CenterText[h, y, "First United Methodist Church", display]; y _ y - 2*h.dim.lineHeight; CenterText[h, y, "625 Hamilton Avenue at Webster", display]; y _ y - 2*h.dim.lineHeight; CenterText[h, y, "Palo Alto, California 94301", display]; y _ y - 2*h.dim.lineHeight; CenterText[h, y, "Telephone: (415) 323-6167", display]; h.press.WritePage[]}; PrintFrontMatter: PROC [h: Handle, number: CARDINAL] = { PT: PROC [t: ROPE, x, y: INT] = {PrintText[h, t, x, y]}; PTH: PROC [t: ROPE, f: FontClass] = {SetFont[h, f]; PrintHere[h, t]}; SF: PROC [class: FontClass] = {SetFont[h, class]}; y: INT _ h.dim.pageHeight - h.dim.topMargin - h.dim.displayHeight; w, x: INT; LabeledName: PROC [label, name: ROPE, bold: BOOL _ TRUE] = { SF[IF bold THEN bodyBold ELSE title]; PT[label, x, y]; PTH[" \030 ", title]; PTH[name, title]; y _ y - (3*h.dim.lineHeight)/2; }; TownAbbr: PROC [abbr, name: ROPE] = { PT[abbr, x, y]; PT[name, x+30, y]; y _ y - h.dim.lineHeight; }; SELECT number FROM 0 => { CenterText[h, y, "First United Methodist Church", display]; y _ y - 2*h.dim.lineHeight; CenterText[h, y, "625 Hamilton Avenue Palo Alto, California 94301", bodyBold]; y _ y - h.dim.lineHeight; CenterText[h, y, "Telephone: (415) 323-6167", bodyBold]; y _ y - 3*h.dim.lineHeight; CenterText[h, y, "Office Hours: 9:00-5:00 Monday through Friday", bodyBold]; y _ y - 3*h.dim.lineHeight; CenterText[h, y, "Church Staff", display]; y _ y - 2*h.dim.lineHeight; x _ CenterX[h, PWidth[h, "Office Hours: 9:00-5:00 Monday through Friday", bodyBold]]; SF[bodyBold]; PT["Ministers", x, y]; PTH[" \030 ", title]; w _ PWidth[h, "Ministers", bodyBold] + PWidth[h, " \030 ", title]; PT["Douglas I. Norris", x+w, y]; y _ y - h.dim.lineHeight; PT["Glenn S. Fuller", x+w, y]; y _ y - (3*h.dim.lineHeight)/2; LabeledName["Church Business Administrator", "Florence T. Wegner"]; SF[bodyBold]; PT["Secretaries", x, y]; PTH[" \030 ", title]; w _ PWidth[h, "Secretaries", bodyBold] + PWidth[h, " \030 ", title]; PT["Finance: Ruth Willard", x+w, y]; y _ y - h.dim.lineHeight; PT["Ministers: Joanne Perry", x+w, y]; y _ y - h.dim.lineHeight; PT["Communications: Cathy Floyd", x+w, y]; y _ y - (3*h.dim.lineHeight)/2; LabeledName["Director of Children's Ministry", "Dorothy Power"]; LabeledName["Director of Youth Ministry", "Neli Moody-Berne"]; LabeledName["Director of Music", "Leroy Kromm"]; LabeledName["Organist", "Steven Gray"]; SF[bodyBold]; PT["Choir Directors", x, y]; y _ y - (3*h.dim.lineHeight)/2; x _ x + 18; LabeledName["Chancel Choir", "Leroy Kromm", FALSE]; LabeledName["Youth and Adult Choirs", "Leroy Kromm", FALSE]; LabeledName["Children's Choirs", "Linda Jordan", FALSE]; LabeledName["Handbell Choirs", "Sara Salsbury", FALSE]; x _ x - 18; LabeledName["Custodian", "Brian Neeley"]; LabeledName["Librarian", "Virginia Williams"]; LabeledName["Membership Secretary", "Barbara Busby"]; y _ y - (3*h.dim.lineHeight)/2; CenterText[h, y, "Education building pay phone: (415) 853-8801", bodyBold]; y _ y - (3*h.dim.lineHeight)/2; CenterText[h, y, "Sanctuary pay phone: (415) 853-8843", bodyBold]; }; 1 => { y _ h.dim.bottomMargin + 15 * h.dim.lineHeight; x _ 72; SF[body]; PT["This Directory includes the names of those persons on the church", x, y]; y _ y - h.dim.lineHeight; PT["roll as of September 15, 1985. Non-member spouses and children", x, y]; y _ y - h.dim.lineHeight; PT["not yet confirmed in membership are shown in ", x, y]; PTH["italics.", smallItalic]; SF[body]; y _ y - 2*h.dim.lineHeight; PT["Cities are indicated as follows:", x, y]; y _ y - 2*h.dim.lineHeight; y _ h.dim.bottomMargin + 9 * h.dim.lineHeight; TownAbbr["A", "Atherton"]; TownAbbr["C", "Cupertino"]; TownAbbr["EPA", "East Palo Alto"]; TownAbbr["LA", "Los Altos"]; TownAbbr["LAH", "Los Altos Hills"]; TownAbbr["MP", "Menlo Park"]; TownAbbr["MV", "Mountain View"]; TownAbbr["PA", "Palo Alto"]; TownAbbr["PV", "Portola Valley"]; y _ h.dim.bottomMargin + 9 * h.dim.lineHeight; x _ 3*72; TownAbbr["RC", "Redwood City"]; TownAbbr["S", "Stanford"]; TownAbbr["Svl", "Sunnyvale"]; TownAbbr["SC", "Santa Clara"]; TownAbbr["SF", "San Francisco"]; TownAbbr["SJ", "San Jose"]; TownAbbr["SM", "San Mateo"]; TownAbbr["W", "Woodside"]; }; ENDCASE; NewPage[h]}; CenterText: PROC [h: Handle, y: INT, t: ROPE, f: FontClass] = { SetFont[h, f]; PrintText[h, t, CenterX[h, PWidth[h, t, f]], y]}; CenterX: PROC [h: Handle, w: INT] RETURNS [x: INT] = { RETURN[ h.dim.leftMargin + (h.dim.pageWidth - h.dim.leftMargin - h.dim.rightMargin - w)/2]}; RightX: PROC [h: Handle, w: INT] RETURNS [x: INT] = { RETURN[h.dim.pageWidth - h.dim.rightMargin - w]}; PWidth: 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.pt]]; }; UC: PROC [c: CHAR] RETURNS [CHAR] = { RETURN[IF c IN ['a..'z] THEN VAL[c.ORD - ORD['a] + ORD['A]] ELSE c]}; CFName: PROC [h: Handle, name: ROPE] RETURNS [cf: ROPE] = { funny: BOOLEAN _ FALSE; lastName: REF TEXT _ NEW[TEXT[Rope.Length[name]]]; -- plenty long FOR i: INT IN [0..Rope.Length[name]) DO c: CHAR _ UC[Rope.Fetch[name, i]]; SELECT c FROM ', => EXIT; '*, '+ => LOOP; ENDCASE => { IF c = ' AND ~funny THEN { funny _ TRUE; h.tsOut.Put[[character['\n]], [rope[name]], [character['\n]]]}; lastName[lastName.length] _ c; lastName.length _ lastName.length + 1}; ENDLOOP; RETURN[Rope.FromRefText[lastName]]}; PressNames: PROC [h: Handle, name: ARRAY [0..5) OF ROPE] = { ascent: INT = h.dim.fontSize; PT: PROC [t: ROPE, x, y: INT] = {PrintText[h, t, x, y]}; PTH: PROC [t: ROPE, f: FontClass] = {SetFont[h, f]; PrintHere[h, t]}; SF: PROC [class: FontClass] = {SetFont[h, class]}; NameBreak: IO.BreakProc = { RETURN [SELECT char FROM '&, ', => break, '\t => sepr, -- blanks are allowed in names ENDCASE => other]}; default: FontClass _ bodyBold; 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; fc: FontClass; ns _ IO.RIS[name[0]]; [t, default, affiliate, bk] _ GetName[]; -- last name IF affiliate THEN { SF[symbols]; PT[t: "!", x: h.nameX - PWidth[h, "!", symbols], y: h.yTop - ascent]}; SF[default]; PT[t: t, x: h.nameX, y: h.yTop - ascent]; 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..nLines) WHILE name[i] # NIL DO y: INT = h.yTop - i*h.dim.lineHeight - ascent; x: INT _ MAX[h.nameX + h.dim.nameIndent, h.phoneLast[i] + 12]; ns _ IO.RIS[name[i], ns]; [t, fc, affiliate, bk] _ GetName[]; IF t = NIL THEN LOOP; IF affiliate THEN { SF[symbols]; PT[t: "!", x: h.nameX + h.dim.nameIndent - PWidth[h, "!", symbols], y: y]}; SF[fc]; PT[t: t, x: x, y: h.yTop - i*h.dim.lineHeight - ascent]; 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..5) OF ROPE] = { ascent: INT = h.dim.fontSize; number: ROPE; SF: PROC [class: FontClass] = {SetFont[h, class]}; PT: PROC [t: ROPE, x, y: INT] = {PrintText[h, t, x, y]}; PTH: PROC [t: ROPE, f: FontClass] = {SetFont[h, f];PrintHere[h, t]}; h.phoneLast _ ALL[0]; FOR i: INT IN SmallCount WHILE phone[i] # NIL DO p: ROPE = phone[i]; y: INT = h.yTop - i*h.dim.lineHeight - ascent; x: INT _ h.phoneX; first: INT _ 0; len: INT = Rope.Length[p]; last: INT _ len; work: BOOLEAN _ FALSE; IF UC[Rope.Fetch[p, 0]] = 'W THEN {work _ TRUE; first _ 1}; IF len > 6 THEN FOR j: INT IN [6..len) DO IF Rope.Fetch[p, j] = '( THEN {last _ j; EXIT}; ENDLOOP; IF Rope.Length[p] > first+6 AND Rope.Equal[Rope.Substr[p, first, 6], "(415) "] THEN { x _ h.phoneX2; first _ first + 6}; IF UC[Rope.Fetch[p, first]] = 'X THEN x _ h.phoneX2 + 12; IF work THEN { SF[bodyItalic]; PT[t: "w", x: x-PWidth[h, "w", bodyItalic]-2, y: y]}; number _ Rope.Substr[p, first, last - first]; SF[body]; PT[t: number, x: x, y: y]; h.phoneLast[i] _ x + PWidth[h, number, body]; IF last < len THEN { name: ROPE = Rope.Substr[p, last, len - last]; PTH[t: name, f: tiny]; h.phoneLast[i] _ h.phoneLast[i] + PWidth[h, name, tiny]}; ENDLOOP}; PressEntry: PROC [h: Handle, e: Entry] = { ascent: INT = h.dim.fontSize; lastName: ROPE; eLines: CARDINAL _ 1; pLines, aLines, nLines: CARDINAL _ 0; addLine, tLine, zLine: CARDINAL _ 0; newLetter: BOOLEAN _ FALSE; PT: PROC [t: ROPE, x, y: INT] = {PrintText[h, t, x, y]}; x, eh, eh2: INT; myFirst: CHAR; ez: ROPE _ IF e.zip = NIL THEN "" ELSE e.zip; FOR i: CARDINAL DECREASING IN SmallCount DO IF e.phone[i] # NIL THEN {pLines _ i+1; EXIT}; ENDLOOP; FOR i: CARDINAL DECREASING IN SmallCount DO IF e.name[i] # NIL THEN { addLine _ nLines _ i+1; tLine _ addLine; EXIT}; ENDLOOP; FOR i: CARDINAL DECREASING IN SmallCount DO IF e.addr [i] # NIL THEN {aLines _ i+1; EXIT}; ENDLOOP; eLines _ MAX[pLines, nLines + aLines]; IF e.town # NIL THEN { tLine _ addLine; WHILE PWidth[h, e.addr[tLine], body] > h.addrPWidth DO IF tLine = nLines-1 THEN Quit[h, "no room for town"]; tLine _ tLine + 1; ENDLOOP; zLine _ tLine} ELSE { tLine _ 0; FOR i: CARDINAL DECREASING IN SmallCount DO IF e.addr[i] # NIL THEN {zLine _ i + addLine; EXIT}; ENDLOOP; }; eLines _ MAX[eLines, tLine+1, zLine+1]; eh _ eLines * h.dim.lineHeight; lastName _ CFName[h, e.name[0]]; myFirst _ Rope.Fetch[lastName, 0]; newLetter _ SELECT TRUE FROM h.alphaSort^ => h.prevInitial # myFirst, ENDCASE => FALSE; IF newLetter THEN eh2 _ eh + 2*h.dim.displayHeight ELSE eh2 _ eh; IF h.yTop - eh2 < h.dim.bottomMargin THEN FinishPage[h]; IF newLetter THEN { l: ROPE = Rope.FromChar[myFirst]; h.yTop _ h.yTop - h.dim.displayHeight; SetFont[h, display]; PT[t: l, x: CenterX[h, PWidth[h, l, display]], y: h.yTop]; h.tsOut.PutChar[myFirst]; h.yTop _ h.yTop - h.dim.displayHeight; h.prevInitial _ myFirst; h.prevZip _ ez}; SetFont[h, body]; PressPhone[h, e.phone]; PressNames[h, e.name]; SetFont[h, body]; x _ h.addrX; FOR i: CARDINAL IN SmallCount DO IF e.addr[i] = NIL THEN EXIT; PT[t: e.addr[i], x: x, y: h.yTop - (addLine + i)*h.dim.lineHeight - ascent]; ENDLOOP; IF e.town # NIL THEN PT[t: e.town, x: h.townX, y: h.yTop - tLine*h.dim.lineHeight - ascent]; IF e.zip # NIL THEN PT[t: e.zip, x: h.zipX, y: h.yTop - zLine*h.dim.lineHeight - ascent]; h.yTop _ h.yTop - eh - h.dim.yLead; h.lastOnPage _ lastName; IF h.firstOnPage = NIL THEN h.firstOnPage _ lastName; }; FinishPage: PROC [h: Handle] = { names, pageText: ROPE; nx, hy: INT; PT: PROC [t: ROPE, x, y: INT] = {PrintText[h, t, x, y]}; PTH: PROC [t: ROPE, f: FontClass] = {SetFont[h, f]; PrintHere[h, t]}; SF: PROC [class: FontClass] = {SetFont[h, class]}; Rectangle[h: h, xstart: h.dim.leftMargin, ystart: h.dim.pageHeight - h.dim.topMargin + h.dim.lineHeight, xlen: h.dim.pageWidth - h.dim.leftMargin - h.dim.rightMargin, ylen: 1]; names _ IF Rope.Equal[h.firstOnPage, h.lastOnPage] THEN h.firstOnPage ELSE Rope.Cat[h.firstOnPage, Rope.FromChar[dash], h.lastOnPage]; hy _ h.dim.pageHeight - h.dim.topMargin + 2*h.dim.lineHeight; IF ~h.duplex^ OR (h.pageNumber MOD 2 = 1) THEN { nx _ RightX[h, PWidth[h, names, tabs]]; PT[t: "Fall 1985", x: h.dim.leftMargin, y: hy]; } ELSE { nx _ h.dim.leftMargin; SF[headingLarge]; PT[t: "F", x: h.fumcX, y: hy]; PTH["IRST ", headingSmall]; PTH["U", headingLarge]; PTH["NITED ", headingSmall]; PTH["M", headingLarge]; PTH["ETHODIST, ", headingSmall]; PTH["P", headingLarge]; PTH["ALO ", headingSmall]; PTH["A", headingLarge]; PTH["LTO", headingSmall]; SF[date]; }; SF[tabs]; PT[t: names, x: nx, y: hy]; pageText _ Convert.RopeFromInt[h.pageNumber]; nx _ CenterX[h, PWidth[h, pageText, pageNum]]; SF[pageNum]; PT[t: pageText, x: nx, y: h.dim.bottomMargin - 3*h.dim.lineHeight]; IF h.affiliateThisPage THEN { SF[symbols]; PT["!", h.dim.leftMargin, h.dim.bottomMargin - (3*h.dim.lineHeight/2)]; PTH[" affiliate member", bodyItalic]}; NewPage[h]; h.yTop _ h.dim.pageHeight - h.dim.topMargin; h.firstOnPage _ h.lastOnPage _ NIL; h.affiliateThisPage _ FALSE; h.pageNumber _ h.pageNumber + 1; }; ReprintPage: PROC [h: Handle, pg: CARDINAL] = { pd: PageData _ h.page[pg]; start: INT _ pd.start; limit: INT _ h.page[pg+1].start; IF pg < frontMatterPages THEN {PrintFrontMatter[h, pg]; RETURN}; IF start = -1 OR limit = -1 THEN NewPage[h] ELSE { h.prevInitial _ pd.initial; h.pageNumber _ pd.number; FOR i: INT IN [start..limit) DO PressEntry[h, h.entry[i]]; ENDLOOP; FinishPage[h]}; }; Problem: ERROR = CODE; Xform: PROC [h: Handle, x, y: INT] RETURNS [xPrime, yPrime: INT] = { SELECT h.pageLoc FROM R90T => RETURN[17*36 - y, 11 * 36 - h.dim.fudgePoints + x]; R90B => RETURN[17*36 - y, x]; R270T => RETURN[y, 11 * 72 - h.dim.fudgePoints - x]; R270B => RETURN[y, 11 * 36 - x]; ENDCASE; }; PrintText: PROC [h: Handle, t: ROPE, x, y: INT] = { xT, yT: INT; IF h.reallyPrinting THEN { [xT, yT] _ Xform[h, x, y]; SirPress.PutText[p: h.press, textString: t, xCoordinateOfLeftEdge: xT, yCoordinateOfBaseline: yT, unit: SirPress.pt]; }; }; PrintHere: PROC [h: Handle, t: ROPE] = { IF h.reallyPrinting THEN SirPress.PutTextHere[p: h.press, textString: t]}; SetFont: PROC [h: Handle, f: FontClass] = { rot: Rotation _ (SELECT h.pageLoc FROM R90T, R90B => R90, ENDCASE => R270); IF h.reallyPrinting THEN h.press.SetFontFromCode[h.fontCode[rot][f]]; }; Rectangle: PROC [h: Handle, xstart, ystart, xlen, ylen: INT] = { xT, yT: INT; xStop, yStop: INT; [xT, yT] _ Xform[h, xstart, ystart]; [xStop, yStop] _ Xform[h, xstart + xlen, ystart + ylen]; IF h.reallyPrinting THEN SELECT h.pageLoc FROM R90T, R90B => h.press.PutRectangle[xstart: xStop, ystart: yT, xlen: ylen, ylen: xlen, unit: SirPress.pt]; R270T, R270B => h.press.PutRectangle[xstart: xT, ystart: yStop, xlen: ylen, ylen: xlen, unit: SirPress.pt]; ENDCASE; }; NewPage: PROC [h: Handle] = { IF h.reallyPrinting THEN { h.pageParity _ (h.pageParity + 1) MOD 4; SELECT h.pageParity FROM 1 => h.pageLoc _ R90B; 2 => {h.press.WritePage[]; h.pageLoc _ IF h.oneRot^ THEN R90B ELSE R270T}; 3 => h.pageLoc _ IF h.oneRot^ THEN R90T ELSE R270B; 0 => {h.press.WritePage[]; h.pageLoc _ R90T}; ENDCASE} ELSE { h.page.count _ h.page.count + 1; h.page[h.page.count] _ [ start: h.entry.count - 1, initial: h.prevInitial, number: h.pageNumber + 1]; }; }; MyBreak: IO.BreakProc -- [char: CHAR] RETURNS [IO.CharClass] -- = { RETURN [SELECT char FROM '\\, '|, '} => 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]}; InputEntry: 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]; handle.entry[handle.entry.count] _ e; handle.entry.count _ handle.entry.count + 1; 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; i: CARDINAL; IF (ch _ st.GetChar[]) # '{ THEN Quit[handle, "Syntax error "]; i _ 0; DO e.phone[i] _ GetTokenRope[st, MyBreak].token; SELECT (ch _ st.GetChar[]) FROM '\\ => IF i = nLines-1 THEN Quit[handle, "Syntax error "]; '| => EXIT; '} => RETURN; ENDCASE => Quit[handle, "Syntax error "]; i _ i + 1; ENDLOOP; { smash: BOOL _ FALSE; FOR j: NAT IN SmallCount DO IF smash THEN e.phone[j] _ NIL ELSE IF e.phone[j] # NIL AND UC[Rope.Fetch[e.phone[j], 0]] = 'W THEN { smash _ TRUE; e.phone[j] _ NIL}; ENDLOOP; }; i _ 0; DO e.name[i] _ GetTokenRope[st, MyBreak].token; SELECT (ch _ st.GetChar[]) FROM '\\ => IF i = nLines-1 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 = nLines-1 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; GO TO badsyntax; EXITS badsyntax => Quit[handle, "Syntax error "]; }; 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}; 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: "LandPrintDir", proc: MakeTool, doc: "Create a church directory printer" ]; [ ] _ MakeTool[NIL]; -- and create an instance END. ÜLandPrintDirB.mesa; Last Edited by: Sweet, September 15, 1985 2:40:27 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. force the selection into the user input field do I have to close ns? one should SkipWhitespace before calling (and check for eof) copied from IOSearchImpl because it didn't handle empty tokens properly Ê´– "Cedar" style˜Icode– "Cedar" stylešœ™K™8šÏk ˜ Kšœ˜Kšœ˜Kšœ œ˜(Kšœ œ"˜2K˜Kšœ˜Kšœ˜K˜K˜K˜Kšœ˜Kšœœ˜K˜ K˜ K˜K˜Kšœœ˜-Kšœ œ˜Kšœ œ˜ —šœœœ˜ Kšœ%œu˜£Kšœ˜—Kšœœ˜Kšœ½™½Kšœ œÏc&˜BKšœ œž'˜CKšœ œž+˜HKšœœ˜K˜Kšœœ˜K˜K˜šœ œœ˜Kšœ/œ˜4—Kšœœœ ˜#šœ"˜'Kšœ˜Kšœ œ˜šœžœ˜>Kšœ%ž ˜EKšœœž4˜DKšœž˜0Kšœ œœž'˜>—Kšœž!˜4KšœP˜PKšœ'˜'Kšœ)ž˜=Kšœ˜Kšœ)ž˜@Kšœ˜—K˜•StartOfExpansion† -- [parent: REF ANY, clientData: REF ANY _ NIL, mouseButton: Menus.MouseButton _ red, shift: BOOL _ FALSE, control: BOOL _ FALSE] -- šÏnœœÐck…œ˜®Kšœ-™-Kšœœž˜4Kš˜šœ˜Kš œœ œœ œ˜GKšœ œ'œœ˜D—Kšœœ1˜K˜0K˜'K˜ K˜Kšœ˜K˜ Kšœ,œ˜3Kšœ5œ˜K˜K˜#Kšœœœœ˜šœ œ˜Kšœ œI˜X—Kšœ˜Kšœ6˜8š˜šœ˜Kšœœ˜Kšœœ˜Kšœ˜—K˜#Kšœœœœ˜Kšœ œœ˜$Kšœ˜ Kšœ˜—Kšœ˜—K˜K˜—š Ÿ œœœœœ˜=Kšœœ˜Kšœœ˜ Kšœœ*˜2Kšœœœœ˜8Kšœœœ2˜DKšœœ˜š œœœ œ œ˜0Kšœœ ˜Kšœœ(˜.Kšœœ ˜Kšœœ˜Kšœœ˜Kšœœ˜Kšœœœ˜Kšœœ œ ˜;š œ œœœœ ˜)Kšœœ œ˜/Kšœ˜—šœœ0œ˜VK˜"—Kšœœœ˜9šœœ˜Kšœœ3˜E—Kšœ-˜-Kšœ"˜$K˜-šœ œ˜Kšœ.˜.Kšœ˜Kšœ9˜9—Kšœ˜ —K˜—šŸ œœ˜*Kšœœ˜Kšœ œ˜Kšœœ˜Kšœœ˜%Kšœœ˜$Kšœ œœ˜Kšœœœœ˜8Kšœ œ˜Kšœ œ˜Kš œœœ œœœ˜-š œœ œœ ˜+Kšœœœœ˜.Kšœ˜—š œœ œœ ˜+šœ œœ˜Kšœ*œ˜0—Kšœ˜—š œœ œœ ˜+Kšœœœœ˜.Kšœ˜—Kšœ œ˜&šœ œœ˜K˜šœ/˜6Kšœœ˜5K˜Kšœ˜—K˜—šœ˜K˜ š œœ œœ ˜+Kšœ œœœ˜4Kšœ˜—K˜—Kšœ œ˜'Kšœ˜K˜ K˜"šœ œœœ˜Kšœ œ˜(Kš œœ˜—Kšœ œ!˜2Kšœ ˜Kšœ#œ˜8šœ œ˜Kšœœ˜!Kšœ&˜&K˜Kšœ8˜:Kšœ˜K˜&K˜K˜—K˜Kšœ˜K˜K˜K˜ šœœœ ˜ Kšœ œœœ˜K–[]šœK˜MKšœ˜—šœ œ˜KšœE˜G—šœ œ˜KšœC˜E—K˜#K˜Kšœœœ˜5K˜K˜—šŸ œœ˜ Kšœœ˜Kšœœ˜ Kšœœœœ˜8Kšœœœ3˜EKšœœ*˜2˜K˜XK˜G—šœœ)œ˜EKšœ<˜@—K˜=šœ œœœ˜0K˜(Kšœ/˜/K˜—šœ˜Kšœ˜K˜K˜K˜K˜K˜K˜K˜ K˜K˜K˜K˜K˜ Kšœ˜—K˜ K˜K˜-K˜/K˜ K˜Cšœœ˜Kšœ œE˜TKšœ#˜&—J˜ K˜,Kšœœœ˜@K˜ K˜K˜—šŸ œœœ˜/K˜Kšœœ ˜Kšœœ˜ Kšœœœ˜@Kšœ œ œ ˜+šœ˜K˜K˜šœœœ˜K˜Kšœ˜—K˜—K˜K˜K˜—Kšœ œœ˜K˜K˜š Ÿœœœœœ˜Dšœ ˜Kšœœ-˜;Kšœœ˜Kšœ œ%˜4Kšœ œ˜ Kšœ˜—K˜K˜—šŸ œœœœ˜3Kšœœ˜ šœœ˜Kšœ˜K˜uK˜—K˜K˜—šŸ œœœ˜(Kšœœ2˜JK˜—šŸœœ˜+Kšœœ œœ ˜KKšœœ-˜EKšœ˜K˜—šŸ œœ)œ˜@Kšœœ˜ Kšœœ˜K˜$K˜8šœœ˜šœ ˜˜ Kšœ[˜[—˜Kšœ[˜[—Kšœ˜——K˜K˜—šŸœœ˜šœœ˜Kšœ"œ˜(šœ˜K˜Kšœ'œ œœ˜JKšœœ œ˜3K˜-Kšœ˜——šœ˜K˜ K˜eK˜—K˜—K˜K˜–+ -- [char: CHAR] RETURNS [IO.CharClass] -- šœ œ  *œ˜Dšœœ˜Kšœ˜K˜ Kšœ ˜—K˜K˜—š Ÿœœœœœ˜4šœœ˜Kš œœ œœœ˜3—K˜—šŸ œœ˜%K˜ Kšœ œœ˜šœ œœ˜šœ˜Kšœ$˜$Kšœ œ˜—Kšœ˜Kš œ˜—Kšœ ˜ Kš œœœœœ˜:Kšœ˜K˜%K˜,Kšœ˜š˜Kšœœ˜ —K˜—K˜šŸ œœœ˜7Kšœ<™