DIRECTORY Convert USING [CardFromRope, Error], CountedVM USING [SimpleAllocate, Free, Handle], FS USING [Open, OpenFile, Close, Error, Read], IO, MessageFileFormat USING [Domain, FileHeader, Segment, TextEntry], NSString USING [nullString, String], PrincOps USING [wordsPerPage], PrincOpsUtils USING [LongCopy], Rope USING [FromRefText, Length, ROPE, ToRefText], VM USING [PageCount, WordsForPages], XMessage USING [ClientData, DestroyMsgsProc, ErrorType, Messages, MsgDomains, MsgKey, MsgKeyList, StringArray], XMessagePrivate USING [FileInfo, FileInfoObject, Object]; XMessageImpl: PROGRAM IMPORTS Convert, CountedVM, FS, IO, PrincOpsUtils, Rope, VM EXPORTS XMessage = BEGIN OPEN XMessage, MFF: MessageFileFormat; ROPE: TYPE ~ Rope.ROPE; STREAM: TYPE ~ IO.STREAM; initialHeapPages: CARDINAL = 4; heapIncrement: CARDINAL = 4; swapUnitSize: CARDINAL = 4; leftAngleChar: REF TEXT = "<"; rightAngleChar: REF TEXT = ">"; Handle: TYPE = REF Object; Object: PUBLIC TYPE = XMessagePrivate.Object; Error: PUBLIC ERROR [type: ErrorType] = CODE; AllocateMessages: PUBLIC SAFE PROCEDURE [applicationName: NSString.String, maxMessages: CARDINAL, clientData: ClientData, proc: DestroyMsgsProc] RETURNS [Handle] = TRUSTED BEGIN h: REF rawData Object; h _ NEW[Object.rawData[maxMessages]]; h.proc _ proc; h.clientData _ clientData; FOR i: CARDINAL IN [0..maxMessages) DO h.array[i] _ NSString.nullString; ENDLOOP; RETURN[h]; END; DestroyMessages: PUBLIC SAFE PROCEDURE [h: Handle] = TRUSTED {IF h.proc # NIL THEN h.proc[h.clientData]; WITH hh: h SELECT FROM rawData => {FOR i: CARDINAL IN [0..hh.maxMsgIndex) DO hh.array[i] _ NIL ENDLOOP}; file => {}; ENDCASE; }; Decompose: PUBLIC SAFE PROCEDURE [source: NSString.String] RETURNS [args: REF StringArray] = TRUSTED {RETURN[NIL]}; -- of Decompose Compose: PUBLIC SAFE PROCEDURE [source: NSString.String, args: REF StringArray] RETURNS [destination: NSString.String] = TRUSTED { destination _ ComposeToFormatHandle[source, args]}; ComposeOne: PROCEDURE [source: NSString.String, arg: NSString.String] RETURNS [destination: NSString.String] = TRUSTED { args: REF StringArray _ NEW[StringArray[1]]; args.data[0] _ arg; destination _ ComposeToFormatHandle[source, args]}; ComposeToFormatHandle: PROCEDURE [source: NSString.String, args: REF StringArray] RETURNS [destination: NSString.String] = { TokenProc: IO.BreakProc = TRUSTED BEGIN IF char = tokenChar THEN RETURN [sepr] ELSE RETURN [other]; END; tokenChar, c: CHAR; front: ROPE; argIndex, index, length: CARDINAL _ 0; sourceRope: ROPE _ Rope.FromRefText[source]; noNumber: BOOLEAN; inS: STREAM _ IO.RIS[sourceRope]; outS: STREAM _ IO.ROS[]; IF Rope.Length[sourceRope] = 0 THEN Error[invalidString]; IF args = NIL THEN Error[notEnoughArguments]; UNTIL IO.EndOf[inS] DO tokenChar _ '<; front _ IO.GetTokenRope[inS, TokenProc].token; [] _ IO.GetChar[inS]; -- Get rid of the < IO.PutRope[outS, front]; IF ~IO.EndOf[inS] THEN { tokenChar _ '>; front _ IO.GetTokenRope[inS, TokenProc].token; c _ IO.GetChar[inS]; IF c = '> THEN { noNumber _ FALSE; argIndex _ Convert.CardFromRope[front ! Convert.Error => {noNumber _ TRUE; CONTINUE}]; IF noNumber THEN {IO.PutChar[outS, '<]; IO.PutRope[outS, front]; IO.PutChar[outS, '>]} ELSE IO.PutText[outS, args.data[argIndex - 1]]; } ELSE IO.PutRope[outS, front]; }; ENDLOOP; RETURN[Rope.ToRefText[IO.RopeFromROS[outS]]]; }; Get: PUBLIC SAFE PROCEDURE [h: Handle, msgKey: MsgKey] RETURNS [msg: NSString.String] = TRUSTED {RETURN GetInternal[h, msgKey]}; GetList: PUBLIC SAFE PROCEDURE [h: Handle, msgKeys: REF MsgKeyList, msgs: REF StringArray] = TRUSTED BEGIN IF msgKeys = NIL THEN Error[invalidMsgKeyList]; IF msgs = NIL THEN Error[invalidStringArray]; IF msgKeys.length # msgs.length THEN Error[arrayMismatch]; FOR i: CARDINAL IN [0..msgKeys.length) DO msgs[i] _ GetInternal[h, msgKeys[i]] ENDLOOP END; -- of GetList RegisterMessages: PUBLIC SAFE PROCEDURE [h: Handle, messages: REF Messages, stringBodiesAreReal: BOOLEAN] = TRUSTED BEGIN IF messages = NIL THEN Error[notEnoughArguments]; WITH hh: h SELECT FROM rawData => { FOR i: CARDINAL IN [0..messages.length) DO hh.array[messages[i].msgKey] _ messages[i].msg; ENDLOOP}; ENDCASE => ERROR Error[invalidMsgKeyList]; END; -- of RegisterMessages MessagesFromReference: PUBLIC SAFE PROCEDURE [file: ROPE, clientData: ClientData, proc: DestroyMsgsProc] RETURNS [msgDomains: REF MsgDomains] = TRUSTED { fileHandle: FS.OpenFile = FS.Open[file ! FS.Error => GOTO Out]; RETURN [MessagesFromFileHandle[fileHandle, clientData, proc]]; EXITS Out => RETURN[NIL]}; GetInternal: PROCEDURE [h: Handle, msgKey: MsgKey] RETURNS [NSString.String] = BEGIN WITH hh: h SELECT FROM rawData => RETURN[hh.array[msgKey]]; file => { text: LONG POINTER TO MessageFileFormat.TextEntry = @hh.textBase[ hh.domain[hh.messageTable][msgKey]]; rt: REF TEXT _ NEW[TEXT[text.maxLength]]; PrincOpsUtils.LongCopy[ from: LOOPHOLE[LOOPHOLE[text, LONG POINTER] + SIZE[MessageFileFormat.TextEntry]], nwords: text.length/2, to: LOOPHOLE[LOOPHOLE[rt, LONG POINTER] + SIZE[TEXT[0]]]]; RETURN[rt]}; pilotFile => { text: LONG POINTER TO MessageFileFormat.TextEntry = @hh.textBase[ hh.domain[hh.messageTable][msgKey]]; rt: REF TEXT _ NEW[TEXT[text.maxLength]]; PrincOpsUtils.LongCopy[ from: LOOPHOLE[LOOPHOLE[text, LONG POINTER] + SIZE[MessageFileFormat.TextEntry]], nwords: text.length/2, to: LOOPHOLE[LOOPHOLE[rt, LONG POINTER] + SIZE[TEXT[0]]]]; RETURN[rt]}; ENDCASE => ERROR Error[invalidMsgKeyList]; END; FreeMsgDomainsStorage: PUBLIC SAFE PROCEDURE [msgDomains: REF XMessage.MsgDomains] = TRUSTED {}; MessagesFromFileHandle: PROCEDURE [file: FS.OpenFile, clientData: ClientData, proc: DestroyMsgsProc] RETURNS [msgDomains: REF MsgDomains] = TRUSTED { header: MFF.FileHeader; cvmH: CountedVM.Handle _ CountedVM.SimpleAllocate[VM.WordsForPages[1]]; nSegments, nPages: CARDINAL; fileInfo: XMessagePrivate.FileInfo; domainSeq: REF MsgDomains; header _ LOOPHOLE[cvmH.pointer]; FS.Read[file: file, from: 0, nPages: 1, to: header]; nSegments _ header.nSegments; nPages _ PagesForHeader[nSegments]; IF nPages # 1 THEN { CountedVM.Free[cvmH]; cvmH _ CountedVM.SimpleAllocate[VM.WordsForPages[nPages]]; header _ LOOPHOLE[cvmH.pointer]; FS.Read[file: file, from: 0, nPages: nPages, to: header]; }; fileInfo _ NEW[XMessagePrivate.FileInfoObject _ [stuff: cvmH, nDomains: nSegments]]; domainSeq _ NEW[MsgDomains[nSegments]]; FOR i: CARDINAL IN [0..nSegments) DO pageCnt: VM.PageCount _ header.segments[i].count; cvmHandel: CountedVM.Handle _ CountedVM.SimpleAllocate[VM.WordsForPages[pageCnt]]; domain: MessageFileFormat.Domain _ -- LONG BASE POINTER TO DomainHeader -- LOOPHOLE[cvmHandel.pointer]; h: REF Object.file _ NEW[Object.file _ [ proc: proc, clientData: clientData, body: file[fileInfo: fileInfo, cvmH: cvmHandel, domain: domain, textBase: @domain[domain.textTable], messageTable: domain.messageTable]]]; text: LONG POINTER TO MessageFileFormat.TextEntry = @h.textBase[domain.domainName]; nsString: REF TEXT _ NEW[TEXT[text.length]]; FS.Read[file: file, from: header.segments[i].base, nPages: header.segments[i].count, to: domain]; FOR j: CARDINAL IN [0 .. text.length) DO nsString[i] _ LOOPHOLE[text.bytes[i]]; ENDLOOP; nsString.length _ text.length; domainSeq.data[i] _ [handle: h, applicationName: nsString]; ENDLOOP; FS.Close[file]; RETURN[domainSeq]}; PagesForHeader: PROCEDURE [nSegments: CARDINAL] RETURNS [CARDINAL] = INLINE { wpp: CARDINAL = PrincOps.wordsPerPage; RETURN[(MFF.FileHeader.SIZE + nSegments * MFF.Segment.SIZE + wpp - 1) / wpp]}; END. -- of MessageImpl 30-May-84 16:24:48 - Saund - Reduced initial Heap size from 64 to 4 pages. 7-Jun-84 15:15:52 - Sandman - Remove unused stuff. 23-Jul-84 11:42:42 - Sandman - Make Compose not alter source arg and use 1 relative indexing on args. 25-Jan-85 15:04:08 - Sandman - Implement message file stuff. 30-May-85 16:23:01 - McManis - Comment out MessageFromFile because services cannot use it and there is a conflict of Catalog with NSFile. 12-Sep-85 14:46:09 - McManis - Added check for NIL proc in DestroyMessages. 14-Oct-85 15:30:41 - McManis - Added pilotFile to SELECT in Get to allow messages to be retrieved from pilotFiles. tXMessageImpl.mesa Copyright Σ 1984, 1985, 1986, 1987 by Xerox Corporation. All rights reserved. Tim Diebert: January 6, 1987 5:21:16 pm PST leftAngleChar: XChar.Character = XCharSet0.Make[lessThan]; rightAngleChar: XChar.Character = XCharSet0.Make[greaterThan]; PROC [char: CHAR] RETURNS [CharClass]; << This proc is commented out because it depends on the BWS file structure which is not available in services. MessagesFromFile: PUBLIC SAFE PROCEDURE [ fileName: LONG STRING, clientData: ClientData, proc: DestroyMsgsProc] RETURNS [msgDomains: XMessage.MsgDomains] = TRUSTED { rb: XString.ReaderBody _ XString.FromSTRING[fileName]; fileHandle: NSFile.Handle = Catalog.GetFile[name: @rb, readonly: TRUE]; RETURN MessagesFromFileHandle[fileHandle, clientData, proc]};>> -- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- PRIVATE OPERATIONS : -- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- DomainSeq: TYPE = REF DomainSeqRecord; DomainSeqRecord: TYPE = RECORD [data: SEQUENCE length: CARDINAL OF XMessage.MsgDomain]; MsgDomain: TYPE = RECORD [applicationName: NSString.String, handle: Handle]; domainSeq: DomainSeq; header _ NSSegment.Map[ origin: [count: 1, base: 0, file: file], access: NSFile.readAccess].pointer; [] _ Space.Unmap[header]; header _ NSSegment.Map[ origin: [count: nPages, base: 0, file: file], access: NSFile.readAccess].pointer domain: MessageFileFormat.Domain _ NSSegment.Map[ origin: [count: header.segments[i].count, base: header.segments[i].base, file: file], access: NSFile.readAccess].pointer; header _ Space.Unmap[header]; RETURN[DESCRIPTOR[domainSeq, nSegments]]}; Κ έ˜codešœ™KšœO™OK™+—K˜K˜šΟk ˜ Kšœœ˜$Kšœ œ ˜/Kšœœ&˜.Kšœ˜Kšœœ*˜AKšœ œ˜$Kšœ œ˜Kšœœ ˜Kšœœœ ˜2Kšœœ˜$Kšœ œa˜oKšœœ$˜9—K˜šΟn œ˜Kšœœœ˜;Kšœ ˜Kšœ˜—˜Kšœœ œ˜,—˜Kšœœœ˜Kšœœœœ˜—˜Kšœœ˜Kšœœ˜Kšœœ˜K™:K™>Kšœœœ˜Kšœœœ˜—˜Kšœœœ˜Kšœœœ˜-—˜Kšžœœœœ˜-—˜šžœœœ œ1œ1œ œ˜±Kšœœ˜Kšœœ˜%K˜)šœœœ˜&Kšœ"œ˜*—Kšœ˜ Kšœ˜——˜š žœœœ œœ˜=Kšœœ œœ˜+šœœ˜šœ œœœ˜5Kšœ˜Kšœ˜ —Kšœ ˜ Kšœ˜—Kšœ˜——˜Kšž œœœ œœœœœœΟc˜„—˜šžœœœ œ!œœ"œ˜‚Kšœ3˜3——˜šž œ œ1œ"œ˜xKšœœœ˜,K˜Kšœ3˜3K˜—K˜šžœ œ!œœ#˜|šž œœ œ˜'Kšœœœ ™&Kš œœœœœ ˜;Kšœ˜—Kšœœ œ˜ Kšœœ˜&Kšœ œ˜,Kšœ œ˜Kšœœœœ ˜!Kšœœœœ˜Kšœœ˜9Kšœœœ˜-K˜šœœ ˜Kšœ˜Kšœœ$˜.KšœœŸ˜*Kšœ˜šœœ œ˜Kšœ˜Kšœœ$˜.Kšœœ˜šœ˜ šœ˜Kšœ œ˜šœ%˜%Kšœœœ˜0—Kšœ ˜ Kšœœœœ˜JKšœœ(˜/K˜—Kšœœ˜—K˜—Kš˜—Kšœœ˜-Kšœ˜K˜——˜šžœœ˜6Kšœœœ˜I——˜šžœœœ œœœœ˜jKšœ œœ˜/Kšœœœ˜-Kšœœ˜:šœœœ˜)Kšœ%˜,—KšœŸ ˜——˜šžœœœ œœ œœ˜yKšœ œœ˜1šœœ˜˜ šœœœ˜*Kšœ/˜/Kšœ˜ ——Kšœœ˜*—KšœŸ˜——˜Kšœ8œ3™n—™šžœœ™)Kšœ œœ0™EKšœ.™5K™6KšœAœ™GKšœ9™?——˜šžœœœ œœ1œœœ˜™Kš œ œ œ œ œ˜?Kšœ8˜>Kšœœœ˜——˜KšœI™IKšœ™KšœI™I—˜šž œ œœ˜Tšœœ˜Kšœ œ˜$˜ šœœœœ,˜AK˜$—Kš œœœœœ˜)šœ˜Kš œœœœœœ˜QKšœ˜Kš œœœœœœœ˜:—Kšœ˜ —˜šœœœœ,˜AK˜$—Kš œœœœœ˜)šœ˜Kš œœœœœœ˜QKšœ˜Kš œœœœœœœ˜:—Kšœ˜ —Kšœœ˜*—Kšœ˜——˜Kšœ œœ™&Kš œœœœ œœ™WKšœ œœ4™L—˜Kš žœœœ œœœ˜`—˜š žœ œœ:œœœ˜•Kšœœ ˜KšœG˜GKšœœ˜K˜#Kšœ œ ˜K™Kšœ œ˜ K•StartOfExpansionE[file: FS.OpenFile, from: INT, nPages: INT, to: LONG POINTER]šœ2˜4™K™L—K˜K˜#šœ œ˜Kšœ˜Kšœ:˜:K™Kšœ œ˜ K–E[file: FS.OpenFile, from: INT, nPages: INT, to: LONG POINTER]šœ7˜9™K™.K™"—K˜—Kšœ œF˜TKšœ œ˜'šœœœ˜$Kšœ œ&˜1Kšœ7œ˜Ršœ#Ÿ'˜JKšœ˜—™1K™UK™#—šœœœ˜(K˜#Kšœd˜dK˜%—Kšœœœœ>˜SKš œ œœœœ˜,K–E[file: FS.OpenFile, from: INT, nPages: INT, to: LONG POINTER]šœ_˜ašœœœ˜(Kšœœ˜&Kšœ˜—Kšœ˜Kšœ;˜;Kšœ˜—K™Kšœ ˜Kšœ œ™*Kšœ ˜——˜š žœ œ œœœœ˜MKšœœ˜&Kš œœ œœ œ˜N——˜KšœŸ˜—˜JK˜2—K˜eK˜