-- File: GrapenutImpl.mesa -- Contents: whitepages facilities, running on top of Cypress, Squirrel, and Finch -- Created by Cattell, January 1984 -- Last edited by: -- Cattell on January 13, 1984 5:36 pm DIRECTORY CommandTool, Commander, DB, FinchSmarts USING [PlaceCall], IO, Menus, Nut, NutOps, NutViewer, Rope, PrincOpsUtils USING [IsBound], ViewerClasses USING [Viewer], ViewerOps USING [PaintViewer], UserCredentials; GrapenutImpl: CEDAR PROGRAM IMPORTS CommandTool, Commander, DB, FinchSmarts, IO, Menus, Nut, NutOps, NutViewer, Rope, PrincOpsUtils, ViewerOps, UserCredentials = BEGIN ROPE: TYPE = Rope.ROPE; PhoneProc: Commander.CommandProc = TRUSTED { ENABLE IO.EndOfStream => {msg_ "Illegal syntax"; CONTINUE}; number: ROPE; t: DB.Relship; phone: DB.Relation; phoneOf, phoneIs, phoneAt: DB.Attribute; h: IO.STREAM = IO.RIS[cmd.commandLine]; skip: CHAR = h.GetChar[]; -- skip leading space name: ROPE = h.GetLineRope[]; person: DB.Entity = StringToPerson[name]; IF person=NIL THEN RETURN[NIL, Rope.Cat["Found no Person or RegisteredName ", name]]; phone_ DB.DeclareRelation["phone", DB.SegmentOf[person], OldOnly]; phoneOf_ DB.DeclareAttribute[phone, "of"]; phoneIs_ DB.DeclareAttribute[phone, "is"]; phoneAt_ DB.DeclareAttribute[phone, "at"]; t_ DB.DeclareRelship[phone, LIST[[phoneOf, person], [phoneAt, DB.S2V["work"]]], OldOnly]; IF t=NIL THEN RETURN[NIL, Rope.Cat["Found no phone number for ", name]]; number _ DB.V2S[DB.GetF[t, phoneIs]]; IF NOT PrincOpsUtils.IsBound[FinchSmarts.PlaceCall] THEN { err: ROPE; NutViewer.MessageRope[NIL, "Loading and starting Finch... "]; err_ CommandTool.Run["Finch"].errMsg; IF err.Length[]#0 THEN NutViewer.Message[NIL, err] ELSE { [] _ CommandTool.DoCommandRope[ commandLine: "Finch", parent: NEW[Commander.CommandObject _ []]]; NutViewer.MessageRope[NIL, "Done."] } }; FinchSmarts.PlaceCall[number: number, rName: DB.NameOf[person]]; }; PhoneHomeProc: Menus.MenuProc = { viewer: ViewerClasses.Viewer = NARROW[parent]; seg: DB.Segment; d: DB.Domain; eName: ROPE; ok: PROC[s: ROPE] RETURNS[BOOL] = {RETURN[s.Equal["home", FALSE]]}; [seg, d, eName]_ NutViewer.GetNutInfo[viewer]; Phone[DB.FetchEntity[d, eName, seg], ok]; }; PhoneWorkProc: Menus.MenuProc = { viewer: ViewerClasses.Viewer = NARROW[parent]; seg: DB.Segment; d: DB.Domain; eName: ROPE; ok: PROC[s: ROPE] RETURNS[BOOL] = {RETURN[NOT s.Equal["home", FALSE]]}; [seg, d, eName]_ NutViewer.GetNutInfo[viewer]; Phone[DB.FetchEntity[d, eName, seg], ok]; }; Phone: PROC [e: DB.Entity, ok: PROC[ROPE] RETURNS [BOOL]] = { seg: DB.Segment = DB.SegmentOf[e]; phone: DB.Relation = DB.DeclareRelation["phone", seg, OldOnly]; phoneOf: DB.Attribute = DB.DeclareAttribute[r: phone, name: "of", version: OldOnly]; phoneIs: DB.Attribute = DB.DeclareAttribute[r: phone, name: "is", version: OldOnly]; phoneAt: DB.Attribute = DB.DeclareAttribute[r: phone, name: "at", version: OldOnly]; phones: DB.RelshipSet_ DB.RelationSubset[phone, LIST[[phoneOf, e]]]; FOR pRel: DB.Relship_ DB.NextRelship[phones], DB.NextRelship[phones] UNTIL pRel=NIL DO IF ok[DB.GetFS[pRel, phoneAt]] THEN TRUSTED {FinchSmarts.PlaceCall[ number: DB.GetFS[pRel, phoneIs], rName: DB.NameOf[e], useNumber: TRUE]; RETURN}; ENDLOOP; NutViewer.Error[NIL, "Can't find phone number for ", DB.NameOf[e]]; }; PersonProc: Commander.CommandProc = { ENABLE IO.EndOfStream => {msg_ "Illegal syntax"; CONTINUE}; h: IO.STREAM = IO.RIS[cmd.commandLine]; skip: CHAR = h.GetChar[]; -- skip leading space name: ROPE = h.GetLineRope[]; person: DB.Entity = StringToPerson[name]; IF person#NIL THEN []_ Nut.Display[person] ELSE msg_ Rope.Cat["Found no Person or RegisteredName ", name]; }; StringToPerson: PROC[name: ROPE] RETURNS [person: DB.Entity] = { -- Try to find the named person. Look in Squirrel, GrapenutLocal, and GrapenutRemote -- segments. Try name as an RName, then as a prefix of a real name. localFile: ROPE_ Rope.Cat["[Luther.Alpine]<", UserCredentials.Get[].name, ">Squirrel.segment"]; IF name=NIL THEN RETURN[NIL]; IF NutOps.SetUpSegment[localFile, $Squirrel].success THEN { person_ TryAsRName[name, $Squirrel]; IF person#NIL THEN RETURN; person_ TryAsName[name, $Squirrel]; IF person#NIL THEN RETURN}; IF NutOps.SetUpSegment[ "[Luther.Alpine]Grapenut.segment", $Grapenut].success THEN { person_ TryAsRName[name, $Grapenut]; IF person#NIL THEN RETURN; person_ TryAsName[name, $Grapenut]; IF person#NIL THEN RETURN}; }; TryAsRName: PROC[name: ROPE, seg: DB.Segment] RETURNS [person: DB.Entity] = { RName: DB.Domain = DB.DeclareDomain["RegisteredName", seg, OldOnly]; mailbox: DB.Relation = DB.DeclareRelation["mailbox-name", seg, OldOnly]; mailboxOf: DB.Attribute = DB.DeclareAttribute[mailbox, "of"]; IF RName=NIL THEN RETURN[NIL]; person_ DB.FetchEntity[RName, name]; IF person=NIL THEN RETURN[NIL]; person_ DB.V2E[DB.GetP[person, mailboxOf]]; }; TryAsName: PROC[name: ROPE, seg: DB.Segment] RETURNS [person: DB.Entity] = { es: DB.EntitySet; other: DB.Entity; count: INT_ 0; People: DB.Domain = DB.DeclareDomain["Person", seg, OldOnly]; IF People=NIL THEN RETURN[NIL]; es_ DB.DomainSubset[People, name, name.Concat["\177"]]; person_ DB.NextEntity[es]; IF (other_ DB.NextEntity[es])#NIL THEN BEGIN NutViewer.MessageRope[NIL, "Name is not unique! Matches: "]; NutViewer.MessageRope[NIL, DB.NameOf[person]]; NutViewer.MessageRope[NIL, "; "]; NutViewer.MessageRope[NIL, DB.NameOf[other]]; NutViewer.MessageRope[NIL, "; "]; WHILE (other_ DB.NextEntity[es])#NIL DO IF (count_ count+1)> 5 THEN {NutViewer.MessageRope[NIL, " ... "]; EXIT}; NutViewer.MessageRope[NIL, DB.NameOf[other]]; NutViewer.MessageRope[NIL, "; "]; ENDLOOP; person_ NIL; END; }; MyDisplay: Nut.DisplayProc = -- For Organizations and Persons BEGIN Nut.DefaultDisplay[e, newV, seg]; IF PrincOpsUtils.IsBound[FinchSmarts.PlaceCall] THEN { -- Ambush the menu and add Phone, PhoneHome items on the end! Menus.AppendMenuEntry[newV.menu, Menus.CreateEntry[ "Phone", PhoneWorkProc,, "Call this person at work number"]]; Menus.AppendMenuEntry[newV.menu, Menus.CreateEntry[ "PhoneHome", PhoneHomeProc,, "Call this person at home number"]]; ViewerOps.PaintViewer[newV, menu]; -- Repaint the menu }; END; Nut.Register["Person", NIL, MyDisplay]; Nut.Register["Organization", NIL, MyDisplay]; Commander.Register[ "Person", PersonProc, "Display person with given RName or name (any prefix, lastname first)"]; Commander.Register[ "Ring", PhoneProc, "Phones person with given RName or real name (prefix, lastname first)"]; END. ʘJšœÍ˜ÍJšœÏk œœ œ#œ œLœœœ2 ˜§Jš®œ œ œ"ÏcœœmœœœœÏb œœœœ(œœSœœœœœ0œFœœœœœ­œ>œœœœœ_œ-œœœWœœœ œ`œ@œTœŸ œ7œ3œ œœœœœœBœ'Ÿœ7œ3œ œœœœœœœAœ)ÐbnœœœœœœEœäœœBœœœœœœaœœœœ7žŸ œ œœ(œ œœœœœ0œFœœœœCŸœœœœÉœUœœœœœœ3œ/œœœœ-œœœœœ\œ/œœœœ-œœœœ Ÿ œœœœ˜Ÿ œœœœâœ?œ*œ#œ)œqœ/œ)œ?Ÿ œ9œ'œ.œ…œœ+œ÷œ˜¢3Jšœ˜—…—žf