<<>> <> <> <> <> <> <> <> <> DIRECTORY AdobeCommon USING [CatchErrors, Handle, PostMessage, PostNumber], AdobeCommonInternal USING [InstanceData, InstanceDataHandle], AdobeTool, ARAccess USING [AppendChar], Ascii USING [CR, LF, NUL], Convert USING [CardFromRope, Error, RopeFromCard], IO USING [Close, EndOf, EndOfStream, GetChar, PutChar, PutRope, SetIndex, STREAM], PFS USING [Error, PathFromRope, StreamOpen], Rope USING [Concat, Equal, Fetch, Length, ROPE], TopoSort USING [ListSort, PartialComparison]; AdobeToolImplD: CEDAR MONITOR IMPORTS AdobeCommon, ARAccess, Convert, IO,PFS, Rope, TopoSort EXPORTS AdobeTool = BEGIN <> sortPos: CARDINAL = 0; showPos: CARDINAL = 1; sortBkgdPos: CARDINAL = 2; maxLenPos: CARDINAL = 3; inputPos: CARDINAL = 4; outputPos: CARDINAL = 5; keyspecsPos: CARDINAL = 6; nSortParams: CARDINAL = 7; LT: INTEGER = -1; EQ: INTEGER = 0; GT: INTEGER = 1; adobeBytesPerPage: LONG CARDINAL = 65536; SortKeySpec: TYPE = REF SortKeySpecItem; SortKeySpecItem: TYPE = RECORD [ posInSortKeyFile: CARDINAL, ascending: BOOLEAN, next: SortKeySpec]; SortStringBuffer: TYPE = RECORD [s: Rope.ROPE]; <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> < {>> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> < ERROR; --shouldn't happen>> <> SortCommandProc: PUBLIC PROCEDURE [h: AdobeCommon.Handle] = { windowData: AdobeCommon.Handle ¬ h; --AdobeCommon.GetDataSW[sw]; instanceData: AdobeCommonInternal.InstanceDataHandle ¬ NARROW[windowData.instanceData]; <> IF windowData.system = LAST[CARDINAL] --OR windowData.context = NIL-- OR windowData.knownSystems = NIL OR windowData.knownSystems.next = 0 THEN { AdobeCommon.PostMessage[windowData, TRUE, "No available systems"]; RETURN}; IF windowData.isBusy THEN AdobeCommon.PostMessage[windowData, TRUE, "Adobe system is Busy. Please try again later. "] ELSE { windowData.isBusy ¬ TRUE; <> <> <> <> <> <> AdobeCommon.CatchErrors[ --sw, item, index, --windowData, ChooseSortCmd]}--}; }; UpperCase: PROCEDURE [c: CHAR] RETURNS [CHAR] = { IF c IN ['a..'z] THEN RETURN [c - 'a + 'A] ELSE RETURN[c]; }; ChooseSortCmd: PROCEDURE [windowData: AdobeCommon.Handle] = <> { <> {ENABLE UNWIND => windowData.isBusy ¬ FALSE; <> <>> <> <> < p2.Fetch[index] =>>> <> <> <> <> <> <> AdobeCommon.PostMessage[data, FALSE, "Sorting..."]; [currentFileLength, maxFileLength, headerLength, numberOfKeySpecsEntered, outputFileName] ¬ InitializeSortVariables[data, sortKeySpecRef]; ReadFirstLine[sortData.sortKeysSH]; reportData ¬ GetSortData[]; <> <> <> <> <> <> sortStringBuffer ¬ NIL; <> ReadFirstLine[sortData.sortKeysSH]; IF sortKeySpecRef­ = NIL THEN CopyInputFileToOutputFile[ data, outputFileName, maxFileLength, tempstring, headerLength] <> ELSE { TopoSort.ListSort[ alpha: NIL, omega: NIL, GetLink: GetLink, SetLink: SetLink, Compare: Compare]; maxCharsAllStrings ¬ 0; WHILE reportData # NIL DO SortKeysPutString[reportData.data, 0]; reportData ¬ reportData.next; ENDLOOP; }; <> <> <> <> <> <> IF maxFileLength # LAST[LONG CARDINAL] THEN { AdobeCommon.PostMessage[data, FALSE, "Output Files: "]; AdobeCommon.PostMessage[data, FALSE, outputFileName]; AdobeCommon.PostMessage[data, FALSE, "1.."]; AdobeCommon.PostMessage[data, FALSE, outputFileName]; AdobeCommon.PostNumber[data, TRUE, sortData.fileNumber - 1]}; <> <> <> <> <> IF sortKeySpecRef­ # NIL THEN FreeSortKeySpec[data, sortKeySpecRef­]; sortData.sortKeysSH ¬ CleanUpStream[sortData.sortKeysSH]; sortData.inputSH ¬ CleanUpStream[sortData.inputSH]; sortData.outputSH ¬ CleanUpStream[sortData.outputSH]; }; ENDCASE; }; --of Sort ShowSortKeys: PUBLIC PROC [handle: AdobeCommon.Handle] = { data: AdobeCommon.Handle ¬ handle; char: CHARACTER; <> sortKey: Rope.ROPE ¬ NIL; --String.MakeString[data.heap, 16]; instanceData: AdobeCommonInternal.InstanceDataHandle ¬ NARROW[data.instanceData]; WITH instanceData SELECT FROM sortData: REF AdobeCommonInternal.InstanceData.sort => { ENABLE { UNWIND => { IF sortData.sortKeysSH # NIL THEN sortData.sortKeysSH ¬ CleanUpStream[ sortData.sortKeysSH]; <> } }; sortData.sortInputFile ¬ data.getContents[data.editors[2]]; IF sortData.sortInputFile = NIL OR sortData.sortInputFile.Length = 0 THEN { AdobeCommon.PostMessage[data, TRUE, "No input file specified."]; ERROR ABORTED }; GetSortKeysFile[data]; IF sortData.sortKeysSH # NIL THEN { AdobeCommon.PostMessage[data, FALSE, "Choose from these sort keys: "]; char ¬ IO.GetChar[sortData.sortKeysSH]; WHILE char # Ascii.CR AND char # Ascii.LF DO IF char = Ascii.NUL THEN { AdobeCommon.PostMessage[data, FALSE, sortKey]; <<--ClearString[sortKey];>> sortKey ¬ NIL; <> char ¬ IO.GetChar[sortData.sortKeysSH]; IF char # Ascii.CR AND char # Ascii.LF THEN { AdobeCommon.PostMessage[data, FALSE, ", "]; sortKey ¬ ARAccess.AppendChar[sortKey, char] <> } ELSE EXIT; } ELSE sortKey ¬ ARAccess.AppendChar[sortKey, char]; <> char ¬ IO.GetChar[sortData.sortKeysSH]; ENDLOOP; AdobeCommon.PostMessage[data, TRUE, " "] } ELSE { AdobeCommon.PostMessage[data, TRUE, "the sortkeys file does not exist"]; ERROR ABORTED }; sortData.sortKeysSH ¬ CleanUpStream[sortData.sortKeysSH]; }; ENDCASE; --should not happen <> }; --of ShowSortKeys InitializeSortVariables: PROCEDURE [data: AdobeCommon.Handle, ptrToSortKeySpec: REF SortKeySpec] RETURNS [currentFileLength: LONG CARDINAL, maxFileLength, headerLength: LONG CARDINAL, numberOfKeySpecsEntered: CARDINAL, outputFileName: Rope.ROPE] = { instanceData: AdobeCommonInternal.InstanceDataHandle ¬ NARROW[data.instanceData]; numberofSortKeys: CARDINAL ¬ 0; currentFileLength ¬ 0; WITH instanceData SELECT FROM sortData: REF AdobeCommonInternal.InstanceData.sort => { sortData.sortInputFile ¬ data.getContents[data.editors[2]]; IF sortData.sortInputFile = NIL OR sortData.sortInputFile.Length = 0 THEN { AdobeCommon.PostMessage[data, TRUE, "ERROR--no input file specified."]; ERROR ABORTED }; sortData.sortOutputFile ¬ data.getContents[data.editors[3]]; IF sortData.sortOutputFile = NIL OR sortData.sortOutputFile.Length = 0 THEN { AdobeCommon.PostMessage[data, TRUE, "ERROR--no output file specified."]; ERROR ABORTED }; sortData.keySpecs ¬ data.getContents[data.editors[4]]; IF sortData.keySpecs = NIL OR sortData.keySpecs.Length = 0 THEN { AdobeCommon.PostMessage[data, TRUE, "ERROR--no key specs were specified."]; ERROR ABORTED }; sortData.inputSH ¬ GetFile[data, sortData.sortInputFile, TRUE]; GetSortKeysFile[data]; outputFileName ¬ sortData.sortOutputFile; <> [numberofSortKeys, numberOfKeySpecsEntered] ¬ GetKeySpec[data, ptrToSortKeySpec]; headerLength ¬ GetHeaderLength[data, numberofSortKeys]; sortData.fileNumber ¬ 1; sortData.maxLen ¬ data.getContents[data.editors[1]]; IF sortData.maxLen = NIL OR sortData.maxLen.Length = 0 THEN { maxFileLength ¬ LAST[LONG CARDINAL]; sortData.outputSH ¬ GetFile[data, sortData.sortOutputFile, FALSE]; currentFileLength ¬ PutHeader[data, outputFileName, headerLength]} ELSE { maxFileLength ¬ Convert.CardFromRope[sortData.maxLen, 10 ! Convert.Error => {maxFileLength ¬ LAST[CARD]; CONTINUE}]; <> currentFileLength ¬ GetNextFileAndPutHeader[data, outputFileName, headerLength]; sortData.fileNumber ¬ sortData.fileNumber + 1 } }; ENDCASE; --should not happen }; --of InitializeSortVariables GetFile: PROCEDURE [data: AdobeCommon.Handle, fileName: Rope.ROPE, read: BOOLEAN] RETURNS [fileHandle: IO.STREAM --MStream.Handle-- ¬ NIL] = BEGIN <> fileHandle ¬ IF read THEN PFS.StreamOpen[PFS.PathFromRope[fileName] ! PFS.Error => { AdobeCommon.PostMessage[data, FALSE, fileName]; AdobeCommon.PostMessage[data, TRUE, " cannot be acquired."]; ERROR ABORTED; }] <> < {>> <> <> <> <> <<}]>> ELSE PFS.StreamOpen[PFS.PathFromRope[fileName], write ! PFS.Error => { AdobeCommon.PostMessage[data, FALSE, fileName]; AdobeCommon.PostMessage[data, TRUE, " cannot be acquired."]; ERROR ABORTED; }]; <> < {>> <> <> <> <> <<}];>> END; GetNextFileAndPutHeader: PROCEDURE [data: AdobeCommon.Handle, outputFileName: Rope.ROPE, headerLength: LONG CARDINAL] RETURNS [currentFileLength: LONG CARDINAL] = { instanceData: AdobeCommonInternal.InstanceDataHandle ¬ NARROW[data.instanceData]; <> newFileName: Rope.ROPE ¬ outputFileName; <> WITH instanceData SELECT FROM sortData: REF AdobeCommonInternal.InstanceData.sort => { newFileName ¬ newFileName.Concat[Convert.RopeFromCard[sortData.fileNumber, 10, FALSE]]; <> sortData.outputSH ¬ PFS.StreamOpen[PFS.PathFromRope[newFileName], write]; <> <> currentFileLength ¬ 0; currentFileLength ¬ PutHeader[data, newFileName, headerLength]; } ENDCASE => ERROR; --shouldn't happen <> }; --of GetNextFileAndPutHeader ReadFirstLine: PROCEDURE [sortSH: IO.STREAM--MStream.Handle--] = BEGIN <> <> char: CHARACTER ¬ ' ; IO.SetIndex[sortSH, 0]; <> char ¬ IO.GetChar[sortSH]; WHILE char # Ascii.CR AND char # Ascii.LF DO char ¬ IO.GetChar[sortSH]; ENDLOOP; END; --of ReadFirstLine GetKeySpec: PROCEDURE [data: AdobeCommon.Handle, ptrToSortKeySpec: REF SortKeySpec] RETURNS [numberOfSortKeys, numberOfKeySpecsEntered: CARDINAL] = BEGIN index: INTEGER ¬ 0; sortKeySpec, newSortKeySpec, endOfSortKeySpec: SortKeySpec ¬ NIL; char: CHARACTER ¬ ' ; keySpecAscending: BOOLEAN ¬ TRUE; keySpecsString: Rope.ROPE ¬ NIL; keySpecToken: Rope.ROPE ¬ NIL; <> instanceData: AdobeCommonInternal.InstanceDataHandle ¬ NARROW[data.instanceData]; <> WITH instanceData SELECT FROM sortData: REF AdobeCommonInternal.InstanceData.sort => { numberOfSortKeys ¬ numberOfKeySpecsEntered ¬ 0; IF sortData.keySpecs = NIL OR sortData.keySpecs.Length = 0 THEN RETURN; <> <> { ENABLE UNWIND => { <> <> <> }; keySpecsString ¬ NIL; <> <> WHILE index < sortData.keySpecs.Length DO keySpecAscending ¬ TRUE; --default switch value; WHILE index < sortData.keySpecs.Length AND sortData.keySpecs.Fetch[index] # '/ DO IF sortData.keySpecs.Fetch[index] = '' THEN { index ¬ index + 1; IF sortData.keySpecs.Fetch[index] # '/ THEN { AdobeCommon.PostMessage[data, TRUE, "ERROR--invalid field name"]; ERROR ABORTED}}; keySpecToken ¬ ARAccess.AppendChar[keySpecToken, sortData.keySpecs.Fetch[index]]; keySpecsString ¬ ARAccess.AppendChar[keySpecToken, sortData.keySpecs.Fetch[index]]; <> <<@keySpecToken, sortData.keySpecs[index], data.heap];>> <> <<@keySpecsString, sortData.keySpecs[index], data.heap];>> index ¬ index + 1; ENDLOOP; keySpecsString ¬ ARAccess.AppendChar[keySpecsString, '/]; <> index ¬ index + 1; IF index < sortData.keySpecs.Length THEN SELECT sortData.keySpecs.Fetch[index] FROM 'a, 'A, 'u, 'U => { keySpecAscending ¬ TRUE; keySpecsString ¬ ARAccess.AppendChar[keySpecsString, sortData.keySpecs.Fetch[index]]; index ¬ index + 1; }; 'd, 'D => { keySpecAscending ¬ FALSE; keySpecsString ¬ ARAccess.AppendChar[keySpecsString, sortData.keySpecs.Fetch[index]]; index ¬ index + 1; }; ' => { AdobeCommon.PostMessage[data, TRUE, "no switch was entered--the default switch is ascending. "]; keySpecsString ¬ ARAccess.AppendChar[keySpecsString, 'a] }; <> <<@keySpecsString, 'a, data.heap]>> <<};>> ENDCASE => { AdobeCommon.PostMessage[data, TRUE, "invalid switch--the default switch is ascending. "]; keySpecsString ¬ ARAccess.AppendChar[keySpecsString, 'a] <> <<@keySpecsString, 'a, data.heap]>> } ELSE { AdobeCommon.PostMessage[data, TRUE, "no switch was entered--the default switch is ascending. "]; keySpecsString ¬ ARAccess.AppendChar[keySpecsString, 'a] <> }; keySpecsString ¬ ARAccess.AppendChar[keySpecsString, ' ]; <> numberOfKeySpecsEntered ¬ numberOfKeySpecsEntered + 1; <> newSortKeySpec ¬ NEW[SortKeySpecItem]; newSortKeySpec.posInSortKeyFile ¬ FindPosOfKeySpec[ keySpecToken, data]; <> keySpecToken ¬ NIL; <> newSortKeySpec.ascending ¬ keySpecAscending; newSortKeySpec.next ¬ NIL; IF ptrToSortKeySpec­ = NIL THEN { ptrToSortKeySpec­ ¬ newSortKeySpec; sortKeySpec ¬ ptrToSortKeySpec­; endOfSortKeySpec ¬ newSortKeySpec; } <> ELSE { endOfSortKeySpec.next ¬ newSortKeySpec; endOfSortKeySpec ¬ newSortKeySpec}; index ¬ index + 1; ENDLOOP}; <> sortData.keySpecs ¬ NIL; <> sortData.keySpecs ¬ sortData.keySpecs.Concat[keySpecsString]; <> <> <> numberOfSortKeys ¬ CountSortKeys[sortData.sortKeysSH]; FOR index IN [numberOfSortKeys..numberOfSortKeys + 2] DO newSortKeySpec ¬ NEW[SortKeySpecItem]; newSortKeySpec.posInSortKeyFile ¬ index; newSortKeySpec.next ¬ NIL; endOfSortKeySpec.next ¬ newSortKeySpec; endOfSortKeySpec ¬ newSortKeySpec; ENDLOOP; }; ENDCASE; <> <> END; --of GetKeySpec CopyInputFileToOutputFile: PROCEDURE [data: AdobeCommon.Handle, outputFileName: Rope.ROPE, maxFileLength: LONG CARDINAL, tempstring: Rope.ROPE, headerLength: LONG CARDINAL] = BEGIN instanceData: AdobeCommonInternal.InstanceDataHandle ¬NARROW[data.instanceData]; WITH instanceData SELECT FROM sortData: REF AdobeCommonInternal.InstanceData.sort => { GetNumber: PROCEDURE RETURNS [LONG CARDINAL ¬ 0] = BEGIN tempstring ¬ NIL; <> WHILE char # Ascii.NUL DO tempstring ¬ ARAccess.AppendChar[tempstring, char]; <> char ¬ IO.GetChar[sortData.sortKeysSH]; ENDLOOP; char ¬ IO.GetChar[sortData.sortKeysSH]; RETURN[Convert.CardFromRope[tempstring, 10]]; <> END; --of GetNumber count: CARDINAL ¬ 0; i, pagePos, bytePos, lenPos, currentFileLength: LONG CARDINAL ¬ 0; char: CHARACTER ¬ ' ; numberOfSortKeys: CARDINAL ¬ CountSortKeys[ sortData.sortKeysSH]; UNTIL IO.EndOf[sortData.sortKeysSH] --MStream.EndOf[sortData.sortKeysSH]-- DO WHILE count # numberOfSortKeys DO WHILE char # Ascii.NUL DO char ¬ IO.GetChar[sortData.sortKeysSH]; ENDLOOP; count ¬ count + 1; char ¬ IO.GetChar[sortData.sortKeysSH]; ENDLOOP; pagePos ¬ GetNumber[]; bytePos ¬ GetNumber[]; lenPos ¬ GetNumber[]; count ¬ 0; IF currentFileLength + lenPos > maxFileLength THEN { sortData.outputSH ¬ CleanUpStream[sortData.outputSH]; currentFileLength ¬ GetNextFileAndPutHeader[ data, outputFileName, headerLength]; sortData.fileNumber ¬ sortData.fileNumber + 1}; IO.SetIndex[sortData.inputSH, (adobeBytesPerPage * pagePos + bytePos)]; <> <> <<(adobeBytesPerPage * pagePos + bytePos)];>> FOR i IN [1..lenPos] DO IO.PutChar[ sortData.outputSH, IO.GetChar[sortData.inputSH]]; ENDLOOP; --of for loop currentFileLength ¬ currentFileLength + lenPos; ENDLOOP; --of until loop }; ENDCASE => ERROR; --shouldn't happen END; --of CopyInputFileToOutputFile CountSortKeys: PROCEDURE [sortSH: IO.STREAM--MStream.Handle--] RETURNS [count: CARDINAL ¬ 0] = BEGIN char: CHARACTER ¬ ' ; IO.SetIndex[sortSH, 0]; <> UNTIL char = Ascii.CR OR char = Ascii.LF DO WHILE char # Ascii.NUL DO char ¬ IO.GetChar[sortSH]; ENDLOOP; count ¬ count + 1; char ¬ IO.GetChar[sortSH]; ENDLOOP; --of until loop END; --of CountSortKeys FreeSortKeySpec: PROCEDURE [ data: AdobeCommon.Handle, sortKeySpec: SortKeySpec] = BEGIN tempSortKeySpec: SortKeySpec; UNTIL sortKeySpec = NIL DO tempSortKeySpec ¬ sortKeySpec.next; <> sortKeySpec ¬ tempSortKeySpec; ENDLOOP; END; --of FreeSortKeySpec FindPosOfKeySpec: PROCEDURE [ token: Rope.ROPE, data: AdobeCommon.Handle] RETURNS [pos: CARDINAL ¬ 0] = BEGIN char: CHARACTER ¬ ' ; instanceData: AdobeCommonInternal.InstanceDataHandle ¬ NARROW[data.instanceData]; WITH instanceData SELECT FROM sortData: REF AdobeCommonInternal.InstanceData.sort => { field: Rope.ROPE ¬ NIL; <> <> IO.SetIndex[sortData.sortKeysSH, 0]; <> UNTIL char = Ascii.CR OR char = Ascii.LF DO WHILE ((char ¬ IO.GetChar[sortData.sortKeysSH]) # Ascii.NUL) AND (char # Ascii.CR) AND (char # Ascii.LF) DO field ¬ ARAccess.AppendChar[field, char]; <> ENDLOOP; --of while loop IF Rope.Equal[token, field, FALSE] THEN { <> RETURN[pos] }; <> <> pos ¬ pos + 1; field ¬ NIL; <> ENDLOOP; --of until loop AdobeCommon.PostMessage[data, FALSE, token]; AdobeCommon.PostMessage[data, TRUE, "--this field cannot be used as a sortkey"]; ERROR ABORTED}; ENDCASE; --should not happen END; --of FindPosOfKeySpec GetSortKeysFile: PROCEDURE [data: AdobeCommon.Handle] = BEGIN sortKeyFile: Rope.ROPE ¬ NIL; index: INTEGER ¬ 0; <> instanceData: AdobeCommonInternal.InstanceDataHandle ¬ NARROW[data.instanceData]; WITH instanceData SELECT FROM sortData: REF AdobeCommonInternal.InstanceData.sort => { sortKeyFile ¬ NIL; <> UNTIL index = sortData.sortInputFile.Length OR sortData.sortInputFile.Fetch[index] = '. DO sortKeyFile ¬ ARAccess.AppendChar[sortKeyFile, sortData.sortInputFile.Fetch[index]]; <> <> index ¬ index + 1; ENDLOOP; sortKeyFile ¬ sortKeyFile.Concat[".sortKeys"]; <> sortData.sortKeysSH ¬ PFS.StreamOpen[ PFS.PathFromRope[sortKeyFile] ! PFS.Error => { AdobeCommon.PostMessage[data, TRUE, " ERROR--file cannot be obtained"]; ERROR ABORTED}]; <> <> < {>> <> <> <> <> }; ENDCASE; --should not happen END; --of GetSortKeysFile GetHeaderLength: PROCEDURE [data: AdobeCommon.Handle, numberofSortKeys: CARDINAL] RETURNS [n: LONG CARDINAL] = BEGIN count: CARDINAL ¬ 0; char: CHARACTER ¬ ' ; tempString: Rope.ROPE ¬ NIL; <> page, byte: LONG CARDINAL ¬ 0; instanceData: AdobeCommonInternal.InstanceDataHandle ¬ NARROW[data.instanceData]; WITH instanceData SELECT FROM sortData: REF AdobeCommonInternal.InstanceData.sort => { ReadFirstLine[sortData.sortKeysSH]; <> char ¬ IO.GetChar[ sortData.sortKeysSH ! IO.EndOfStream => { AdobeCommon.PostMessage[ data, TRUE, "There are no ARs in the sortkeys file"]; ERROR ABORTED}]; IF char = Ascii.NUL THEN count ¬ count + 1; UNTIL count = numberofSortKeys DO WHILE (char ¬ IO.GetChar[sortData.sortKeysSH]) # Ascii.NUL DO ENDLOOP; count ¬ count + 1; ENDLOOP; WHILE (char ¬ IO.GetChar[sortData.sortKeysSH]) # Ascii.NUL DO tempString ¬ ARAccess.AppendChar[tempString, char]; <> <<@tempString, char, Heap.systemZone];>> ENDLOOP; page ¬ Convert.CardFromRope[tempString, 10]; <> tempString ¬ NIL; <> WHILE (char ¬ IO.GetChar[sortData.sortKeysSH]) # Ascii.NUL DO tempString ¬ ARAccess.AppendChar[tempString, char]; <> <<@tempString, char, Heap.systemZone];>> ENDLOOP; byte ¬ Convert.CardFromRope[tempString, 10]; <> n ¬ page * adobeBytesPerPage + byte}; ENDCASE; --should not happen <> END; --of GetHeaderLength PutHeader: PROCEDURE [ data: AdobeCommon.Handle, fileName: Rope.ROPE, headerLength: LONG CARDINAL] RETURNS [currentFileLength: LONG CARDINAL] = BEGIN char: CHARACTER ¬ Ascii.NUL; instanceData: AdobeCommonInternal.InstanceDataHandle ¬ NARROW[data.instanceData]; WITH instanceData SELECT FROM sortData: REF AdobeCommonInternal.InstanceData.sort => { PutIt: PROCEDURE [s: Rope.ROPE, CR: BOOLEAN ¬ FALSE] = BEGIN IF s # NIL THEN IO.PutRope[self: sortData.outputSH, r: s]; IF CR THEN IO.PutChar[sortData.outputSH, Ascii.CR]; END; --of PutIt currentFileLength ¬ 0; PutIt[s: "This is file: ", CR: FALSE]; PutIt[s: fileName, CR: TRUE]; PutIt[s: "Generated by AdobeSort using: ", CR: FALSE]; PutIt[s: sortData.keySpecs, CR: TRUE]; PutIt[s: "Original "]; IF sortData.keySpecs = NIL THEN currentFileLength ¬ fileName.Length + 55 ELSE currentFileLength ¬ fileName.Length + sortData.keySpecs.Length + 55; IO.SetIndex[sortData.inputSH, 0]; <> <> THROUGH [0..headerLength) DO IO.PutChar[ sortData.outputSH, IO.GetChar[sortData.inputSH]]; ENDLOOP; currentFileLength ¬ currentFileLength + headerLength} ENDCASE => ERROR; --shouldn't happen END; --of PutHeader CleanUpStream: PROCEDURE [streamHandle: IO.STREAM--MStream.Handle--] RETURNS [IO.STREAM--MStream.Handle--] = BEGIN IO.Close[streamHandle]; <> streamHandle ¬ NIL; RETURN[streamHandle]; END; --of CleanUpStream END. 14-May-87 13:54:20 - rlc - fix CompareStrings. remainder of proc wants to be part of the ELSE clause. As is was the key spec wasn't being incremented properly in the case of an empty field.