DIRECTORY BasicTime USING [Now], Buttons USING [ButtonProc, Create], Containers USING [ChildXBound], Convert USING [Error, IntFromRope], FS USING [ComponentPositions, PagesForBytes, ExpandName], Menus, PopUpSelection USING [Request], Process USING [DisableTimeout, Ticks, SecondsToTicks, SetTimeout], Rope, SendMailOps USING [CreateSendViewer], TEditDocument USING [TEditDocumentData], Tioga USING [Node], TiogaButtons USING [GetState, MarkViewerNotEdited, SetState], TiogaMenuOps USING [Store], TiogaOps USING [SearchDir, FindText], UserProfile USING [Boolean, Token], ViewerBLT USING[ChangeNumberOfLines], ViewerClasses USING [Viewer], ViewerOps, ViewerTools USING [GetContents, GetSelectedViewer, GetSelectionContents, SetSelection], Wallaby USING [QueryProc], WalnutFilter USING [MenuExtras], WalnutNewMail USING [CheckMailBoxes], WalnutOps USING [ActiveName, CreateMsgSet, DeletedName, DestroyMsgSet, dontCareDomainVersion, EmptyMsgSet, GetCategories, LogLength, MsgSet, MsgSetExists, MsgsInSetEnumeration, RemoveMsg, SizeOfDatabase, SizeOfMsgSet, WriteArchiveFile], WalnutInternal USING [AddMsgSetButton, DeleteMsgSetButton, DoWaitCall, DoAppendMsg, GetButton, GetSelectedMsgSets, HowToPrint, PrepareToEditMsgSetButtons, PrintMsgCmd, PrintMsgSet, PrintMsgSetCmd, PrintMsgSetTOCCmd, PrintSelCmd, QDisplayMsg, QDisplayMsgSet, ShowMsgSetButtons, WriteMsgSets], WalnutWindowPrivate, WalnutViewer USING [CreateMenuEntry, ImmediateButton, buttonEntryHeight, NextRightTextViewer], WalnutWindow USING [GetNewMail, Expunge, ReadArchiveFile, Report, ReportFormat, ReportRope, SelectMsgSetsFromMSNames]; WalnutWindowMenuImpl: CEDAR MONITOR IMPORTS BasicTime, Buttons, Containers, Convert, FS, Menus, PopUpSelection, Process, Rope, SendMailOps, UserProfile, TiogaButtons, TiogaMenuOps, TiogaOps, ViewerBLT, ViewerOps, ViewerTools, Wallaby, WalnutFilter, WalnutNewMail, WalnutOps, WalnutInternal, WalnutViewer, WalnutWindow EXPORTS WalnutInternal, WalnutWindow SHARES ViewerClasses = BEGIN OPEN WalnutInternal; ROPE: TYPE = Rope.ROPE; Viewer: TYPE = ViewerClasses.Viewer; buttonEntryHeight: INTEGER = WalnutViewer.buttonEntryHeight; noMsgSetsSelected: ROPE = "No seleted MsgSet(s)"; WhatToDoToMsgSets: TYPE = {nothing, empty, destroy}; OldMailOrPrint: TYPE = {oldMail, printing}; OldMailReader: TYPE = WalnutWindowPrivate.OldMailReader; OldMailReaderRec: TYPE = WalnutWindowPrivate.OldMailReaderRec; PrintingOptions: TYPE = WalnutWindowPrivate.PrintingOptions; PrintingOptionsRec: TYPE = WalnutWindowPrivate.PrintingOptionsRec; MsgAndHandle: TYPE = WalnutWindowPrivate.MsgAndHandle; MsgSetButton: TYPE = WalnutWindowPrivate.MsgSetButton; WalnutHandle: TYPE = WalnutWindowPrivate.WalnutHandle; WalnutHandleRec: PUBLIC TYPE = WalnutWindowPrivate.WalnutHandleRec; ChangeMenu: PUBLIC ENTRY PROC[wH: WalnutHandle, m: Menus.Menu, isBusy: BOOL] = { ENABLE UNWIND => NULL; InternalChangeMenu[wH, m, isBusy] }; InternalChangeMenu: INTERNAL PROC[wH: WalnutHandle, menu: Menus.Menu, isBusy: BOOL] = { oldCount, newCount: Menus.MenuLine; IF wH.walnut = NIL THEN RETURN; oldCount ¬ Menus.GetNumberOfLines[wH.walnut.menu]; newCount ¬ Menus.GetNumberOfLines[menu]; wH.walnut.menu ¬ menu; IF oldCount # newCount THEN ViewerBLT.ChangeNumberOfLines[wH.walnut, newCount]; ViewerOps.PaintViewer[wH.walnut, menu]; wH.walnut.newVersion ¬ isBusy; ViewerOps.PaintViewer[wH.walnut, caption]; }; GetUserResponse: PUBLIC ENTRY PROC[wH: WalnutHandle, m: Menus.Menu ¬ NIL, tryAutoConfirm: BOOL ¬ FALSE] RETURNS[BOOL] = { ENABLE UNWIND => NULL; autoConfirm: BOOL = UserProfile.Boolean["Walnut.AutoConfirmRetry", FALSE]; InternalChangeMenu[wH, IF m = NIL THEN wH.confirmMenu ELSE m, FALSE]; IF wH.walnut.iconic THEN ViewerOps.BlinkIcon[wH.walnut, 0] ELSE ViewerOps.BlinkIcon[wH.walnutTS]; IF ( NOT tryAutoConfirm ) OR ( NOT autoConfirm ) THEN { UNTIL wH.userHasResponded DO WAIT wH.responseSynch; ENDLOOP } ELSE { TRUSTED { Process.SetTimeout[@wH.responseSynch, autoTimeoutTicks] }; WAIT wH.responseSynch; TRUSTED { Process.DisableTimeout[@wH.responseSynch] }; IF NOT wH.userHasResponded THEN { wH.userConfirmed ¬ FALSE; WalnutWindow.ReportFormat[wH, "\n*** Auto Retry @ %g\n", [time[BasicTime.Now[]]]]; }; }; wH.userHasResponded ¬ FALSE; InternalChangeMenu[wH, workingMenu, FALSE]; RETURN[wH.userConfirmed]; }; autoTimeoutTicks: Process.Ticks ¬ Process.SecondsToTicks[60*10]; workingMenu: PUBLIC Menus.Menu ¬ Menus.CreateMenu[]; blankMenu: PUBLIC Menus.Menu ¬ Menus.CreateMenu[]; BuildWalnutMenus: PUBLIC PROC[wH: WalnutHandle] = { OPEN Menus; menu: Menu ¬ Menus.CreateMenu[]; AppendMenuEntry[menu, CreateEntry["Sender", NewSenderProc, wH]]; AppendMenuEntry[menu, CreateEntry["NewMail", NewMailProc, wH]]; AppendMenuEntry[menu, WalnutViewer.CreateMenuEntry[wH.walnutQueue, "CloseAll", CloseAllProc, wH]]; AppendMenuEntry[menu, CreateEntry["MsgSetOps", MsgSetOpsProc, wH]]; AppendMenuEntry[menu, CreateEntry["Find", FindProc, wH]]; AppendMenuEntry[menu, CreateEntry["Query", Wallaby.QueryProc, wH]]; FOR added: Menus.MenuEntry ¬ WalnutFilter.MenuExtras[$main], added.link UNTIL added = NIL DO AppendMenuEntry[menu, CreateEntry[added.name, added.proc, wH]]; ENDLOOP; AppendMenuEntry[menu, CreateEntry[name: "Expunge", proc: MenuExpunge, clientData: wH, guarded: TRUE]]; wH.mailDBMenu ¬ menu; menu ¬ Menus.CreateMenu[]; AppendMenuEntry[menu, CreateEntry["Sender", NewSenderProc, wH]]; AppendMenuEntry[menu, WalnutViewer.CreateMenuEntry[wH.walnutQueue, "CloseAll", CloseAllProc, wH]]; AppendMenuEntry[menu, CreateEntry["MsgSetOps", ROMsgSetOpsProc, wH]]; AppendMenuEntry[menu, CreateEntry["Find", FindProc, wH]]; AppendMenuEntry[menu, CreateEntry["Query", Wallaby.QueryProc, wH]]; FOR added: Menus.MenuEntry ¬ WalnutFilter.MenuExtras[$main], added.link UNTIL added = NIL DO AppendMenuEntry[menu, CreateEntry[added.name, added.proc, wH]]; ENDLOOP; wH.readOnlyDBMenu ¬ menu; menu ¬ Menus.CreateMenu[]; AppendMenuEntry[menu, CreateEntry["Sender", NewSenderProc, wH]]; AppendMenuEntry[menu, WalnutViewer.CreateMenuEntry[wH.walnutQueue, "CloseAll", CloseAllProc, wH]]; AppendMenuEntry[menu, CreateEntry["MsgSetOps", MsgSetOpsProc, wH]]; AppendMenuEntry[menu, CreateEntry["Query", Wallaby.QueryProc, wH]]; AppendMenuEntry[menu, CreateEntry["Find", FindProc, wH]]; FOR added: Menus.MenuEntry ¬ WalnutFilter.MenuExtras[$main], added.link UNTIL added = NIL DO AppendMenuEntry[menu, CreateEntry[added.name, added.proc, wH]]; ENDLOOP; AppendMenuEntry[menu, CreateEntry[name: "Expunge", proc: MenuExpunge, clientData: wH, guarded: TRUE]]; wH.nonMailDBMenu ¬ menu; menu ¬ Menus.CreateMenu[]; AppendMenuEntry[menu, CreateEntry["Sender", NewSenderProc]]; AppendMenuEntry[menu, CreateEntry["Confirm", WWConfirmProc, wH]]; AppendMenuEntry[menu, CreateEntry["Deny", WWDenyProc, wH]]; wH.confirmMenu ¬ menu; wH.forceQuitMenu ¬ Menus.CreateMenu[]; AppendMenuEntry[wH.forceQuitMenu, CreateEntry["Quit", WWConfirmProc, wH]]; menu ¬ Menus.CreateMenu[]; AppendMenuEntry[menu, CreateEntry["Quit", WWConfirmProc, wH]]; AppendMenuEntry[menu, CreateEntry["Retry", WWDenyProc, wH]]; wH.maybeQuitMenu ¬ menu; menu ¬ Menus.CreateMenu[]; AppendMenuEntry[menu, CreateEntry["Quit", WWDenyProc, wH]]; AppendMenuEntry[menu, CreateEntry["Scavenge", WWConfirmProc, wH]]; wH.scavMenu ¬ menu; }; NewSenderProc: Menus.MenuProc = { [] ¬ SendMailOps.CreateSendViewer[fromExec: FALSE]}; MsgSetOpsProc: Menus.MenuProc = { wH: WalnutHandle = NARROW[clientData]; isEditted: BOOL = TiogaButtons.GetState[wH.msgSetsTViewer] = editing; edRope: ROPE = IF isEditted THEN "Save msgSetButtons" ELSE "Edit msgSetButtons"; which: INT = PopUpSelection.Request[ header: "MessageSetOps", choice: LIST[ "Database Info", "Size of MsgSet(s)", "Create MsgSet", "Delete MsgSet(s)", "Make MsgSet(s) Empty", "R.O.T. MsgSet", edRope, "Append Msg to MsgSet(s)", "PressPrint", "Interpress2.0Print", "Interpress3.0Print", "Write MsgSet(s) To File", "Write MsgSet TOCs To File", "Archive MsgSet(s)", "Append MsgSet(s)", "ArchiveAndEmpty", "AppendAndEmpty", "ArchiveAndDelete", "AppendAndDelete", "DisplayMsgFromName", "OldMailReaderOptions", "Printing Options" ] ]; SELECT which FROM 1 => DBInfoProc[wH]; 2 => SizeOfMsgSetsProc[wH]; 3 => CreateMsgSetButtonProc[wH]; 4 => EmptyDelMsgSetsProc[wH: wH, del: TRUE]; 5 => EmptyDelMsgSetsProc[wH: wH, del: FALSE]; 6 => { rootMsgSet: ROPE = ViewerTools.GetSelectionContents[]; msgSetList: LIST OF MsgSetButton ¬ GetSelectedMsgSets[wH]; ChangeMenu[wH, workingMenu, TRUE]; [] ¬ DoRemoveOverThere[wH, rootMsgSet, msgSetList]; ChangeMenu[wH, wH.walnutMenu, FALSE]; }; 7 => IF isEditted THEN SaveMsgSetButtonsProc[wH: wH] ELSE PrepareToEditMsgSetButtons[wH]; 8 => AppendMsgProc[wH: wH]; 9 => PrintMsgSetsProc[wH: wH, howToPrint: press]; 10 => PrintMsgSetsProc[wH: wH, howToPrint: ip2]; 11 => PrintMsgSetsProc[wH: wH, howToPrint: ip3]; 12 => WriteMsgSetsProc[wH: wH, tocsOnly: FALSE]; 13 => WriteMsgSetsProc[wH: wH, tocsOnly: TRUE]; 14 => ArchiveOrAppend[wH: wH, append: FALSE, whatToDoToMsgSets: nothing]; 15 => ArchiveOrAppend[wH: wH, append: TRUE, whatToDoToMsgSets: nothing]; 16 => ArchiveOrAppend[wH: wH, append: FALSE, whatToDoToMsgSets: empty]; 17 => ArchiveOrAppend[wH: wH, append: TRUE, whatToDoToMsgSets: empty]; 18 => ArchiveOrAppend[wH: wH, append: FALSE, whatToDoToMsgSets: destroy]; 19 => ArchiveOrAppend[wH: wH, append: TRUE, whatToDoToMsgSets: destroy]; 20 => DoMsg[wH]; 21 => SetupOptions[wH, oldMail]; 22 => SetupOptions[wH, printing]; ENDCASE => NULL; }; DoMsg: PROC[wH: WalnutHandle] = { Dms: PROC = { msg: ROPE = ViewerTools.GetSelectionContents[]; v: Viewer = QDisplayMsg[wH, msg, NIL, FALSE]; IF v = NIL THEN { WalnutWindow.ReportFormat[wH, "Msg \"%g\" doesn't exist\n", [rope[msg]] ]; }; }; [] ¬ DoWaitCall[wH, Dms]; }; SaveMsgSetButtonsProc: PROC[wH: WalnutHandle] = { root: Tioga.Node = NARROW[wH.msgSetsTViewer.data, TEditDocument.TEditDocumentData].text; TiogaMenuOps.Store[wH.msgSetsTViewer, wH.localMsgSetButtonsFile]; TiogaButtons.MarkViewerNotEdited[root]; TiogaButtons.SetState[wH.msgSetsTViewer, buttoning]; }; ROMsgSetOpsProc: Menus.MenuProc = { wH: WalnutHandle = NARROW[clientData]; which: INT = PopUpSelection.Request[ header: "MessageSetOps", choice: LIST["DB-Info", "SizeOf", "PressPrint", "Interpress2.0Print", "Interpress3.0Print", "Archive", "Append", "DisplayMsgFromName", "Printing Options"] ]; SELECT which FROM 1 => DBInfoProc[wH]; 2 => SizeOfMsgSetsProc[wH]; 3 => PrintMsgSetsProc[wH: wH, howToPrint: press]; 4 => PrintMsgSetsProc[wH: wH, howToPrint: ip2]; 5 => PrintMsgSetsProc[wH: wH, howToPrint: ip3]; 6 => ArchiveOrAppend[wH: wH, append: FALSE, whatToDoToMsgSets: nothing]; 7 => ArchiveOrAppend[wH: wH, append: TRUE, whatToDoToMsgSets: nothing]; 8 => DoMsg[wH]; 9 => SetupOptions[wH, printing]; ENDCASE => NULL; }; MenuExpunge: Menus.MenuProc = { wH: WalnutHandle = NARROW[clientData]; { ENABLE UNWIND => ChangeMenu[wH, wH.walnutMenu, FALSE]; WalnutWindow.Report[wH, "You might try the DoWalnutCompact command instead (because expunge only clears the LoganBerry database instead the log)"]; ChangeMenu[wH, workingMenu, TRUE]; WalnutWindow.Expunge[wH]; }; }; NewMailProc: Menus.MenuProc = { wH: WalnutHandle = NARROW[clientData]; IF mouseButton = blue THEN WalnutNewMail.CheckMailBoxes[wH.opsH] ELSE WalnutWindow.GetNewMail[wH] }; CloseAllProc: Menus.MenuProc = { wH: WalnutHandle = NARROW[clientData]; FOR vL: LIST OF Viewer ¬ wH.msgViewerList, vL.rest UNTIL vL=NIL DO IF ViewerOps.FetchProp[vL.first, $Frozen] = NIL THEN ViewerOps.DestroyViewer[vL.first]; vL.first ¬ NIL; ENDLOOP; wH.msgViewerList ¬ NIL; FOR vL: LIST OF Viewer ¬ wH.msgSetViewerList, vL.rest UNTIL vL=NIL DO IF NOT vL.first.destroyed THEN ViewerOps.CloseViewer[vL.first]; ENDLOOP; FOR vL: LIST OF Viewer ¬ wH.wallabyViewerList, vL.rest UNTIL vL=NIL DO IF NOT vL.first.destroyed THEN ViewerOps.CloseViewer[vL.first]; ENDLOOP; IF wH.newMailRetrievalViewer # NIL THEN ViewerOps.CloseViewer[wH.newMailRetrievalViewer]; ViewerOps.CloseViewer[wH.walnut]; }; WWDenyProc: ENTRY Menus.MenuProc = { wH: WalnutHandle = NARROW[clientData]; BEGIN ENABLE UNWIND => NULL; wH.userConfirmed ¬ FALSE; wH.userHasResponded ¬ TRUE; BROADCAST wH.responseSynch; END; }; WWConfirmProc: ENTRY Menus.MenuProc = { wH: WalnutHandle = NARROW[clientData]; BEGIN ENABLE UNWIND => NULL; wH.userConfirmed ¬ TRUE; wH.userHasResponded ¬ TRUE; BROADCAST wH.responseSynch; END; }; CreateMsgSetButtonProc: PROC[wH: WalnutHandle] = { msName: ROPE ¬ ViewerTools.GetSelectionContents[]; Cmsb: PROC = { IF msName.Length[] = 0 THEN { WalnutWindow.Report[wH, "No MsgSet name specified"]; RETURN}; IF msName.Find[" "] >=0 THEN { WalnutWindow.Report[wH, " MsgSet names may not contain spaces"]; RETURN}; IF msName.Find["\n"] >=0 THEN { WalnutWindow.Report[wH, " MsgSet names may not contain CRs"]; RETURN}; IF WalnutOps.MsgSetExists[wH.opsH, msName, wH.msgSetsVersion].exists THEN { WalnutWindow.Report[wH, "MsgSet: ", msName, " already exists"]; [] ¬ WalnutWindow.SelectMsgSetsFromMSNames[wH, LIST[msName] ]; } ELSE { WalnutOps.CreateMsgSet[wH.opsH, msName, wH.msgSetsVersion]; [] ¬ AddMsgSetButton[wH, msName, TRUE]; wH.msgSetsVersion ¬ wH.msgSetsVersion + 1; WalnutWindow.Report[wH, "\nMsgSet: ", msName, " has been created"]; }; }; [] ¬ DoWaitCall[wH, Cmsb]; }; SizeOfMsgSetsProc: PROC[wH: WalnutHandle] = { msgSetList: LIST OF MsgSetButton ¬ GetSelectedMsgSets[wH]; Sms: PROC = { msgSet: ROPE; IF msgSetList = NIL THEN { WalnutWindow.Report[wH, noMsgSetsSelected]; RETURN}; FOR mL: LIST OF MsgSetButton ¬ msgSetList, mL.rest UNTIL mL=NIL DO num: INT ¬ WalnutOps.SizeOfMsgSet[wH.opsH, msgSet ¬ mL.first.msgSet.name].messages; WalnutWindow.ReportFormat[wH, " %g msgs in MsgSet %g\n", [integer[num]], [rope[msgSet]] ]; ENDLOOP; }; [] ¬ DoWaitCall[wH, Sms]; }; EmptyDelMsgSetsProc: PROC[wH: WalnutHandle, del: BOOL] = { msgSetList: LIST OF MsgSetButton ¬ GetSelectedMsgSets[wH]; Dms: PROC = { name: ROPE; someInDeleted: BOOL; anyDeleted: BOOL ¬ TRUE; whatToDo: ROPE = IF del THEN "deleted" ELSE "empty"; IF msgSetList = NIL THEN { WalnutWindow.Report[wH, noMsgSetsSelected, " to delete"]; RETURN}; ChangeMenu[wH, workingMenu, TRUE]; FOR mL: LIST OF MsgSetButton ¬ msgSetList, mL.rest UNTIL mL=NIL DO numIn: INT; name ¬ mL.first.msgSet.name; IF name.Equal[WalnutOps.DeletedName, FALSE] THEN { WalnutWindow.Report[wH, "Can't ", whatToDo, " the Deleted MsgSet"]; LOOP}; IF (numIn ¬ WalnutOps.SizeOfMsgSet[wH.opsH, name].messages) # 0 THEN { WalnutWindow.ReportFormat[wH, " Confirm deletion of %g messages in MsgSet: %g\n", [integer[numIn]], [rope[name]] ]; IF NOT GetUserResponse[wH] THEN { ChangeMenu[wH, wH.walnutMenu, FALSE]; RETURN } }; IF del THEN { DeleteMsgSetButton[wH, name]; someInDeleted ¬ WalnutOps.DestroyMsgSet[wH.opsH, mL.first.msgSet, wH.msgSetsVersion]; } ELSE someInDeleted ¬ WalnutOps.EmptyMsgSet[wH.opsH, mL.first.msgSet]; IF ~del AND mL.first.msViewer # NIL THEN [] ¬ QDisplayMsgSet[wH, mL.first, mL.first.msViewer, FALSE]; anyDeleted ¬ anyDeleted OR someInDeleted; IF ~name.Equal[WalnutOps.ActiveName, FALSE] THEN WalnutWindow.ReportFormat[wH, "\nMsgSet: %g has been %g\n", [rope[name]], [rope[IF del THEN "deleted" ELSE "emptied"]] ] ELSE WalnutWindow.Report[wH, "\nMsgs have been removed from Active"]; IF del THEN wH.msgSetsVersion ¬ wH.msgSetsVersion + 1; ENDLOOP; IF anyDeleted THEN RedisplayDeleted[wH]; ChangeMenu[wH, wH.walnutMenu, FALSE]; }; [] ¬ DoWaitCall[wH, Dms]; }; RemoveOverThereMsgSetsProc: PROC[wH: WalnutHandle] = { rootMsgSet: ROPE = ViewerTools.GetSelectionContents[]; msgSetList: LIST OF MsgSetButton ¬ GetSelectedMsgSets[wH]; ChangeMenu[wH, workingMenu, TRUE]; [] ¬ DoRemoveOverThere[wH, rootMsgSet, msgSetList]; ChangeMenu[wH, wH.walnutMenu, FALSE]; }; DoRemoveOverThere: PUBLIC PROC[wH: WalnutHandle, rootMsgSet: ROPE, msgSetList: LIST OF MsgSetButton] = { Rot: PROC = { IF ~WalnutOps.MsgSetExists[wH.opsH, rootMsgSet, WalnutOps.dontCareDomainVersion].exists THEN { WalnutWindow.ReportFormat[wH, "MsgSet \"%g\" doesn't exist so can't do r.o.t.", [rope[rootMsgSet]] ]; RETURN; }; IF rootMsgSet.Equal[WalnutOps.DeletedName, FALSE] THEN { WalnutWindow.Report[wH, "R.O.T. on Deleted is a noOp"]; RETURN }; WalnutWindow.Report[wH, "Starting R.O.T. of rootMsgSet ", rootMsgSet]; FOR msgs: LIST OF ROPE ¬ WalnutOps.MsgsInSetEnumeration[wH.opsH, rootMsgSet].mL, msgs.rest UNTIL msgs=NIL DO thisMsg: ROPE; catList: LIST OF ROPE ¬ WalnutOps.GetCategories[wH.opsH, thisMsg ¬ msgs.first]; FOR catList ¬ catList, catList.rest UNTIL catList = NIL DO thisMsgSet: ROPE; IF NOT Rope.Equal[thisMsgSet ¬ catList.first, rootMsgSet, FALSE] THEN { IF msgSetList = NIL THEN [] ¬ WalnutOps.RemoveMsg[wH.opsH, thisMsg, [thisMsgSet], wH.msgSetsVersion] ELSE FOR lmsb: LIST OF MsgSetButton ¬ msgSetList, lmsb.rest UNTIL lmsb=NIL DO IF Rope.Equal[lmsb.first.msgSet.name, thisMsgSet, FALSE] THEN [] ¬ WalnutOps.RemoveMsg[wH.opsH, thisMsg, [lmsb.first.msgSet.name], wH.msgSetsVersion] ENDLOOP; }; ENDLOOP; ENDLOOP; ShowMsgSetButtons[wH]; WalnutWindow.Report[wH, " Done with R. O. T."]; }; IF rootMsgSet.Length[] = 0 THEN { WalnutWindow.Report[wH, "No root message set for r.o.t."]; RETURN }; [] ¬ DoWaitCall[wH, Rot]; }; AppendMsgProc: PROC[wH: WalnutHandle] = { msgSetList: LIST OF MsgSetButton ¬ GetSelectedMsgSets[wH]; curSel: ROPE = ViewerTools.GetSelectionContents[]; curV: Viewer = ViewerTools.GetSelectedViewer[]; DoAppendMsg[wH, curSel, curV, msgSetList]; }; PrintMsgSetsProc: PROC[wH: WalnutHandle, howToPrint: HowToPrint] = { msgSetList: LIST OF MsgSetButton ¬ GetSelectedMsgSets[wH]; Pms: PROC = { IF msgSetList = NIL THEN { WalnutWindow.Report[wH, noMsgSetsSelected, " to print"]; RETURN }; ChangeMenu[wH, workingMenu, TRUE]; FOR mL: LIST OF MsgSetButton ¬ msgSetList, mL.rest UNTIL mL=NIL DO IF ~PrintMsgSet[wH, mL.first.msgSet.name, howToPrint] THEN EXIT; ENDLOOP; ChangeMenu[wH, wH.walnutMenu, FALSE]; }; [] ¬ DoWaitCall[wH, Pms]; }; WriteMsgSetsProc: PROC[wH: WalnutHandle, tocsOnly: BOOL] = { Pms: PROC = { msgSetList: LIST OF MsgSetButton ¬ GetSelectedMsgSets[wH]; fileName: ROPE ¬ ViewerTools.GetSelectionContents[]; fullName: ROPE; cp: FS.ComponentPositions; IF fileName.Length[] = 0 THEN { WalnutWindow.Report[wH, "No fileName selected"]; RETURN }; [fullName, cp, ] ¬ FS.ExpandName[fileName, NIL]; IF cp.ext.length = 0 THEN fullName ¬ fullName.Concat[".tioga"]; IF msgSetList = NIL THEN { WalnutWindow.Report[wH, noMsgSetsSelected, " to write to file"]; RETURN }; ChangeMenu[wH, workingMenu, TRUE]; WriteMsgSets[wH, msgSetList, tocsOnly, fullName]; ChangeMenu[wH, wH.walnutMenu, FALSE]; }; [] ¬ DoWaitCall[wH, Pms]; }; ArchiveOrAppend: PROC[wH: WalnutHandle, append: BOOL, whatToDoToMsgSets: WhatToDoToMsgSets ] = { fileName: ROPE ¬ ViewerTools.GetSelectionContents[]; msgSetList: LIST OF MsgSetButton ¬ GetSelectedMsgSets[wH]; AorA: PROC = { ENABLE UNWIND => ChangeMenu[wH, wH.walnutMenu, FALSE]; anyInDeleted: BOOL ¬ FALSE; msList: LIST OF WalnutOps.MsgSet; ChangeMenu[wH, workingMenu, TRUE]; FOR mL: LIST OF MsgSetButton ¬ msgSetList, mL.rest UNTIL mL=NIL DO msList ¬ CONS[mL.first.msgSet, msList]; ENDLOOP; IF ~DoArchive[wH, fileName, msList, append] THEN { ChangeMenu[wH, wH.walnutMenu, FALSE]; RETURN }; IF whatToDoToMsgSets = nothing THEN { ChangeMenu[wH, wH.walnutMenu, FALSE]; RETURN }; WalnutWindow.ReportRope[wH, "\t", IF whatToDoToMsgSets = destroy THEN "Deleting" ELSE "Emptying", " archived msgSet(s):"]; FOR mL: LIST OF MsgSetButton ¬ msgSetList, mL.rest UNTIL mL = NIL DO someInDeleted: BOOL ¬ FALSE; name: ROPE = mL.first.msgSet.name; IF ~name.Equal[WalnutOps.DeletedName, FALSE] THEN { IF whatToDoToMsgSets = destroy THEN DeleteMsgSetButton[wH, name]; WalnutWindow.ReportRope[wH, " ", name]; IF whatToDoToMsgSets = destroy THEN someInDeleted ¬ WalnutOps.DestroyMsgSet[wH.opsH, mL.first.msgSet, wH.msgSetsVersion ] ELSE someInDeleted ¬ WalnutOps.EmptyMsgSet[wH.opsH, mL.first.msgSet ]; IF whatToDoToMsgSets # destroy AND mL.first.msViewer # NIL THEN [] ¬ QDisplayMsgSet[wH, mL.first, mL.first.msViewer, FALSE]; IF whatToDoToMsgSets = destroy THEN wH.msgSetsVersion ¬ wH.msgSetsVersion + 1; anyInDeleted ¬ anyInDeleted OR someInDeleted; }; ENDLOOP; WalnutWindow.ReportRope[wH, "... Done\n"]; IF anyInDeleted THEN RedisplayDeleted[wH]; ChangeMenu[wH, wH.walnutMenu, FALSE]; }; [] ¬ DoWaitCall[wH, AorA]; }; DoArchive: PUBLIC PROC[wH: WalnutHandle, fileName: ROPE, msList: LIST OF WalnutOps.MsgSet, append: BOOL] RETURNS[ok: BOOL] = { fullName: ROPE; num: INT ¬ 0; ok ¬ FALSE; IF msList = NIL THEN { WalnutWindow.Report[wH, noMsgSetsSelected, " to archive"]; RETURN}; IF fileName.IsEmpty[] THEN { IF msList.rest = NIL THEN fileName ¬ msList.first.name -- if only one message set is selected, then create a filename ELSE { WalnutWindow.Report[wH, "No Archive file specified for selected message sets"]; RETURN }; }; BEGIN cp: FS.ComponentPositions; wDir: ROPE ¬ UserProfile.Token["Walnut.DefaultArchiveDir"]; [fullName, cp, ] ¬ FS.ExpandName[fileName, wDir]; IF cp.ext.length = 0 THEN fullName ¬ fullName.Concat[".ArchiveLog"]; END; IF Rope.Equal[fullName, wH.opsH.rootName, FALSE] THEN { WalnutWindow.Report[wH, "Can't archive on log file"]; RETURN}; IF append THEN WalnutWindow.Report[wH, "Appending msgs to the file: ", fileName]; WalnutWindow.ReportRope[wH, "Archiving the MsgSet(s): "]; FOR mL: LIST OF WalnutOps.MsgSet ¬ msList, mL.rest UNTIL mL = NIL DO msName: ROPE = mL.first.name; this: INT ¬ WalnutOps.SizeOfMsgSet[wH.opsH, msName].messages; WalnutWindow.ReportFormat[wH, "%g (%g messages) ", [rope[msName]], [integer[this]]]; num ¬ num + this; ok ¬ WalnutOps.WriteArchiveFile[wH.opsH, fullName, LIST[mL.first], append]; IF ~ok THEN EXIT; append ¬ TRUE; -- always true after the first write ENDLOOP; IF ~ok THEN RETURN[FALSE]; WalnutWindow.ReportFormat[wH, "\n %g messages archived on file: %g\n", [integer[num]], [rope[fullName]] ]; RETURN[TRUE] }; DBInfoProc: PROC[wH: WalnutHandle] = { Dbi: PROC = { len: INT ¬ WalnutOps.LogLength[wH.opsH]; numIn: INT ¬ WalnutOps.SizeOfMsgSet[wH.opsH, WalnutOps.DeletedName].messages; messages, msgSets: INT; [messages, msgSets] ¬ WalnutOps.SizeOfDatabase[wH.opsH]; WalnutWindow.ReportFormat[wH, " The log file is %g bytes (%g pages) long\n", [integer[len]], [integer[FS.PagesForBytes[len]]] ]; WalnutWindow.ReportFormat[wH, " There are %g deleted msgs, (%g total msgs), & %g msgSets\n", [integer[numIn]], [integer[messages]], [integer[msgSets]] ]; }; [] ¬ DoWaitCall[wH, Dbi]; }; SetupOptions: PROC[wH: WalnutHandle, which: OldMailOrPrint] = { Sop: PROC = { oneHeight: INTEGER = buttonEntryHeight + 1 + 1; move: INTEGER = (IF which = oldMail THEN 2*oneHeight ELSE oneHeight) + 1; oldY: INTEGER = wH.walnutRulerAfter.wy + wH.walnutRulerAfter.wh; IF which = oldMail AND wH.oldMailReader # NIL THEN RETURN; IF which = printing AND wH.printingOptions # NIL THEN RETURN; IF (which = oldMail AND wH.printingOptions # NIL) OR (which = printing AND wH.oldMailReader # NIL) THEN { WalnutWindow.Report[wH, "Can't have both OldMailReader & Printing Options"]; RETURN; }; wH.walnut.inhibitDestroy ¬ TRUE; ViewerOps.MoveViewer[wH.walnutTS, wH.walnutTS.wx, wH.walnutTS.wy+move, wH.walnutTS.ww, wH.walnutTS.wh, FALSE]; IF which = oldMail THEN { omr: OldMailReader ¬ NEW[OldMailReaderRec]; omr.container ¬ ViewerOps.CreateViewer[ flavor: $Container, info: [parent: wH.walnut, wy: oldY, ww: 1000, wh: move, scrollable: FALSE]]; Containers.ChildXBound[wH.walnut, omr.container]; omr.doIt ¬ Buttons.Create[ proc: OldMailReaderProc, clientData: wH, paint: FALSE, info: [name: "DoIt", parent: omr.container, wx: 4, wy: 1, border: TRUE] ]; omr.fileLabel ¬ WalnutViewer.ImmediateButton[name: "file:", proc: FileLabelProc, data: wH, sib: omr.doIt, paint: FALSE]; omr.fileText ¬ WalnutViewer.NextRightTextViewer[omr.fileLabel, 700]; Containers.ChildXBound[omr.container, omr.fileText]; omr.close ¬ WalnutViewer.ImmediateButton[name: "Close", proc: CloseOmrProc, sib: omr.fileText, data: wH, border: TRUE, newLine: TRUE, paint: FALSE]; omr.msgSetLabel ¬ WalnutViewer.ImmediateButton[name: "msgSet:", proc: MsgSetLabelProc, data: wH, sib: omr.close, paint: FALSE]; omr.msgSetText ¬ WalnutViewer.NextRightTextViewer[omr.msgSetLabel, 700]; Containers.ChildXBound[omr.container, omr.msgSetText]; wH.oldMailReader ¬ omr; } ELSE { por: PrintingOptions ¬ NEW[PrintingOptionsRec]; por.container ¬ ViewerOps.CreateViewer[ flavor: $Container, info: [parent: wH.walnut, wy: oldY, ww: 1000, wh: move, scrollable: FALSE]]; Containers.ChildXBound[wH.walnut, por.container]; por.options ¬ Buttons.Create[ proc: PrintingOptionsProc, clientData: wH, paint: FALSE, info: [name: "Options", parent: por.container, wx: 4, wy: 1, border: TRUE] ]; por.copiesLabel ¬ WalnutViewer.ImmediateButton[name: "copies:", proc: CopiesLabelProc, data: wH, sib: por.options, paint: FALSE]; por.copiesText ¬ WalnutViewer.NextRightTextViewer[por.copiesLabel, 50]; por.serverLabel ¬ WalnutViewer.ImmediateButton[name: "server:", proc: ServerLabelProc, data: wH, sib: por.copiesText, paint: FALSE]; por.serverText ¬ WalnutViewer.NextRightTextViewer[por.serverLabel, 500]; Containers.ChildXBound[por.container, por.serverText]; wH.printingOptions ¬ por; }; wH.walnut.inhibitDestroy ¬ FALSE; ViewerOps.PaintViewer[wH.walnut, client]; }; [] ¬ DoWaitCall[wH, Sop]; }; OldMailReaderProc: Buttons.ButtonProc = { wH: WalnutHandle = NARROW[clientData]; msgSet: ROPE = ViewerTools.GetContents[wH.oldMailReader.msgSetText]; fileName: ROPE = ViewerTools.GetContents[wH.oldMailReader.fileText]; WalnutWindow.ReadArchiveFile[wH, fileName, msgSet]; }; MsgSetLabelProc: Buttons.ButtonProc = { wH: WalnutHandle = NARROW[clientData]; ViewerTools.SetSelection[wH.oldMailReader.msgSetText, NIL]; }; FileLabelProc: Buttons.ButtonProc = { wH: WalnutHandle = NARROW[clientData]; ViewerTools.SetSelection[wH.oldMailReader.fileText, NIL]; }; CopiesLabelProc: Buttons.ButtonProc = { wH: WalnutHandle = NARROW[clientData]; ViewerTools.SetSelection[wH.printingOptions.copiesText, NIL]; }; ServerLabelProc: Buttons.ButtonProc = { wH: WalnutHandle = NARROW[clientData]; ViewerTools.SetSelection[wH.printingOptions.serverText, NIL]; }; PrintingOptionsProc: Buttons.ButtonProc = { wH: WalnutHandle = NARROW[clientData]; which, how: INT; howToPrint: HowToPrint ¬ press; server, numRope: ROPE; copies: INT; DoPrint: PROC = { SELECT which FROM 1 => { v: Viewer = ViewerTools.GetSelectedViewer[]; maH: MsgAndHandle = NARROW[ViewerOps.FetchProp[v, $WalnutMsgName]]; IF maH = NIL THEN { WalnutWindow.Report[wH, "Viewer is not a Walnut Msg displayer"]; RETURN; }; IF maH.wH # wH THEN { WalnutWindow.Report[wH, "Msg is from a different database"]; RETURN }; PrintMsgCmd[wH, maH.msg, server, howToPrint, copies]; }; 2 => FOR msb: MsgSetButton ¬ wH.selectedMsgSetButtons, msb.selected UNTIL msb = NIL DO PrintSelCmd[wH, msb.msgSet.name, server, howToPrint, copies]; ENDLOOP; 3 => FOR msb: MsgSetButton ¬ wH.selectedMsgSetButtons, msb.selected UNTIL msb = NIL DO PrintMsgSetCmd[wH, msb.msgSet.name, server, howToPrint, copies]; ENDLOOP; 4 => FOR msb: MsgSetButton ¬ wH.selectedMsgSetButtons, msb.selected UNTIL msb = NIL DO PrintMsgSetTOCCmd[wH, msb.msgSet.name, server, howToPrint, copies]; ENDLOOP; 5 => { prev: PrintingOptions = wH.printingOptions; wH.printingOptions ¬ NIL; ViewerOps.DestroyViewer[prev.container, FALSE]; ViewerOps.MoveViewer[wH.walnutTS, wH.walnutTS.wx, wH.walnutRulerAfter.wy+wH.walnutRulerAfter.wh+1, wH.walnutTS.ww, wH.walnutTS.wh, TRUE]; }; ENDCASE; }; which ¬ PopUpSelection.Request[ header: "WhatToPrint", choice: LIST["Msg", "SelectedMsgInMsgSet(s)", "MsgSet(s)", "MsgSetTOC(s)", "Close"] ]; IF which = 0 THEN RETURN; IF which # 5 THEN { how ¬ PopUpSelection.Request[ header: "HowToPrint", choice: LIST[ "PressPrint", "Interpress2.0Print", "Interpress3.0Print" ] ]; IF how = 0 THEN RETURN; server ¬ ViewerTools.GetContents[wH.printingOptions.serverText]; numRope ¬ ViewerTools.GetContents[wH.printingOptions.copiesText]; IF numRope # NIL THEN copies ¬ Convert.IntFromRope[numRope ! Convert.Error => { copies ¬ 1; CONTINUE } ] ELSE copies ¬ 1; howToPrint ¬ SELECT how FROM 1 => press, 2 => ip2, 3 => ip3, ENDCASE => ip3; }; [] ¬ DoWaitCall[wH, DoPrint]; }; CloseOmrProc: Buttons.ButtonProc = { wH: WalnutHandle = NARROW[clientData]; prev: OldMailReader = wH.oldMailReader; wH.oldMailReader ¬ NIL; ViewerOps.DestroyViewer[prev.container, FALSE]; ViewerOps.MoveViewer[wH.walnutTS, wH.walnutTS.wx, wH.walnutRulerAfter.wy+wH.walnutRulerAfter.wh+1, wH.walnutTS.ww, wH.walnutTS.wh, TRUE]; }; RedisplayDeleted: PROC[wH: WalnutHandle] = { msb: MsgSetButton ¬ GetButton[wH, WalnutOps.DeletedName]; IF msb.msViewer = NIL THEN RETURN; [] ¬ QDisplayMsgSet[wH, msb, msb.msViewer, FALSE]; }; FindProc: Menus.MenuProc = { wH: WalnutHandle = NARROW[clientData]; direction: TiogaOps.SearchDir = SELECT mouseButton FROM red => forwards, yellow => anywhere, blue => backwards, ENDCASE => forwards; IF ~TiogaOps.FindText[ viewer: wH.msgSetsTViewer, whichDir: direction, which: feedback, case: ~shift] THEN ViewerOps.BlinkIcon[wH.msgSetsTViewer]; }; Menus.AppendMenuEntry[workingMenu, Menus.CreateEntry["Sender", NewSenderProc]]; END. œ WalnutWindowMenuImpl.mesa Copyright Σ 1985, 1987, 1988, 1989, 1992 by Xerox Corporation. All rights reserved. Willie-Sue, August 8, 1989 3:23:00 pm PDT Jack Kent, April 7, 1987 8:17:28 am PST Swinehart, February 26, 1991 5:01 pm PST Doug Terry, October 2, 1992 10:28 am PDT Willie-s, April 27, 1992 2:58 pm PDT (Christian Jacobi, August 23, 1993 12:03 pm PDT) Contents: Menu control for the Top level Viewer for Walnut created March, 1985 by Willie-Sue Walnut Viewers types and global data * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * menu for personal mail database menu for read only database menu for nonMail writeable database Create a new blank form in a viewer for user to send msg with. IF wH.msgSetButtonsFile = NIL THEN RETURN; [] _ FS.Copy[from: wH.localMsgSetButtonsFile, to: wH.msgSetButtonsFile]; -- to alpine They are one and the same in PCedar! DCS, February 26, 1991 4:46:07 pm PST and also close the wallaby viewers * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * "immediate" buttons that gather some parameters and then queue the real proc to call crank out NextMsgInMsgSet until we're at end of msgset for every message...get its categories if msgSetList = nil then for every other message set that it belongs to...remove it from that message set, else remove msg from only those msgSets in msgSetList in this context, we know deleted is false... update any displayed msgSets make sure didn't specify same name as log file move the typescript down enough space * * * * * * * * * * other menus - done only once * * * * * * * * * * ΚΟ–(cedarcode) style•NewlineDelimiter ™codešΟn™Kšœ ΟeœI™TK™)KšΟy'™'K™(K™(K™$K™0—K˜Kšœ:™:K˜Kšœ!™!K˜šΟk ˜ Kšœ  œ˜Kšœ œ˜#Kšœ  œ˜Kšœ œ˜#Kš œ œ1˜9K˜Kšœ œ ˜Kšœ œ5˜BK˜Kšœ  œ˜%Kšœ œ˜(Kšœ œ˜Kšœ  œ+˜=Kšœ  œ ˜Kšœ  œ˜%Kšœ  œ˜#Kšœ  œ˜%Kšœ œ ˜K˜ Kšœ  œF˜WKšœ œ˜Kšœ  œ˜ Kšœ œ˜%Kšœ  œέ˜μKšœ œ˜£Kšœ˜Kšœ  œL˜^Kšœ  œd˜v˜K˜——šœ œ ˜#š ˜Kšœ) œB˜mK˜&Kšœ,˜,K˜'Kšœ˜Kšœ˜—Kš œ˜%Kš œ˜K˜—Kš œ œ˜K˜Kšœ$™$˜Kš œ œ œ˜Kšœ œ˜$Kšœ œ"˜Kšœ œ'˜K˜<—˜K˜—˜K˜;K˜B—˜K˜———˜š œA œ˜VKšœ?™?K˜—š œ˜!Kšœ œ ˜&Kšœ  œ6˜EKš œ œ œ  œ œ˜Pšœ œ˜ šœ˜Kšœ˜šœ œ˜ Kšœ%˜%KšœM˜MKšœ"˜"KšœT˜TKšœE˜EKšœK˜KK˜@—Kšœ˜——š œ ˜Kšœ˜Kšœ˜Kšœ!˜!Kšœ' œ˜-Kšœ' œ˜.šœ˜Kšœ  œ&˜6Kšœ  œ œ'˜:Kšœ œ˜"K˜3Kšœ œ˜%K˜—Kšœ œ  œ œ ˜ZKšœ˜Kšœ2˜2Kšœ0˜0Kšœ0˜0Kšœ) œ˜0Kšœ) œ˜/Kšœ& œ˜IKšœ& œ˜HKšœ& œ˜GKšœ& œ˜FKšœ& œ˜IKšœ& œ˜HKšœ˜K˜ K˜!Kš œ œ˜—Kšœ˜K˜—šœ œ˜!šœ œ˜ Kšœ œ&˜/Kšœ! œ œ˜-š œ œ œ˜KšœJ˜JK˜—K˜—K˜Kšœ˜K˜—šœ œ˜1Kšœ œ?˜XKšœA˜AKšœ'˜'K˜4Kš œ œ œ œ™*Kšœ œBΟc ™UK™KK˜—K˜šœ˜#Kšœ œ ˜&šœ œ˜ šœ˜Kšœ˜šœ œ#˜/Kšœ@˜@Kšœ)˜)—Kšœ˜——š œ ˜Kšœ˜Kšœ˜Kšœ1˜1Kšœ/˜/Kšœ/˜/Kšœ% œ˜HKšœ% œ˜GKšœ˜K˜ Kš œ œ˜—Kšœ˜K˜—š œ˜Kšœ œ ˜&šœ œ œ" œ˜8K˜“Kšœ œ˜"Kšœ˜K˜—K˜—K˜š œ˜Kšœ œ ˜&Kš œ œ' œ˜aK˜K˜—š œ˜ Kšœ œ ˜&š  œ œ œ$ œ œ ˜BKš œ* œ œ#˜WKšœ  œ˜Kš œ˜—Kšœ œ˜š  œ œ œ' œ œ ˜EKš œ œ œ" œ˜H—K™"š  œ œ œ( œ œ ˜FKš œ œ œ" œ˜H—Kš œ œ œ2˜YK˜!Kšœ˜—K˜š œ œ˜$Kšœ œ ˜&š œ œ œ œ˜Kšœ œ˜Kšœ œ˜Kš  œ˜Kš œ˜—K˜—K˜š œ œ˜'Kšœ œ ˜&š œ œ œ œ˜Kšœ œ˜Kšœ œ˜Kš  œ˜Kš œ˜—K˜——K˜Kšœ<™K˜—š œ˜Kšœ;˜;Kšœ! œ˜'K˜*KšœC˜CKšœ˜——K˜—K˜K˜——˜šœ œ˜-Kšœ  œ œ'˜:šœ œ˜ Kšœ œ˜ Kš œ œ œ/ œ˜Oš  œ œ œ$ œ œ ˜BKšœ œK˜Sšœ8˜8Kšœ"˜"—Kš œ˜—K˜—K˜K˜——˜šœ œ œ˜:Kšœ  œ œ'˜:šœ œ˜ Kšœ œ˜ Kšœ œ˜Kšœ  œ œ˜Kš œ  œ œ œ  œ ˜4š œ œ ˜Kšœ< œ˜D—Kšœ œ˜"K˜š  œ œ œ$ œ œ ˜BKšœ œ˜ K˜š œ# œ ˜0KšœF œ˜L—K˜š œ> œ˜FšœQ˜QKšœ!˜!—š œ œ ˜Kšœ  œ œ˜0—K˜—K˜š œ œ˜ Kšœ˜˜0Kšœ$˜$—K˜Kš œA˜E—š œ œ œ ˜(Kšœ5 œ˜<—Kšœ œ˜)š œ# œ ˜0šœ;˜;Kšœ œ œ  œ˜=—Kš œA˜E—Kš œ œ+˜6—Kš œ˜K˜Kš œ  œ˜(Kšœ œ˜%Kšœ˜—K˜K˜K˜—šœ œ˜6Kšœ  œ&˜6Kšœ  œ œ'˜:Kšœ œ˜"K˜3Kšœ œ˜%Kšœ˜K˜—š œ œ œ œ œ œ˜hšœ œ˜ š œV œ˜^šœ˜KšœG˜G—Kš œ˜K˜—š œ) œ ˜6Kšœ: œ˜DK˜—Kš‘6™6KšœF˜Fš  œ œ œ œE œ œ ˜lKšœ  œ˜Kšœ  œ œ œ:˜OK™&K™Kšœ#ΟbœX’œ‘ ™ š œ! œ  œ ˜:Kšœ  œ˜š œ œ4 œ œ˜Gš œ œ ˜K™,K˜Kš ˜š  œ œ œ& œ œ ˜Hš œ0 œ ˜=K˜W—Kš œ˜———K˜—Kš œ˜—Kš œ˜—˜K™—Kšœ/˜/K˜—š œ ˜Kšœ= œ˜F—K˜K˜K˜—š œ œ˜)Kšœ  œ œ'˜:Kšœ œ&˜2Kšœ/˜/Kšœ*˜*K˜K˜—šœ œ.˜DKšœ  œ œ'˜:šœ œ˜ š œ œ ˜Kšœ; œ˜D—šœ œ˜"K˜—š  œ œ œ$ œ œ ˜BKš œ4 œ œ˜@Kš œ˜—Kšœ œ˜%Kšœ˜—K˜K˜—K˜šœ œ œ˜<šœ œ˜ Kšœ  œ œ'˜:Kšœ  œ&˜4Kšœ  œ˜Kšœ œ˜š œ œ˜Kšœ0˜0Kš ˜K˜—Kšœ œ œ˜0Kš œ œ&˜?š œ œ ˜KšœC œ˜L—Kšœ œ˜"Kšœ1˜1Kšœ œ˜%Kšœ˜—K˜K˜—K˜K˜šœ œ œ,˜`Kšœ  œ&˜4Kšœ  œ œ'˜:šœ œ˜Kš œ œ" œ˜6K˜Kšœ œ œ˜Kšœ œ œ˜!K˜Kšœ œ˜"š  œ œ œ$ œ œ ˜BKšœ  œ œ˜0—K˜š œ* ˜0Kšœ  œ œ˜1—K˜š œ ˜#Kšœ  œ œ˜1—K˜šœ" œ œ  œ ˜aKšœ˜—š  œ œ œ$ œ œ ˜DKšœ œ œ˜Kšœ œ˜"š œ$ œ œ˜3Kš œ œ˜AKšœ(˜(š œ ˜#˜0Kšœ$˜$—Kš œB˜F—K˜š œ œ œ ˜?Kšœ5 œ˜=—Kš œ œ+˜NKšœ œ˜-K˜—Kš œ˜—K˜*Kš œ œ˜*Kšœ œ˜%Kšœ˜—K˜K˜—K˜š œ œ œ œ  œ œ œ˜hKš œ œ˜Kšœ  œ˜Kšœ œ˜ Kšœ œ˜ š œ  œ ˜Kšœ= œ˜E—š œ œ˜Kš œ œ‘>˜uš œ˜KšœO˜OKš ˜Kšœ˜—Kšœ˜—Kšœ.™.š ˜Kšœ œ˜Kšœ œ1˜;Kšœ œ˜1Kš œ œ+˜DKš œ˜—K˜š œ( œ ˜5Kšœ8 œ˜@—K˜Kš œ œC˜QK˜9K˜š  œ œ œ$ œ œ ˜DKšœ œ˜Kšœ œ4˜=KšœT˜TK˜Kšœ3 œ˜KKš œ œ œ˜Kšœ  œ‘$˜4Kš œ˜—K˜Kš œ œ œ œ˜Kšœj˜jKš œ œ˜ K˜—K˜š œ œ˜&šœ œ˜ Kšœ œ ˜(Kšœ œC˜MKšœ œ˜K˜8K˜šœN˜NKšœ œ˜3—šœ˜šœ@˜@Kšœ<˜<——K˜—K˜K˜K˜—š œ œ-˜?šœ œ˜ Kšœ  œ˜/Kš œ œ œ œ  œ˜IKšœ œ3˜@Kš  œ œ œ œ œ˜:Kš  œ œ œ œ œ˜=š œ œ œ ˜4šœ œ œ œ˜4K˜LKš œ˜K˜——Kšœ œ˜ K™%Kšœg œ˜nš œ œ˜Kšœ œ˜+˜'K˜KšœD œ˜L—Kšœ1˜1˜Kšœ0 œ˜6KšœB œ˜J—Kšœq œ˜xK˜DKšœ4˜4Kšœq œ  œ  œ˜”Kšœx œ˜K˜HKšœ6˜6K˜K˜K˜Kš œ˜Kšœ œ˜/˜'K˜KšœD œ˜L—Kšœ1˜1˜Kšœ2 œ˜8KšœE œ˜M—Kšœz œ˜K˜GKšœ} œ˜„K˜HKšœ6˜6K˜K˜—Kšœ œ˜!K˜)K˜—K˜K˜K˜—šœ˜)Kšœ œ ˜&Kšœ œ8˜DKšœ  œ6˜DKšœ3˜3K˜K˜—šœ˜'Kšœ œ ˜&Kšœ6 œ˜;K˜K˜—š œ˜%Kšœ œ ˜&Kšœ4 œ˜9K˜K˜—šœ˜'Kšœ œ ˜&Kšœ8 œ˜=K˜K˜—šœ˜'Kšœ œ ˜&Kšœ8 œ˜=K˜K˜—šœ˜+Kšœ œ ˜&Kšœ  œ˜K˜Kšœ œ˜Kšœ œ˜ šœ œ˜š œ ˜˜Kšœ,˜,Kšœ œ)˜Cš œ œ œ˜K˜@Kš œ˜K˜—š œ  œ˜K˜