-- WhiteboardToolImpl.mesa -- last edit by -- Maxwell, September 30, 1982 10:35 am -- Willie-Sue, February 22, 1983 4:30 pm -- Cattell, June 8, 1983 7:08 pm -- Donahue, May 30, 1983 8:53 am DIRECTORY BcdDefs USING [CTIndex, MTIndex, NameRecord], BcdOps USING [BcdBase, CTHandle, MTHandle, NameString, ProcessConfigs, ProcessModules], DB USING [ Attribute, DeclareEntity, Domain, Entity, Error, GetName, GetP, Relship, SetP, S2V, V2E, V2S], Icons USING [IconFlavor], IO USING [UnsafeGetBlock, GetLength, Close, GetChar, UnsafeBlock, STREAM, SetIndex], FileIO, PilotLoadStateOps USING [ AcquireBcd, ConfigIndex, EnumerateBcds, InputLoadState, ReleaseBcd, ReleaseLoadState], Nut USING [ CreateProc, DisplayProc, EditProc, QueryProc, Register, DefaultDisplay], NutViewer, PressFormat, Rope, Runtime USING[ IsBound], -- ShowPress USING[ CreateShowViewer ], String USING [EquivalentString, AppendChar], Strings USING [AppendSubString, SubStringDescriptor], UserExec USING [ExecHandle, DoIt], ViewerClasses USING [Viewer], ViewerOps USING [CreateViewer, FindViewer, OpenIcon, PaintViewer], ViewerTools USING [MakeNewTextViewer], Whiteboard; WhiteboardToolImpl: CEDAR PROGRAM IMPORTS BcdOps, DB, IO, Nut, NutViewer, PilotLoadStateOps, FileIO, Rope, Runtime, String, Strings, UserExec, ViewerOps, ViewerTools, Whiteboard EXPORTS Whiteboard = BEGIN OPEN DB, IO, Whiteboard; ROPE: TYPE = Rope.ROPE; Viewer: TYPE = ViewerClasses.Viewer; -- ************************ initializing domains ************************* InitTextViewer: PROC = BEGIN Nut.Register[domain: NutViewer.TextViewer, segment: $Squirrel, create: CreateTextViewer, display: NullDisplay, edit: NullEdit, query: NullQuery]; END; InitToolViewer: PROCEDURE = BEGIN Nut.Register[ domain: NutViewer.ToolViewer, segment: $Squirrel, create: CreateToolViewer, display: NullDisplay, edit: NullEdit, query: NullQuery]; InsertTools[]; END; InsertTools: PROCEDURE = BEGIN RegisterTool["Cedar Spy", "Spy", "Run Spy"]; RegisterTool["Squirrel", "Squirrel", "Squirrel"]; RegisterTool["File Tool", "FileTool", "Run FileTool"]; RegisterTool["EditTool", "EditTool", "Run EditTool"]; RegisterTool["Talker", "Talker", "Talker"]; RegisterTool["Clover", "Tsetter", "Tsetter"]; RegisterTool["Walnut", "Walnut", "Walnut"]; RegisterTool["Watch", "Watch", "Run Watch"] END; RegisterTool: PUBLIC PROCEDURE[name, impl, instructions: ROPE _ NIL] = BEGIN ENABLE DB.Error => TRUSTED { CONTINUE }; tool, bcd: Entity; tool _ DeclareEntity[Whiteboard.ToolViewer, name]; bcd _ DeclareEntity[Whiteboard.BCD, impl]; []_ SetP[tool, Whiteboard.implementor, bcd]; IF instructions # NIL THEN []_ SetP[tool, Whiteboard.comment, instructions]; END; NullDisplay: Nut.DisplayProc = {}; NullQuery: Nut.QueryProc = {}; NullEdit: Nut.EditProc = {}; -- *********************** creating entities ************************** CreateTextViewer: PUBLIC Nut.CreateProc = BEGIN IF IsAPressFile[eName] THEN TRUSTED{ --IF Runtime.IsBound[link: ShowPress.CreateShowViewer] THEN --[] _ ShowPress.CreateShowViewer[eName]; RETURN[NIL] }; v _ ViewerOps.FindViewer[eName]; IF v = NIL OR v.destroyed THEN v _ ViewerTools.MakeNewTextViewer[info: [name: eName, file: eName]]; Open[v]; RETURN[NIL]; END; IsAPressFile: PUBLIC PROCEDURE [fileName: ROPE] RETURNS [BOOLEAN _ FALSE] = TRUSTED { Byte: TYPE = [0..256); bytesPerPressRecord: CARDINAL = 512; wordsPerPressRecord: CARDINAL = 256; Block: TYPE = PACKED ARRAY [0..bytesPerPressRecord] OF Byte; -- oversize for overrun check buffer: REF Block _ NEW[Block]; unsafeBlock: IO.UnsafeBlock; ReadABlock: UNSAFE PROCEDURE = { nBytesRead: INT; buffer[bytesPerPressRecord] _ 123; nBytesRead _ stream.UnsafeGetBlock[unsafeBlock]; IF buffer[bytesPerPressRecord] # 123 THEN ERROR; -- it went too far! IF nBytesRead # bytesPerPressRecord THEN ERROR; -- should always be reading full blocks }; lengthInBytes: INT; stream: IO.STREAM; documentDirectory: LONG POINTER TO PressFormat.DDV; documentDirectory _ unsafeBlock.base _ LOOPHOLE[buffer]; unsafeBlock.startIndex _ 0; unsafeBlock.stopIndexPlusOne _ bytesPerPressRecord; stream _ FileIO.Open[fileName, read ! FileIO.OpenFailed => TRUSTED {GOTO Quit} ]; lengthInBytes _ stream.GetLength[]; IF lengthInBytes > 22 AND stream.GetChar = LOOPHOLE[0AAH, CHAR] AND stream.GetChar = LOOPHOLE[0AAH, CHAR] THEN RETURN[TRUE]; -- it looks like a PD file IF lengthInBytes = 0 OR (lengthInBytes MOD bytesPerPressRecord # 0) THEN { stream.Close[]; RETURN}; stream.SetIndex[lengthInBytes-bytesPerPressRecord]; ReadABlock[]; IF documentDirectory.Passwd # PressFormat.PressPasswd THEN { stream.Close[]; RETURN }; IF documentDirectory.nRecs # lengthInBytes/bytesPerPressRecord THEN { stream.Close[]; RETURN }; stream.Close[]; RETURN[TRUE]; EXITS Quit => {} }; CreateToolViewer: PUBLIC Nut.CreateProc = BEGIN error: ROPE _ ""; tool, module: Entity; v _ ViewerOps.FindViewer[eName]; IF v # NIL THEN {Open[v]; RETURN[NIL]}; -- load the module (cross your fingers!!) tool _ DeclareEntity[d: Whiteboard.ToolViewer, name: eName, version: OldOnly]; IF tool = NIL THEN RETURN[NIL]; module _ V2E[GetP[tool, Whiteboard.implementor]]; IF module # NIL AND ~Loaded[GetName[module]] THEN { UserExec.DoIt[Rope.Cat["Run ", GetName[module]] ! ANY => {error _ "UNCAUGHT SIGNAL"; CONTINUE}] }; -- was the load successful? IF Rope.Equal[error,""] THEN v _ ViewerOps.FindViewer[eName]; IF v # NIL THEN {Open[v]; RETURN[NIL]}; -- try to invoke the command given in the instructions IF Rope.Equal[error,""] AND module = NIL THEN error _ "No implementor defined." ELSE { instructions: ROPE = V2S[ GetP[ tool, Whiteboard.comment ] ]; IF Rope.Equal[instructions,""] THEN error _ "Loaded tool, but no viewer created" ELSE { UserExec.DoIt[instructions ! ANY => {error _ "Bad instructions"; CONTINUE}]; IF Rope.Equal[error,""] THEN v _ ViewerOps.FindViewer[eName]; IF v = NIL THEN error _ "Loaded tool, but no viewer created" ELSE { Open[v]; RETURN[NIL] } } }; -- if you get to here, then something went wrong, eg., couldn't load, no viewer created [] _ SetP[tool, Whiteboard.loadError, S2V[error]]; v _ ViewerOps.CreateViewer[flavor: $Container, info: [name: eName]]; Nut.DefaultDisplay[tool, v, seg]; RETURN[NIL]; END; Loaded: PUBLIC PROCEDURE[module: ROPE] RETURNS[loaded: BOOLEAN] = TRUSTED BEGIN OPEN PilotLoadStateOps; temp: STRING _ [30]; modName: STRING _ [30]; EachConfig: PROC[ci: ConfigIndex] RETURNS [BOOLEAN] = TRUSTED BEGIN FindModule: PROC [mth: BcdOps.MTHandle, mti: BcdDefs.MTIndex] RETURNS [BOOLEAN] = TRUSTED { GetNameString[bcdns, mth.name, temp]; loaded _ String.EquivalentString[modName, temp]; RETURN[loaded]}; FindConfig: PROC [cth: BcdOps.CTHandle, cti: BcdDefs.CTIndex] RETURNS [BOOLEAN] = TRUSTED { GetNameString[bcdns, cth.name, temp]; loaded _ String.EquivalentString[modName, temp]; RETURN[loaded]}; bcd: BcdOps.BcdBase _ AcquireBcd[ci]; bcdns: BcdOps.NameString _ LOOPHOLE[bcd + bcd.ssOffset]; [] _ BcdOps.ProcessModules[bcd, FindModule]; IF ~loaded THEN [] _ BcdOps.ProcessConfigs[bcd, FindConfig]; ReleaseBcd[bcd]; RETURN[loaded]; END; -- main code loaded _ FALSE; FOR i: INT IN [0..MIN[30, Rope.Length[module]]) DO String.AppendChar[modName, Rope.Fetch[base: module, index: i]] ENDLOOP; [] _ InputLoadState[]; [] _ EnumerateBcds[recentfirst, EachConfig]; -- sets 'loaded' ReleaseLoadState[]; END; GetNameString: PROC[ssb: BcdOps.NameString, n: BcdDefs.NameRecord, name: STRING] = TRUSTED BEGIN ssd: Strings.SubStringDescriptor; ssd _ [base: @ssb.string, offset: n, length: MIN[ssb.size[n], 100]]; name.length _ 0; Strings.AppendSubString[name, @ssd]; END; ExtractName: PUBLIC PROCEDURE[name: ROPE] RETURNS[ROPE] = BEGIN pos: INTEGER; pos _ Rope.Find[name, ": "]; IF pos < 0 THEN pos _ 0 ELSE pos _ pos + 2; RETURN[Rope.Substr[name, pos, Rope.Length[name]-pos-11]]; -- remove the " (Squirrel)" too END; Open: PROCEDURE[viewer: Viewer] = INLINE BEGIN IF viewer.iconic THEN ViewerOps.OpenIcon[viewer] ELSE ViewerOps.PaintViewer[viewer, all]; END; InitTextViewer[]; InitToolViewer[]; InsertTools[] END. Change Log Cattell August 11, 1982 12:23 pm: Removed StartTrap call, want to selectively start up whiteboards. Also make GetIconInfo recover gracefully if icon relation has been deleted or not initialized. Cattell October 11, 1982 9:29 pm: GetIcon must catch MultipleMatch on GetEntityByName, because there may be more than one sub-type of the domain; in this case just use nut icon. ÊV˜J•StartOfExpansion [base: ROPE, index: INT _ 0]š^Ïc+œ(œ)œDœÏk œ žœ,žœPžœžœvžœžœžœxžœqžœ¤žœ!žœ-žœ6žœ'žœžœDžœ;žœžœžœžœžœžœžœžœžœžœžœžœžœ žœMœÏnœžœ žœ¡žœŸœž œžœÁžœŸ œž œžœÜ˜®Jšœ‹˜‹J–[link: UNSPECIFIED]š[œ2žœŸ œžœž œžœžœžœžœžœ žœžœužœ?žœžœžœ8žœŸ œŸ œŸœIœžœžœžœžœžœzžœžœ.žœžœžœžœWžœžœžœŸ œžœž œ žœžœžœžœžœ žœ$žœžœ˜Ì š œ žœžœžœžœ˜]Jšœžœ žœ˜Jšœ žœ ˜šŸ œžœž œ˜ Jšœ žœ˜J˜"J˜0Jšžœ#žœžœ˜DJšžœ"žœžœ'˜WJ˜—Jšœžœ˜Jšœž œ˜Jš œžœžœžœ žœ˜3Jšœ'žœ ˜8J˜J˜3˜%Jšœžœžœ˜(J˜—J˜#Jšžœžœžœžœžœžœžœžœžœžœ˜—Jš žœžœžœžœžœ˜eJ˜3J˜ Jšžœ4žœžœ˜VJšžœ=žœžœ˜`Jšœžœžœ˜Jšžœ ˜Jšýœžœžœ žœJžœžœžœ žœžœ*œWžœžœžœžœžœ=žœ žœžœžœ@žœ žœ œžœžœ'žœžœžœ žœžœ7œžœžœ žœ žœ*žœžœ6žœžœ8žœ+žœ!žœ žœžœ'žœžœžœ3žœ žœžœ YœªžœžœžœŸœžœž œ žœžœ žœžœžœžœžœžœ Ÿ œžœžœžœžœžœŸ œžœ6žœžœžœ|žœŸ œžœ6žœžœžœ|žœZžœQžœ žœMžœžœ œžœžœžœžœžœžœGžœPœžœŸ œžœ6žœžœžœVžœTžœŸ œžœž œžœžœžœžœ žœ'žœ žœ žœžœ4 œžœŸœž œžœžœžœžœ#žœ)žœ9žœ‡˜÷——…—#Ä)