DIRECTORY Rope USING [ROPE, MaxLen, Substr, Length, Fetch, Find, Cat], BasicTime USING [GMT], IO USING [STREAM, PutF, PutFR, rope], FileReader USING [FromStream], FS USING [FileInfo, Error, StreamOptions, defaultStreamOptions, StreamOpen], FSBackdoor USING [RemoteEvent, NextRemoteEvent], Commander USING [CommandProc, Register], Convert USING [RopeFromTime], CommandTool USING [ArgumentVector, Parse, Failed], Process USING [Detach, SetPriority, priorityBackground], TiogaAccess USING [FromFile, Reader, TiogaChar, Get], VoiceRope USING [Retain, VoiceRopeInterval], Atom USING [PropList], VoiceInText USING [thrushHandle]; VoiceInterestImpl: CEDAR PROGRAM IMPORTS Rope, IO, FileReader, FS, FSBackdoor, Commander, Convert, CommandTool, Process, TiogaAccess, VoiceRope, VoiceInText = BEGIN LocalFile: ERROR; backgroundCommentary: IO.STREAM _ NIL; lastRemoteEvent: REF READONLY FSBackdoor.RemoteEvent _ NIL; MonitorCopiesToGlobal: PROC = { -- invoked as a separate process Process.SetPriority[Process.priorityBackground]; DO lastRemoteEvent _ FSBackdoor.NextRemoteEvent[lastRemoteEvent]; IF lastRemoteEvent.op = endStoring THEN RegisterInterest[lastRemoteEvent.fName, backgroundCommentary] ENDLOOP }; RegisterInterest: PROC [file: Rope.ROPE, commentary: IO.STREAM _ NIL] = { fullFName, attachedTo, globalName: Rope.ROPE; keep: CARDINAL; voiceList: Rope.ROPE _ NIL; createDate: BasicTime.GMT; Commentate: PROC [remark: Rope.ROPE] = { IF commentary # NIL THEN commentary.PutF[remark] }; [fullFName: fullFName, attachedTo: attachedTo, keep: keep, created: createDate] _ FS.FileInfo[file]; -- read FS.Mesa to understand the next few lines Commentate[IO.PutFR["File %g:\n", IO.rope[fullFName]]]; IF attachedTo = NIL THEN { IF keep # 0 THEN ERROR LocalFile[] -- neither a global file or a local one with global attachment ELSE { globalName _ fullFName; Commentate["File is global:\n"] } } ELSE { globalName _ attachedTo; Commentate[IO.PutFR["File is attached to global file %g:\n", IO.rope[globalName]]] }; { fileStream: IO.STREAM; streamOptions: FS.StreamOptions _ FS.defaultStreamOptions; tiogaFile: BOOLEAN; streamOptions[tiogaRead] _ FALSE; fileStream _ FS.StreamOpen[fileName: fullFName, streamOptions: streamOptions]; [tiogaFile: tiogaFile] _ FileReader.FromStream[fileStream, LAST[INT]]; IF ~tiogaFile THEN { Commentate[" Not a tioga file\n"]; RETURN } }; { fileStream: TiogaAccess.Reader _ TiogaAccess.FromFile[fullFName]; rootChar: TiogaAccess.TiogaChar _ TiogaAccess.Get[fileStream]; -- first character produces the root properties FOR rootProps: Atom.PropList _ rootChar.propList, rootProps.rest WHILE rootProps # NIL DO IF rootProps.first.key = $voicelist THEN { IF voiceList = NIL THEN voiceList _ NARROW[rootProps.first.val, Rope.ROPE] ELSE ERROR } ENDLOOP }; IF voiceList = NIL THEN { Commentate[" No voice in file\n"]; RETURN }; Commentate[" Voice message IDs are\n"]; { nextVoice: Rope.ROPE; startOfID: INT _ 1; endOfID: INT; IF NOT ( voiceList.Length > 0 AND voiceList.Fetch[0] = '& ) THEN ERROR; DO endOfID _ voiceList.Find["&", startOfID]; nextVoice _ voiceList.Substr[startOfID, IF endOfID = -1 THEN Rope.MaxLen ELSE endOfID - startOfID]; IF nextVoice.Length = 0 THEN ERROR; VoiceRope.Retain[handle: VoiceInText.thrushHandle, voiceRope: NEW [VoiceRope.VoiceRopeInterval _ [nextVoice, 0, 0]], refID: globalName.Cat[" ", Convert.RopeFromTime[createDate]], refIDType: "TiogaVoice"]; Commentate[nextVoice]; Commentate["\n"]; IF endOfID = -1 THEN EXIT; startOfID _ endOfID + 1 ENDLOOP } }; RegisterVoiceInterest: Commander.CommandProc = { { ENABLE { FS.Error => IF error.group # user THEN REJECT ELSE {msg _ error.explanation; GOTO Quit}; LocalFile => {msg _ "File must be global or have a global attachment"; GOTO Quit}; }; argv: CommandTool.ArgumentVector; argv _ CommandTool.Parse[cmd ! CommandTool.Failed => {msg _ errorMsg; GOTO Quit}]; IF argv.argc # 2 THEN { msg _ "Usage: RegisterVoiceInterest inFile"; GOTO Quit; }; RegisterInterest[argv[1], cmd.out] EXITS Quit => RETURN [$Failure, msg] }}; backgroundCommentaryInit: Commander.CommandProc = { backgroundCommentary _ cmd.out }; p: PROCESS _ FORK MonitorCopiesToGlobal; TRUSTED {Process.Detach[p]}; Commander.Register[key: "RegisterVoiceInterest", proc: RegisterVoiceInterest, doc: "RegisterVoiceInterest inFile: register loganberry interests for all voice messages in a global or globally attached file"]; Commander.Register[key: "InterestInfo", proc: backgroundCommentaryInit, doc: "InterestInfo: registers an output stream for commentary about voice interest registration"] END. 2VoiceInterestImpl.mesa a mechanism to track all files copied to global file space and register interest in any voice contained in them, plus a command to register interests in any voice found in a named file [which must be global or with global attachment: the interest is registered for the global name] Ades, April 14, 1986 3:11:27 pm PST the code is very inefficient in the way that it deals with files: it opens the file as a stream to see if it is a tioga file and then gets a TiogaAccess.Reader on each tioga file, which means making a complete copy of the file into TiogaAccess.Reader format, and then reads its root properties faster code could be produced by using the 'control' rope reader returned by FileReader.FromStream but that means writing fairly grubby code that knows a lot about the tioga file format [see FileOps.mesa in tioga.df if interested] in order to determine if some file is a tioga file, we need to open it as a plain file [hence following line] and use FileReader.FromStream to determine whether it is of the correct format. FromStream also returns the text, comments and control sections of the documents if we are interested [see comments at the head of this code] the voiceRope specification in this procedure call is only used to extract the RopeID - the start and length are not used ΚΘ˜™™™J™#J™—J™₯Icode™Jšœζ™ζJ™—šΟk ˜ Jšœœœ,˜˜>Jšœ!œ>˜e—Jš˜—J˜J˜š žœœ œœœœ˜IJšœ(œ˜-Jšœœ˜Jšœœœ˜Jšœœ˜J˜Jš ž œœœœœœ˜\J˜JšœSœŸ0˜–Jšœ7˜7Jšœ˜Jšœ˜šœœ œœ Ÿ>˜dJšœ<˜@—J˜Jšœ'œ0œ˜uJ˜šœœœ˜Jšœ:˜:J˜J˜JšœΛ™ΛJšœ!˜!Jšœ œ?˜NJšœF˜FJšœœ˜šœ'˜'J˜—J˜—J˜J˜šœD˜DJšœ?Ÿ/˜nšœ>œ œ˜YJšœ"œœ œœ œœœœ˜‚—Jš˜—J˜J˜Jšœ œ˜Jšœ˜šœ'˜'Jš˜—J˜J˜)J˜šœœ˜Jšœ œ˜Jšœ œ˜ Jš œœœœœ˜GJ˜š˜J˜*Jšœ(œœ œ˜cJšœœœ˜#J˜Jšœy™yJšœΝ˜ΝJšœ(˜(J˜Jšœœœ˜J˜—Jš˜—J˜—J˜J˜J˜šœ0˜0J˜šœ˜Jš œ œœœœœ˜XJšœGœ˜R—J˜J˜Jšœ!˜!JšœFœ˜Ršœœ˜Jšœ,˜,Jšœ˜ J˜—Jšœ"˜"š˜Jšœœ˜——J˜J˜šœU˜UJ˜—Jšœœœ˜(šœ˜J˜—JšœΟ˜ΟJ˜šœ©˜©J˜—Jšœ˜—…—τξ