<> <> <> <> <> <> <> <> <> DIRECTORY Ascii USING [CR, SP, TAB], FS USING [defaultStreamOptions, Open, OpenFile, StreamFromOpenFile, StreamOpen, StreamOptions], IO USING [Close, PutRope, SetIndex, SetLength, STREAM], Rope USING [Concat, Fetch, FromChar, FromProc, InlineSize, MaxLen, Replace, ROPE, Size, Substr], RopeEdit USING [CharPropertyTable], RopeFile USING [FromStream], RopeIO USING [], RopePrivate USING [InlineDepth]; RopeEditImpl: CEDAR PROGRAM IMPORTS FS, IO, Rope, RopePrivate, RopeFile EXPORTS RopeEdit, RopeIO SHARES Rope = BEGIN OPEN RopeEdit; ROPE: TYPE = Rope.ROPE; MaxLen: INT = Rope.MaxLen; Depth: PUBLIC PROC [rope: ROPE] RETURNS [depth: INTEGER] = { RETURN [RopePrivate.InlineDepth[rope]] }; <> Substr: PUBLIC PROC [base: ROPE, start: INT _ 0, len: INT _ MaxLen] RETURNS [ROPE] = { RETURN [Rope.Substr[base: base, start: start, len: len]]; }; Concat: PUBLIC PROC [base, rest: ROPE, baseLen, restLen: INT _ MaxLen] RETURNS [new: ROPE] = { IF Rope.Size[rest] > restLen THEN rest _ Rope.Substr[base: rest, start: 0, len: restLen]; IF Rope.Size[base] > baseLen THEN rest _ Rope.Substr[base: base, start: 0, len: baseLen]; RETURN [Rope.Concat[base, rest]]; }; Copy: PUBLIC PROC [dest: ROPE, destLoc: INT, source: ROPE, start: INT, len: INT, destSize: INT] RETURNS [ROPE] = { IF destLoc > destSize THEN destLoc _ destSize; RETURN [ Replace[base: dest, start: destLoc, len: 0, replace: Substr[source, start, len], baseSize: destSize, repSize: len] ] }; Delete: PUBLIC PROC [base: ROPE, start, len, baseSize: INT] RETURNS [ROPE] = { RETURN [Replace[base, start, len, NIL, baseSize, 0]]; }; Insert: PUBLIC PROC [dest: ROPE, destLoc: INT _ 0, source: ROPE, destSize, sourceSize: INT _ MaxLen] RETURNS [ROPE] = { RETURN [Replace[dest, destLoc, 0, source, destSize, sourceSize]]; }; AppendChar: PUBLIC PROC [base: ROPE, char: CHAR, baseSize: INT _ MaxLen] RETURNS [ROPE] = { RETURN [ReplaceByChar[base, char, MaxLen, 0, baseSize]]; }; InsertChar: PUBLIC PROC [base: ROPE, char: CHAR, loc: INT _ 0, baseSize: INT _ MaxLen] RETURNS [ROPE] = { RETURN [ReplaceByChar[base, char, loc, 0, baseSize]]; }; <<**** IO Operations ****>> PutRope: PUBLIC PROC [stream: IO.STREAM, rope: ROPE] = { IO.PutRope[stream, rope]; }; GetRope: PUBLIC PROC [stream: IO.STREAM, len: INT _ MaxLen] RETURNS [ROPE] = { RETURN [RopeFile.FromStream[stream, 0, len]]; }; <<**** Filing Operations ****>> ToFile: PUBLIC PROC [fileName, rope: ROPE, start: INT _ 0] = { WriteFile[FS.StreamOpen[fileName, $create], rope, start]; }; ToFileC: PUBLIC PROC [openFile: FS.OpenFile, rope: ROPE, start: INT _ 0] = { WriteFile[FS.StreamFromOpenFile[openFile, $write], rope, start]; }; WriteFile: PROC [stream: IO.STREAM, rope: ROPE, start: INT] = { IO.SetLength[stream, start]; IO.SetIndex[stream, start]; PutRope[stream, rope]; IO.Close[stream]; }; FromFile: PUBLIC PROC [fileName: ROPE, start: INT _ 0, len: INT _ MaxLen] RETURNS [ROPE] = { openFile: FS.OpenFile ~ FS.Open[fileName, $read]; RETURN[FromFileC[openFile, start, len]]; }; BufferStrategyProc: TYPE ~ PROC [len: INT] RETURNS [ pagesPerStreamBuffer: INT, streamBuffers: INT, ropeBufSize: INT, ropeBuffers: INT ]; BufferStrategy: BufferStrategyProc _ DefaultBufferStrategy; <> DefaultBufferStrategy: BufferStrategyProc ~ { pagesPerStreamBuffer _ defaultPagesPerStreamBuffer; streamBuffers _ defaultStreamBuffers; ropeBufSize _ defaultRopeBufSize; ropeBuffers _ defaultRopeBuffers; }; <> defaultPagesPerStreamBuffer: NAT _ 4; defaultStreamBuffers: NAT _ 2; defaultRopeBufSize: NAT _ 512; defaultRopeBuffers: NAT _ 4; FromFileC: PUBLIC PROC [openFile: FS.OpenFile, start: INT _ 0, len: INT _ MaxLen] RETURNS [ROPE] = { stream: IO.STREAM; pagesPerStreamBuffer: INT; streamBuffers: INT; ropeBufSize: INT; ropeBuffers: INT; options: FS.StreamOptions _ FS.defaultStreamOptions; options[tiogaRead] _ FALSE; -- include the formatting information options[closeFSOpenFileOnClose] _ FALSE; -- don't close the openFile [pagesPerStreamBuffer, streamBuffers, ropeBufSize, ropeBuffers] _ BufferStrategy[len]; stream _ FS.StreamFromOpenFile[ openFile: openFile, accessRights: $read, streamOptions: options, streamBufferParms: [vmPagesPerBuffer: pagesPerStreamBuffer, nBuffers: streamBuffers] ]; RETURN [RopeFile.FromStream[stream: stream, start: start, len: len, bufSize: ropeBufSize, buffers: ropeBuffers]]; }; <<***** Replace Operations>> ReplaceByChar: PUBLIC PROC [base: ROPE, char: CHAR, start: INT, len: INT, baseSize: INT] RETURNS [new: ROPE] = { new _ Replace[base: base, start: start, len: len, replace: Rope.FromChar[char], baseSize: baseSize, repSize: MaxLen]; }; ReplaceByTEXT: PUBLIC PROC [base: ROPE, text: REF READONLY TEXT, textStart: NAT, textSize: NAT, start: INT, len: INT, baseSize: INT] RETURNS [new: ROPE _ NIL] = { Chars: PROC RETURNS [CHAR] ~ {c: CHAR _ text[i]; i _ i + 1; RETURN [c]}; i: NAT _ textStart _ MIN[text.length, textStart]; textSize _ MIN[text.length-textStart, textSize]; IF baseSize < Rope.InlineSize[base] THEN base _ Rope.Substr[base, 0, baseSize]; new _ Rope.Replace[base, start, len, Rope.FromProc[textSize, Chars]]; }; Replace: PUBLIC PROC [base: ROPE, start: INT, len: INT, replace: ROPE, baseSize: INT, repSize: INT] RETURNS [new: ROPE] = { IF baseSize < Rope.Size[base] THEN base _ Rope.Substr[base: base, start: 0, len: baseSize]; IF repSize < Rope.Size[replace] THEN replace _ Rope.Substr[replace, 0, repSize]; new _ Rope.Replace[base: base, start: start, len: len, with: replace]; }; <<***** Initialization>> punctuationString: ROPE _ "!@#$%~&*()-`=+[{]};:'"",.<>/?\\|_^"; charPropertyTable: PUBLIC REF READONLY CharPropertyTable _ InitCharPropertyTable[]; LegalCharacters: TYPE = CHAR[0C..177C]; InitCharPropertyTable: PROC RETURNS [REF CharPropertyTable] = { cpt: REF CharPropertyTable _ NEW[CharPropertyTable]; FOR ch: CHAR IN CHAR DO cpt[ch] _ illegal; ENDLOOP; FOR ch: CHAR IN LegalCharacters DO cpt[ch] _ alphaNumeric; ENDLOOP; cpt[Ascii.TAB] _ white; cpt[Ascii.SP] _ white; cpt[Ascii.CR] _ white; cpt[140C] _ punctuation; TRUSTED { FOR i: INT IN [0 .. Rope.Size[punctuationString]) DO cpt[Rope.Fetch[punctuationString, i]] _ punctuation; ENDLOOP }; RETURN[cpt]; }; END. <> <> <> <<>> <> <> <> <<>> <> <> <<>> <> <> <<>>