DIRECTORY Basics USING [Comparison], Buttons USING [Button, ButtonProc, Create], Containers USING [ChildXBound, ChildYBound, Container, Create], Labels USING [Create, Label, Set], Menus USING [CreateEntry, CreateMenu, InsertMenuEntry, Menu, MenuProc], Rules USING [Create, Rule], ViewerIO USING [CreateViewerStreams], ViewerOps USING [CreateViewer, PaintViewer, SetMenu, SetOpenHeight], ViewerClasses USING [Viewer], ViewerTools USING [MakeNewTextViewer, GetContents, SetContents, SetSelection], FS USING [StreamOpen ], GVNames USING [CheckStamp, Expand, ExpandInfo, GetFriends, GetMembers, MemberInfo, RListHandle, StampInfo], Histogram, IO USING [card, Close, Flush, PutF, PutFR, PutRope, rope, STREAM, time], RedBlackTree USING [Create, Delete, Insert, Key, Lookup, LookupNextLarger, LookupSmallest, Table, UserData], Rope USING [Cat, Compare, Equal, Fetch, Length, ROPE, SkipOver, SkipTo, Substr]; GVInvert: CEDAR MONITOR IMPORTS Buttons, Containers, Labels, Menus, Rules, ViewerIO, ViewerOps, ViewerTools, FS, GVNames, Histogram, IO, RedBlackTree, Rope = { ROPE: TYPE = Rope.ROPE; Invert: PROC = { ParseFileNamePattern: PROC = { f: ROPE = ViewerTools.GetContents[fileName]; starPosition: CARDINAL = Rope.SkipTo[f, 0, "*"]; IF starPosition = Rope.Length[f] OR Rope.SkipTo[f, starPosition+1, "*"] # Rope.Length[f] THEN { outStr.PutRope["\nFile name patterns should have exactly one *."]; ERROR inverterStopped }; fileNamePrefix _ Rope.Substr[f, 0, starPosition]; fileNameSuffix _ Rope.Substr[f, starPosition+1, Rope.Length[f] - starPosition+1]; }; --ParseFileNamePattern-- GetRegistryGroups: PROC [r: ROPE] = { c: CARDINAL; target: ROPE _ Rope.Cat["groups.", r]; rLH: GVNames.RListHandle; Labels.Set[currentName, target]; [rLH, c, ] _ MyExpand[target, FALSE]; registryList _ CONS[rLH, registryList]; totalGrp _ totalGrp + c; UpdateCounter[totalGroups, totalGrp]; }; --GetRegistryGroups-- CreateOutputFileForRegistry: PROC [reg: ROPE] = { data: RedBlackTree.UserData; acceptAll: BOOL = Rope.Equal["other", reg, FALSE]; outStr.PutF["\nCreating output file for %g.", [rope[reg]]]; fH _ FS.StreamOpen[fileName: Rope.Cat[fileNamePrefix, reg, fileNameSuffix], accessOptions: create]; fH.PutF["DL inversion for the %g registry.\n\n%t\n\n\n\n", IO.rope[reg], IO.time[]]; data _ RedBlackTree.LookupSmallest[membersTable]; UNTIL data = NIL DO mR: REF MemberRecord _ NARROW[data]; key: ROPE _ mR.name; IF acceptAll OR Rope.Equal[reg, ExtractRegistry[key], FALSE] THEN {PrintMemberEntry[mR]; [] _ RedBlackTree.Delete[membersTable, key]}; data _ RedBlackTree.LookupNextLarger[membersTable, key]; ENDLOOP; fH.Flush[]; fH.Close[]; }; -- CreateOutputFileForRegistry-- PrintMemberEntry: PROC [mR: REF MemberRecord] = { groupPrinted: BOOL _ FALSE; mbrStatus: MailStatus; numGroups: CARDINAL _ 0; PutGroup: PROC [group: ROPE, owners, friends: BOOL] = { IF groupPrinted THEN fH.PutRope[", "] ELSE groupPrinted _ TRUE; IF owners THEN fH.PutRope["Owners("]; IF friends THEN fH.PutRope["Friends("]; fH.PutRope[group]; IF owners OR friends THEN fH.PutRope[")"]; }; --PutGroup-- Labels.Set[currentName, mR.name]; fH.PutF["\n\n%g: ", IO.rope[mR.name]]; mbrStatus _ PrintMailStatus[mR.name, mR.knownToBeIndividual]; IF mR.owner#NIL THEN FOR j: CARDINAL IN [0 .. groups.length) DO IF mR.owner[j] THEN { PutGroup[groups[j], TRUE, FALSE]; IF mbrStatus=notRegistered THEN RecordBadMember[ tbl: badDLsTable, dl: Rope.Cat["Owners(", groups[j], ")"], mbr: mR.name]; }; ENDLOOP; IF mR.friend#NIL THEN FOR j: CARDINAL IN [0 .. groups.length) DO IF mR.friend[j] THEN { PutGroup[groups[j], FALSE, TRUE]; IF mbrStatus=notRegistered THEN RecordBadMember[ tbl: badDLsTable, dl: Rope.Cat["Friends(", groups[j], ")"], mbr: mR.name]; }; ENDLOOP; IF mR.member#NIL THEN FOR j: CARDINAL IN [0 .. groups.length) DO IF mR.member[j] THEN { PutGroup[groups[j], FALSE, FALSE]; IF mbrStatus=notRegistered THEN RecordBadMember[tbl: badDLsTable, dl: groups[j], mbr: mR.name]; numGroups _ numGroups + 1; }; ENDLOOP; IF NOT groupPrinted THEN fH.PutRope["NONE"]; IF mbrStatus=inboxes THEN gram.DataPoint[MIN[numGroups, maxGram]]; currentMbrs _ currentMbrs + 1; UpdateCounter[currentMembers, currentMbrs]; }; --PrintMemberEntry-- Foreign: PROC [name: ROPE] RETURNS [BOOL] = { reg: ROPE = ExtractRegistry[name]; IF foreignRegistries = NIL THEN { c: CARDINAL; fR: GVNames.RListHandle; AddThem: PROC[f: ROPE] RETURNS [done: BOOL] = {foreignRegistries[c] _ Rope.Substr[f, 0, FindLastPeriod[f]]; c _ c+1; done _ FALSE}; Labels.Set[currentName, "individuals.foreign"]; [fR, c, ] _ MyExpand["individuals.foreign", TRUE]; foreignRegistries _ NEW [RopeSequence[c]]; c _ 0; EnumerateRList[fR, AddThem]; }; FOR i: CARDINAL IN [0 .. foreignRegistries.length) DO IF Rope.Equal[foreignRegistries[i], reg, FALSE] THEN RETURN[TRUE]; ENDLOOP; RETURN[FALSE]; }; --Foreign-- MailStatus: TYPE = {notRegistered, invalid, forwarded, foreign, inboxes, group}; PrintMailStatus: PROC [name: ROPE, knownToBeIndividual: BOOL] RETURNS [status: MailStatus]= { allDownDot: BOOL _ FALSE; UNTIL Stopped[] DO nameType: GVNames.StampInfo _ IF knownToBeIndividual THEN individual ELSE GVNames.CheckStamp[name]; SELECT nameType FROM group => { fH.PutRope["(group) "]; status _ group }; individual => { rLH: GVNames.RListHandle; c: CARDINAL; siteList: BOOL; Labels.Set[currentName, name]; [rLH, c, siteList] _ MyExpand[name, TRUE]; IF c = 0 THEN { fH.PutRope[" (invalid recipient)"]; status _ invalid; } ELSE { fH.PutRope["("]; IF ~siteList THEN { fH.PutRope["->"]; status _ forwarded } ELSE status _ inboxes; fH.PutRope[NameListToRope[rLH]]; fH.PutRope[") "]; }; }; notFound => { IF Foreign[name] THEN { fH.PutRope[" (foreign registry)"]; status _ foreign } ELSE { fH.PutRope["(not registered) "]; status _ notRegistered; }; }; allDown => { ReportAllDown[allDownDot, name]; allDownDot_TRUE; LOOP; }; ENDCASE => ERROR; EXIT; ENDLOOP; }; --PrintMailStatus-- InsertGrouplessIndividuals: PROC [reg: ROPE] = { RecordIfNonMember: PROC [n: ROPE] RETURNS [BOOL] = { mR: REF MemberRecord _ NARROW[RedBlackTree.Lookup[membersTable, n]]; IF mR = NIL THEN mR _ MakeTableEntry[n, TRUE]; RETURN [FALSE]; }; --RecordIfNonMember-- g: ROPE = Rope.Cat["individuals.", reg]; Labels.Set[currentName, g]; EnumerateRList[MyExpand[g, TRUE].m, RecordIfNonMember]; }; --InsertGrouplessIndividuals-- ProcessGroup: PROC [group: ROPE] RETURNS [done: BOOL] = { ownersList: ROPE = Rope.Cat["Owners-", group]; friendsList: ROPE = Rope.Cat["Friends-", group]; doingOwners, doingFriends: BOOL _ FALSE; RecordMembership: PROC [n: ROPE] RETURNS [BOOL] = { mR: REF MemberRecord _ NARROW[RedBlackTree.Lookup[membersTable, n]]; IF mR=NIL THEN mR _ MakeTableEntry[n, FALSE]; SELECT TRUE FROM doingOwners => { IF mR.owner=NIL THEN mR.owner _ NEW[Membership[groups.length]]; mR.owner[currentGrp] _ TRUE; }; doingFriends => { IF mR.friend=NIL THEN mR.friend _ NEW[Membership[groups.length]]; mR.friend[currentGrp] _ TRUE; }; ENDCASE => { IF mR.member=NIL THEN mR.member _ NEW[Membership[groups.length]]; mR.member[currentGrp] _ TRUE; }; RETURN [FALSE]; }; --RecordMembership-- Labels.Set[currentName, group]; UpdateCounter[currentGroups, currentGrp+1]; EnumerateRList[MyExpand[group, TRUE].m, RecordMembership]; doingFriends _ TRUE; EnumerateRList[MyGetFriends[group, TRUE].m, RecordMembership]; doingOwners _ TRUE; EnumerateRList[MyExpand[ownersList, TRUE].m, RecordMembership]; groups[currentGrp] _ group; currentGrp _ currentGrp+1; RETURN[FALSE] }; MakeTableEntry: PROC [n: ROPE, ind: BOOL] RETURNS [mR: REF MemberRecord] = { mR _ NEW [MemberRecord]; mR.name _ n; mR.knownToBeIndividual _ ind; mR.owner _ NIL; mR.member _ NIL; totalMbrs _ totalMbrs + 1; UpdateCounter[totalMembers, totalMbrs]; RedBlackTree.Insert[membersTable, mR, n]; }; --MakeTableEntry-- UpdateCounter: PROC [l: Labels.Label, c: CARDINAL] = {Labels.Set[l, IO.PutFR[v1: IO.card[c]] ]}; registryList: LIST OF GVNames.RListHandle _ NIL; groups: REF RopeSequence; foreignRegistries: REF RopeSequence _ NIL; fH: IO.STREAM; membersTable: RedBlackTree.Table = RedBlackTree.Create[GetKey, MyCompare]; badDLsTable: RedBlackTree.Table = RedBlackTree.Create[GetKey, MyCompare]; currentGrp, totalGrp, currentMbrs, totalMbrs: CARDINAL _ 0; inputRegs: ROPE = ViewerTools.GetContents[registries]; fileNamePrefix: ROPE; fileNameSuffix: ROPE; maxGram: INT = 500; gram: Histogram.Gram = Histogram.NewGram[0, maxGram]; outStr.PutF["Running at %t.", IO.time[]]; Labels.Set[currentName, "none"]; UpdateCounter[totalGroups, 0]; UpdateCounter[currentGroups, 0]; UpdateCounter[totalMembers, 0]; UpdateCounter[currentMembers, 0]; ParseFileNamePattern[]; ForWordsInRopeDo[inputRegs, CheckRegistryValidity]; ForWordsInRopeDo[AllRegistries[], GetRegistryGroups]; groups _ NEW [RopeSequence[totalGrp]]; FOR registryList _ registryList, registryList.rest UNTIL registryList = NIL DO EnumerateRList[registryList.first, ProcessGroup]; ENDLOOP; ForWordsInRopeDo[inputRegs, InsertGrouplessIndividuals]; ForWordsInRopeDo[inputRegs, CreateOutputFileForRegistry]; PrintBadMembers[badDLsTable, inputRegs]; gram.Print[outStr, "\n\nNumber of DL's for each mail system user."]; outStr.PutF["\nDone at %t.\n\n", IO.time[]]; };--Invert-- RopeSequence: TYPE = RECORD[SEQUENCE length: CARDINAL OF ROPE]; inverterStopped: ERROR = CODE; inversionInProgress: BOOL _ FALSE; allRegistries: ROPE _ NIL; defaultRegistries: ROPE = "AllAreas Arpa Auto BITNET CHI Cholla COM CSNET DLOS DLOSLV EDU EIS ElSegundo EOSA ES ESArea ESCP8 ESXC15 ESXC16 FX GOV Guest Henr IHAIL Internet MAILNET NS OSBUBayshore OSBUNorth OSBUSouth OSDA PA PAArea PARC PASA RX SanDiegoXCSS SBDERX Siemens Sunnyvale UK UUCP WBST WBSTArea WBST128 WBST129 X XRCC XSIS MS GV Other"; defaultFileNamePattern: ROPE = "///GV/*.txt"; stop: BOOL _ FALSE; DoIt: Menus.MenuProc = { IF ~ReserveInverter[] THEN RETURN; Invert[ ! inverterStopped => {outStr.PutF["\nStopped at %t.\n\n", IO.time[]]; CONTINUE} ]; outStr.Flush[]; ReleaseInverter[]; }; -- DoIt-- StopIt: Menus.MenuProc = {SetStop[]}; ReserveInverter: ENTRY PROC RETURNS [BOOL] = { IF inversionInProgress THEN RETURN [FALSE] ELSE {inversionInProgress _ TRUE; RETURN[TRUE]}; }; ReleaseInverter: ENTRY PROC = {inversionInProgress _ FALSE; stop _ FALSE}; SetStop: ENTRY PROC = {stop _ TRUE}; StopSet: ENTRY PROC RETURNS [BOOL] = {RETURN [stop]}; Stopped: PROC RETURNS [BOOL] = { IF StopSet[] THEN ERROR inverterStopped ELSE RETURN[FALSE]}; AllRegistries: PROC RETURNS[ROPE] = { ExtractRegistry: PROC [r: ROPE] RETURNS [done: BOOL] = { allRegistries _ Rope.Cat[allRegistries, " ", Rope.Substr[r, 0, FindLastPeriod[r]]]; done _ FALSE; }; IF allRegistries = NIL THEN { Labels.Set[currentName, "groups.gv"]; EnumerateRList[ MyExpand["groups.gv", FALSE].m, ExtractRegistry]; }; RETURN [ allRegistries ]; }; --AllRegistries-- FindLastPeriod: PROC[r: ROPE] RETURNS [lastPeriod: CARDINAL] = { FOR i: INT DECREASING IN [0 .. Rope.Length[r]) DO IF Rope.Fetch[r, i] = '. THEN {lastPeriod _ i; EXIT}; REPEAT FINISHED => lastPeriod _ Rope.Length[r]; ENDLOOP; }; --FindLastPeriod-- ReportAllDown: PROC [dot: BOOL, name: ROPE] = { IF dot THEN outStr.PutRope["."] ELSE outStr.PutF["\nAll down: %g. ", [rope[name]]]; }; MyExpand: PROC [eName: ROPE, ignoreNotFound: BOOL] RETURNS [m: GVNames.RListHandle, c: CARDINAL, isSiteList: BOOL] = { printDot: BOOL _ FALSE; ReportNotFound: PROC = {outStr.PutF["%g%g\n\n", [rope[eName]], [rope[" not found."]]]; ERROR inverterStopped}; UNTIL Stopped[] DO WITH GVNames.Expand[eName] SELECT FROM g: GVNames.ExpandInfo[group] => {m _ g.members; c _ g.count; isSiteList _ FALSE}; i: GVNames.ExpandInfo[individual] => {m _ i.sites; c _ i.count; isSiteList _ TRUE}; n: GVNames.ExpandInfo[notFound] => WITH GVNames.GetMembers[eName] SELECT FROM g: GVNames.MemberInfo[group] => {m _ g.members; c _ g.count; isSiteList _ FALSE}; n: GVNames.MemberInfo[notFound] => IF ignoreNotFound THEN {m _ NIL; c _ 0} ELSE ReportNotFound[]; a: GVNames.MemberInfo[allDown] => {ReportAllDown[printDot, eName]; printDot _ TRUE; LOOP}; ENDCASE => ERROR; a: GVNames.ExpandInfo[allDown] => {ReportAllDown[printDot, eName]; printDot _ TRUE; LOOP}; ENDCASE => ERROR; EXIT; ENDLOOP; }; --MyExpand-- MyGetFriends: PROC [eName: ROPE, ignoreNotFound: BOOL] RETURNS [m: GVNames.RListHandle, c: CARDINAL, isSiteList: BOOL] = { printDot: BOOL _ FALSE; ReportNotFound: PROC = {outStr.PutF["%g%g\n\n", [rope[eName]], [rope[" not found."]]]; ERROR inverterStopped}; UNTIL Stopped[] DO WITH GVNames.GetFriends[eName] SELECT FROM g: GVNames.MemberInfo[group] => {m _ g.members; c _ g.count; isSiteList _ FALSE}; i: GVNames.MemberInfo[individual] => ERROR; n: GVNames.MemberInfo[notFound] => IF ignoreNotFound THEN {m _ NIL; c _ 0; isSiteList _ FALSE} ELSE ReportNotFound[]; a: GVNames.MemberInfo[allDown] => {ReportAllDown[printDot, eName]; printDot _ TRUE; LOOP}; ENDCASE => ERROR; EXIT; ENDLOOP; }; ExtractRegistry: PROC [RName: ROPE] RETURNS [registry: ROPE] = { start: CARDINAL _ FindLastPeriod[RName]+1; RETURN [IF start >= Rope.Length[RName] THEN NIL ELSE Rope.Substr[RName, start, Rope.Length[RName] - start]] }; --ExtractRegistry-- NameListToRope: PROC [mLH: GVNames.RListHandle] RETURNS [r: ROPE] = { AddMemberToRope: PROC[m: ROPE] RETURNS [done: BOOL] = { IF r # NIL THEN r _ Rope.Cat[r, ", "]; r _ Rope.Cat[r, m]; done _ FALSE }; r _ NIL; EnumerateRList[mLH, AddMemberToRope]; }; --NameListToRope-- ForWordsInRopeDo: PROC [r: ROPE, work: PROC[ROPE]] = { parsePosition: CARDINAL _ Rope.SkipOver[r, 0, " "]; -- skip initial blanks UNTIL parsePosition = Rope.Length[r] DO --parse registry input-- start: CARDINAL = parsePosition; parsePosition _ Rope.SkipTo[r, parsePosition, " "]; work[Rope.Substr[r, start, parsePosition-start]]; parsePosition _ Rope.SkipOver[r, parsePosition, " "]; ENDLOOP; }; -- ForWordsInRopeDo -- EnumerateRList: PROC [r: GVNames.RListHandle, p: PROC [ROPE] RETURNS [BOOL] ] = {FOR r _ r, r.rest UNTIL r=NIL OR p[r.first] DO ENDLOOP}; ValidNameWithStar: PROC [reg: ROPE] RETURNS [ok: BOOL] = { printDot: BOOL _ FALSE; length: INT _ Rope.Length[reg]; IF Rope.Equal[reg, "*"] THEN RETURN [TRUE]; IF length < 3 THEN RETURN [FALSE]; IF Rope.Fetch[reg, 0] # '* THEN RETURN [FALSE]; IF Rope.Fetch[reg, 1] # '. THEN RETURN [FALSE]; reg _ Rope.Substr[reg, 2, length-2]; UNTIL Stopped[] DO name: ROPE _ Rope.Cat[reg, ".gv"]; SELECT GVNames.CheckStamp[name] FROM group => RETURN [TRUE]; individual => RETURN [FALSE]; notFound => RETURN [FALSE]; allDown => {ReportAllDown[printDot, name]; printDot_TRUE; LOOP}; ENDCASE => ERROR; ENDLOOP; }; CheckRegistryValidity: PROC [reg: ROPE] = { printDot: BOOL _ FALSE; ReportInvalidRegistry: PROC = { outStr.PutF["%g%g\n\n", [rope[reg]], [rope[" is not a valid registry."]]]; ERROR inverterStopped; }; IF Rope.Equal["other", reg, FALSE] THEN RETURN; UNTIL Stopped[] DO name: ROPE _ Rope.Cat[reg, ".gv"]; SELECT GVNames.CheckStamp[name] FROM group => NULL; individual => ReportInvalidRegistry[]; notFound => { name _ Rope.Cat[reg, ".foreign"]; SELECT GVNames.CheckStamp[name] FROM group, notFound => ReportInvalidRegistry[]; individual => NULL; allDown => {ReportAllDown[printDot, name]; printDot_TRUE; LOOP}; ENDCASE => ERROR; }; allDown => {ReportAllDown[printDot, name]; printDot_TRUE; LOOP}; ENDCASE => ERROR; EXIT; ENDLOOP; }; --CheckRegistryValidity-- BadDL: TYPE = RECORD [name: ROPE, badMbr: LIST OF ROPE]; RecordBadMember: PROC [tbl: RedBlackTree.Table, dl, mbr: ROPE] = { dlEntry: REF BadDL; IF ValidNameWithStar[mbr] THEN RETURN; dlEntry _ NARROW[RedBlackTree.Lookup[tbl, dl]]; IF dlEntry = NIL THEN { dlEntry _ NEW[BadDL]; dlEntry.name _ dl; dlEntry.badMbr _ NIL; RedBlackTree.Insert[tbl, dlEntry, dl]; }; dlEntry.badMbr _ CONS[mbr, dlEntry.badMbr]; }; --RecordBadMember-- PrintBadMembers: PROC [tbl: RedBlackTree.Table, inputRegistries: ROPE] = { PrintBadDLsForRegistry: PROC [reg: ROPE] = { needRegistryLabel: BOOL _ TRUE; acceptAll: BOOL = Rope.Equal["other", reg, FALSE]; data: RedBlackTree.UserData; data _ RedBlackTree.LookupSmallest[tbl]; UNTIL data = NIL DO dl: REF BadDL _ NARROW[data]; key: ROPE _ dl.name; IF Rope.Equal[reg, ExtractRegistry[key], FALSE] OR acceptAll THEN { firstName: BOOL _ TRUE; IF needRegistryLabel THEN { IF needTitle THEN { outStr.PutRope["\n\n\nDL's with members that are NOT REGISTERED."]; needTitle _ FALSE; }; outStr.PutF["\n\n\n""%g"" registry:\n", IO.rope[reg]]; needRegistryLabel _ FALSE; }; Labels.Set[currentName, dl.name]; outStr.PutF["\n\n%g -- ", IO.rope[key]]; FOR mbr: LIST OF ROPE _ dl.badMbr, mbr.rest UNTIL mbr=NIL DO IF firstName THEN firstName _ FALSE ELSE outStr.PutRope[", "]; outStr.PutRope[mbr.first]; ENDLOOP; [] _ RedBlackTree.Delete[tbl, key]; }; data _ RedBlackTree.LookupNextLarger[tbl, key];ENDLOOP; }; --PrintBadDLsForRegistry-- needTitle: BOOL _ TRUE; ForWordsInRopeDo[inputRegistries, PrintBadDLsForRegistry]; IF needTitle THEN outStr.PutRope["No bad members.\n"] }; --PrintBadMembers-- Membership: TYPE = RECORD[PACKED SEQUENCE length: CARDINAL OF BOOL]; MemberRecord: TYPE = RECORD[name: ROPE, knownToBeIndividual: BOOL, owner, friend, member: REF Membership]; GetKey: PROC [data: RedBlackTree.UserData] RETURNS [key: RedBlackTree.Key] = { WITH data SELECT FROM m: REF MemberRecord => key _ m.name; d: REF BadDL => key _ d.name; r: ROPE => key _ r; ENDCASE => ERROR; }; MyCompare: PROC [k: RedBlackTree.Key, data: RedBlackTree.UserData] RETURNS [Basics.Comparison] = { a: ROPE _ NARROW[k]; b: ROPE _ NARROW[GetKey[data]]; RETURN [Rope.Compare[a, b, FALSE]] }; --compareMbrs-- entryHeight: CARDINAL = 15; entryVSpace: CARDINAL = 10; entryHSpace: CARDINAL = 10; heightSoFar: CARDINAL _ 0; container: Containers.Container; currentMembers, totalMembers: Labels.Label; currentGroups, totalGroups: Labels.Label; currentName: Labels.Label; exceptions: ViewerClasses.Viewer; inStr, outStr: IO.STREAM; fileName, registries: ViewerClasses.Viewer; BuildOuter: PROC = { myMenu: Menus.Menu _ Menus.CreateMenu[]; container _ Containers.Create[info: [name: "InvertDLs", scrollable: FALSE] ]; Menus.InsertMenuEntry[menu: myMenu, entry: Menus.CreateEntry[name: "DoIt", proc: DoIt] ]; Menus.InsertMenuEntry[menu: myMenu, entry: Menus.CreateEntry[name: "Stop", proc: StopIt] ]; ViewerOps.SetMenu[viewer: container, menu: myMenu]; BuildUserInput[]; BuildUserFeedback[]; BuildExceptions[]; ViewerOps.SetOpenHeight[viewer: container, clientHeight: heightSoFar]; ViewerOps.PaintViewer[viewer: container, hint: all]; }; BuildUserInput: PROC = { l1, l2: Buttons.Button; heightSoFar _ heightSoFar+entryVSpace/2; l1 _ Buttons.Create[info: [name: "File name pattern (* for registry):", parent: container, border: FALSE, wy: heightSoFar], proc: ForceSelToFileName]; fileName _ ViewerTools.MakeNewTextViewer[info: [parent: container, wx: l1.wx+l1.ww+entryHSpace, wy: heightSoFar, ww: 0, wh: entryHeight, data: defaultFileNamePattern, scrollable: FALSE, border: FALSE], paint: FALSE]; Containers.ChildXBound[container, fileName]; heightSoFar _ heightSoFar+entryVSpace+l1.wh; l2 _ Buttons.Create[info: [name: "Registries:", parent: container, border: FALSE, wy: heightSoFar], proc: ForceSelToRegistries]; registries _ ViewerTools.MakeNewTextViewer[info: [parent: container, wx: l2.wx+l2.ww+entryHSpace, wy: heightSoFar, ww: 0, wh: 3*entryHeight, data: defaultRegistries, scrollable: TRUE, border: FALSE], paint: FALSE]; Containers.ChildXBound[container, registries]; heightSoFar _ heightSoFar+entryVSpace+registries.wh; }; ForceSelToFileName: Buttons.ButtonProc = { IF mouseButton#red THEN ViewerTools.SetContents[fileName, defaultFileNamePattern] ELSE ViewerTools.SetSelection[fileName]; }; ForceSelToRegistries: Buttons.ButtonProc = { IF mouseButton#red THEN ViewerTools.SetContents[registries, defaultRegistries] ELSE ViewerTools.SetSelection[registries]; }; BuildUserFeedback: PROC = { li, lg, ln, of: Labels.Label; r1: Rules.Rule; r1 _ Rules.Create[info: [parent: container, wx: 0, wy: heightSoFar, ww: 0, wh:1]]; Containers.ChildXBound[container, r1]; heightSoFar _ heightSoFar+entryVSpace; li _ Labels.Create[info: [name: "Members:", parent: container, wx: 0, wy: heightSoFar, border: FALSE]]; currentMembers _ Labels.Create[info: [name: "0000", parent: container, wx: li.wx+li.ww+entryHSpace, wy: heightSoFar, border: TRUE]]; Labels.Set[currentMembers, "0"]; of _ Labels.Create[info: [name: "of", parent: container, wx: currentMembers.wx+currentMembers.ww+entryHSpace, wy: heightSoFar, border: FALSE]]; totalMembers _ Labels.Create[info: [name: "0000", parent: container, wx: of.wx+of.ww+entryHSpace, wy: heightSoFar, border: TRUE]]; Labels.Set[totalMembers, "0"]; lg _ Labels.Create[info: [name: "Groups:", parent: container, wx: totalMembers.wx+totalMembers.ww+entryHSpace+entryHSpace, wy: heightSoFar, border: FALSE]]; currentGroups _ Labels.Create[info: [name: "0000", parent: container, wx: lg.wx+lg.ww+entryHSpace, wy: heightSoFar, border: TRUE]]; Labels.Set[currentGroups, "0"]; of _ Labels.Create[info: [name: "of", parent: container, wx: currentGroups.wx+currentGroups.ww+entryHSpace, wy: heightSoFar, border: FALSE]]; totalGroups _ Labels.Create[info: [name: "0000", parent: container, wx: of.wx+of.ww+entryHSpace, wy: heightSoFar, border: TRUE]]; Labels.Set[totalGroups, "0"]; heightSoFar _ heightSoFar+entryVSpace+of.wh; ln _ Labels.Create[info: [name: "Current Name:", parent: container, wx: 0, wy: heightSoFar, border: FALSE]]; currentName _ Labels.Create[info: [name: "", parent: container, wx: ln.wx+ln.ww+entryHSpace, wy: heightSoFar, border: FALSE]]; Labels.Set[currentName, "none"]; Containers.ChildXBound[container, currentName]; heightSoFar _ heightSoFar+entryVSpace+of.wh; }; BuildExceptions: PROC = { r2: Rules.Rule; r2 _ Rules.Create[info: [parent: container, wx: 0, wy: heightSoFar, ww: 0, wh: 1]]; Containers.ChildXBound[container, r2]; heightSoFar _ heightSoFar+entryVSpace; exceptions _ ViewerOps.CreateViewer[flavor: $Typescript, info: [name: "", parent: container, wx: 0, wy: heightSoFar, wh: 5*entryHeight, border: FALSE]]; heightSoFar _ heightSoFar+exceptions.wh; Containers.ChildXBound[container, exceptions]; Containers.ChildYBound[container, exceptions]; [in: inStr, out: outStr] _ ViewerIO.CreateViewerStreams[name: "", viewer: exceptions, backingFile: "InvertDLs.log"]; }; BuildOuter[]; }.. ΜGVInvert.mesa; HGM, November 20, 1984 9:46:45 pm PST Copyright c 1985 by Xerox Corporation. All rights reserved. Edited by Schroeder on March 19, 1983 2:35 pm Hal Murray May 7, 1985 11:58:32 pm PDT Ron Weaver August 30, 1985 11:15:05 am PDT Hal Murray, April 7, 1986 1:00:48 am PST John Larson, July 6, 1986 0:42:27 am PDT Can't get here **************** Viewers set up stuff **************** ******************** Initialization ********************-- Κ˜šœ4™4Jšœ<™J˜BJšœ˜J˜—J˜1J˜QJšœΟc˜—J˜šžœœœ˜%Jšœœ˜ Jšœœ˜&J˜J˜ Jšœœ˜%Jšœœ˜'J˜J˜%JšœŸ˜—J˜šžœœœ˜1J˜Jšœ œœ˜2J˜;šœœD˜KJ˜—Jšœ;œ œ ˜TJ˜1šœœ˜Jšœœœ˜$Jšœœ ˜Jšœ œ'œ˜AJ˜DJ˜8Jšœ˜—J˜ J˜ JšœŸ ˜#—J˜šžœœœ˜1Jšœœœ˜J˜Jšœ œ˜šžœœ œœ˜7Jšœœœœ˜?Jšœœ˜%Jšœ œ˜'J˜Jšœœ œ˜*JšœŸ ˜—J˜!Jšœœ˜&J˜=š œ œœœœœ˜?šœ œ˜Jšœœœ˜!Jšœ˜˜J˜I—J˜—Jšœ˜—š œ œœœœœ˜@šœœ˜Jšœœœ˜!Jšœ˜˜J˜J—J˜—Jšœ˜—š œ œœœœœ˜@šœœ˜Jšœœœ˜"Jšœ˜J˜?J˜J˜—Jšœ˜—Jšœœœ˜,Jšœœœ˜BJ˜J˜+JšœŸ˜—J˜š žœœœœœ˜-Jšœœ˜"šœœœ˜!Jšœœ˜ J˜Jš žœœœœœ˜-JšœOœ˜VJ˜/Jšœ,œ˜2Jšœœ˜*J˜J˜J˜—šœœœ!˜5Jš œ'œœœœ˜BJšœ˜—Jšœœ˜JšœŸ ˜—J˜Jšœ œA˜QJ˜šžœœœœ˜=Jšœ˜Jšœ œœ˜šœ ˜šœœ˜4Jšœ œ˜.—šœ ˜J˜4˜J˜Jšœœ˜ Jšœ œ˜J˜Jšœ$œ˜*Jšœœ:˜Gšœ˜J˜Jšœ œ)˜:Jšœ˜J˜ J˜J˜—J˜—˜Jšœœ8˜Mšœ˜J˜ J˜——Jšœ9œœ˜GJšœœ˜—Jšœ˜Jšœ˜—JšœŸ˜—J˜šžœœœ˜0š žœœœœœ˜4Jšœœœ'˜DJšœœœœ˜.Jšœœ˜JšœŸ˜—Jšœœ!˜(J˜Jšœœ˜8JšœŸ˜!—J˜š ž œœ œœœ˜9Jšœ œ˜.Jšœ œ˜0Jšœœœ˜(š žœœœœœ˜3Jšœœœ'˜DJšœœœœ˜-šœœ˜˜Jšœ œ˜Jšœ œ˜*Jšœœ˜J˜—˜Jšœ œ˜Jšœ œ˜+Jšœœ˜J˜—Jšœ˜ Jšœ œ˜Jšœ œ˜+Jšœœ˜J˜—Jšœœ˜JšœŸ˜—J˜J˜+Jšœœ˜:Jšœœ˜Jšœ#œ˜>Jšœœ˜Jšœ$œ˜?J˜J˜Jšœœ˜ J˜—J˜J˜Jšžœœœœ˜)šœœ˜"Jšœœ˜J˜ J˜Jšœ œ˜Jšœ œ˜J˜J˜'J˜)JšœŸ˜—J˜Jšž œœœ˜4Jšœœ œ ˜+J˜Jšœœœœ˜0Jšœœ˜Jšœœœ˜*Jšœœœ˜J˜JJ˜IJšœ.œ˜;Jšœ œ'˜6Jšœœ˜Jšœœ˜Jšœ œ˜J˜5J˜Jšœœ ˜)J˜ J˜J˜ J˜J˜!J˜J˜3J˜5Jšœ œ˜&šœ0œœ˜NJ˜1Jšœ˜—J˜8J˜9J˜(J˜DJšœ!œ ˜,J˜JšœŸ ˜ —J˜Jš œœœœ œœœ˜?J˜Jšœœœ˜Jšœœœ˜#Jšœœœ˜JšœœΒ˜ΩJšœœ˜.Jšœœœ˜J˜šžœ˜Jšœœœ˜"JšœBœ œ˜ZJ˜J˜JšœŸ ˜ —J˜Jšžœ˜%J˜š žœœœœœ˜.Jšœœœœ˜*Jšœœœœ˜0J˜—J˜Jš žœœœœ œ˜JJ˜Jšžœœœ œ˜$J˜Jš žœœœœœœ ˜6J˜šžœœœœ˜ Jš œ œœœœœ˜<—J˜šž œœœœ˜%š žœœœœœ˜8J˜SJšœœ˜ J˜—šœœœ˜J˜%Jšœ&œ˜BJ˜—Jšœ˜JšœŸ˜—J˜š žœœœœœ˜@š œœ œœ˜1Jšœœœ˜5Jšœœ ˜/Jšœ˜ —JšœŸ˜—J˜šž œœœœ˜/Jšœ˜Jšœ˜Jšœ/˜3J˜—J˜Jšžœœ œœ˜2šœœœ˜CJšœ œœ˜Jšžœœ˜Jšœ@œ˜Wšœ ˜šœœ˜&˜Jšœ*œ˜1—˜$Jšœ(œ˜.—˜"šœœ˜*˜Jšœ*œ˜1—˜"Jšœœœ˜'Jšœ˜—˜!Jšœ,œœ˜8—Jšœœ˜——˜!Jšœ,œœ˜8—Jšœœ˜—Jšœ˜Jšœ˜—JšœŸ ˜—J˜Jšž œœ œœ˜6šœœœ˜CJšœ œœ˜Jšžœœ˜Jšœ@œ˜Wšœ ˜šœœ˜*˜Jšœ*œ˜1—Jšœ%œ˜+˜"Jšœœœœ˜;Jšœ˜—˜!Jšœ,œœ˜8—Jšœœ˜—Jšœ˜Jšœ˜—J˜—J˜š žœœžœœœ œ˜@Jšœœ˜*šœœ˜&Jšœœœ7˜D—JšœŸ˜—J˜šžœœœœ˜Eš žœœœœœ˜7Jšœœœ˜&J˜šœ˜ J˜——Jšœœ˜J˜%JšœŸ˜—J˜š žœœœœœ˜6JšœœŸ˜Jšœ œŸ˜@Jšœœ˜ J˜3J˜1J˜5Jšœ˜—JšœŸ˜—J˜šžœœ˜-Jš œœœœœ˜!—Jš œœœœœ œœ˜9J˜š žœœœœœ˜:Jšœ œœ˜Jšœœ˜Jšœœœœ˜+Jšœ œœœ˜"Jšœœœœ˜/Jšœœœœ˜/J˜$šœ ˜Jšœœ˜"šœ˜$Jšœ œœ˜Jšœœœ˜Jšœ œœ˜J˜ Jšœ)œœ˜5Jšœœ˜—Jšœ™Jšœ˜—J˜—J˜šžœœœ˜+Jšœ œœ˜šžœœ˜J˜JJšœ˜J˜—Jšœœœœ˜/šœ ˜Jšœœ˜"šœ˜$Jšœœ˜J˜&˜J˜!šœ˜$J˜J˜J˜ Jšœ˜J˜ Jšœ)œœ˜5Jšœœ˜—J˜—˜ Jšœ)œœ˜5—Jšœœ˜—Jšœ˜Jšœ˜—JšœŸ˜—J˜J˜Jš œœœœ œœœ˜8J˜šžœœ$œ˜BJšœ œ˜Jšœœœ˜&Jšœ œ˜/šœ œœ˜Jšœ œ˜J˜Jšœœ˜J˜'J˜—Jšœœ˜+JšœŸ˜—J˜šžœœ,œ˜Jšžœœœ˜,Jšœœœ˜Jšœ œœ˜2J˜J˜(šœœ˜Jšœœ œ˜Jšœœ ˜Jšœ'œœ ˜A˜Jšœ œœ˜šœœ˜šœ œ˜J˜CJšœ œ˜J˜—Jšœ(œ ˜6Jšœœ˜J˜—J˜!Jšœœ ˜(š œœœœœœ˜J˜Jšœ˜—J˜#J˜—Jšœ/œ˜7—JšœŸ˜—Jšœ œœ˜J˜:Jšœ œ$˜5JšœŸ˜—J˜J˜Jšœ œœœœ œœœ˜DJ˜š œœœœœ˜BJšœœ ˜'—J˜šžœœœ˜Nšœœ˜Jšœœ˜$Jšœœ˜Jšœœ ˜Jšœœ˜—J˜—J˜šž œœ4œœ˜cJšœœœ˜Jšœœœ˜Jšœœ˜"JšœŸ˜—J˜J˜Jšœ6™6J˜Jšœ œ˜Jšœ œ˜Jšœ œ˜J˜Jšœ œ˜J˜J˜!J˜+J˜)J˜J˜!Jšœœœ˜J˜J˜+J˜šž œœ˜J˜(JšœDœ˜M˜#J˜2J˜—˜#J˜4J˜—J˜3J˜J˜J˜J˜FJ˜4J˜—J˜šžœœ˜J˜J˜(˜GJšœœ.˜N—˜BJ˜EJšœ*œ œ œ˜O—J˜,J˜,˜BJšœœ0˜=—˜DJ˜GJšœ%œ œ œ˜I—J˜.J˜4J˜—J˜šžœ˜*Jšœ˜Jšœ:˜>Jšœ$˜(J˜—J˜šžœ˜,Jšœ˜Jšœ7˜;Jšœ&˜*J˜—J˜šžœœ˜J˜J˜J˜RJ˜&J˜&˜VJšœœ˜—˜FJšœ6œ˜=—J˜ ˜8JšœNœ˜V—˜DJšœ6œ˜=—J˜˜=J˜MJšœœ˜—˜EJšœ6œ˜=—J˜˜8JšœLœ˜T—˜`Jšœœ˜ —J˜J˜,˜[Jšœœ˜—˜\Jšœœ˜!—J˜ J˜/J˜,J˜—J˜šžœœ˜J˜J˜SJ˜&J˜&˜8˜NJšœœ˜——J˜(J˜.J˜.˜UJ˜—J˜—J˜J˜Jšœ:™:J˜J˜ J˜J˜—J˜—…—VΒp©