| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977 |
- IMPLEMENTATION MODULE ListUtils;
- (*
- * REPERTOIRE
- * Release 1.6
- * By Charles Bradford and Cole Brecheen
- * (c) Copyright 1985-1992 PMI
- * Green Bay, Wisconsin
- * All rights reserved
- * (414) 468-6040
- *
- * $Header: D:/logfiles/mods/listutil.mov 1.6 10 Mar 1991 15:35:08 coleb $
- *
- *
- * For GenList manipulation routines that don't need access to
- * the internal structure of a GenList.
- *)
- IMPORT ByteFiddler;
- IMPORT EnvironUtils;
- IMPORT ErrorManager;
- IMPORT HandleIO;
- IMPORT GenLists;
- IMPORT LowLevel;
- IMPORT M2Strings;
- IMPORT Numbers;
- IMPORT NumTypes;
- IMPORT PosUtils;
- IMPORT StrConv;
- IMPORT StrEdit;
- IMPORT StringIO;
- IMPORT SYSTEM;
- IMPORT VStorage;
- VAR
- Initialized : BOOLEAN;
- PROCEDURE Init();
- BEGIN
- IF Initialized THEN
- RETURN;
- ELSE
- Initialized := TRUE;
- END;
- ByteFiddler.Init();
- EnvironUtils.Init();
- ErrorManager.Init();
- HandleIO.Init();
- GenLists.Init();
- LowLevel.Init();
- M2Strings.Init();
- Numbers.Init();
- NumTypes.Init();
- PosUtils.Init();
- StrConv.Init();
- StrEdit.Init();
- StringIO.Init();
- VStorage.Init();
- END Init;
- PROCEDURE InitResponse(msg : ARRAY OF CHAR);
- (*All calls to InitResponse are diagnostic. Remove them from
- finished programs.*)
- VAR
- TmpStr : ARRAY [0..79] OF CHAR;
- BEGIN
- StrEdit.AssignStr('Uninit. list passed to ', TmpStr);
- StrEdit.Append(TmpStr, msg);
- ErrorManager.WARN(TmpStr);
- END InitResponse;
- (*$O-*)
- PROCEDURE CharCount( TheList : GenLists.GenList;
- StartLine, EndLine: CARDINAL ): LONGINT;
- VAR
- tmp1, tmp2: LONGINT;
- lngth, cnt: CARDINAL;
- BEGIN
- tmp2 := NumTypes.L0;
- lngth := GenLists.ListLength( TheList );
- IF EndLine > lngth THEN
- EndLine := lngth;
- END;
- FOR cnt := StartLine TO EndLine DO
- tmp1 := Numbers.Lc( ElmtSize(TheList, cnt) );
- (*Workaround for Logitech LONGINT bug.*)
- tmp2 := tmp2 + tmp1;
- END;
- RETURN tmp2;
- END CharCount;
- (*$O=*)
- PROCEDURE CheckLength(VAR TheList : GenLists.GenList;
- LeftMargin, LngthLimit : CARDINAL);
- VAR
- delimiters : ARRAY [0..15] OF CHAR;
- tmpsize, cnt, DumType, BreakSpot : CARDINAL;
- tmpadr: SYSTEM.ADDRESS;
- BEGIN
- delimiters := ' -,)]?+';
- cnt := 1;
- WHILE cnt <= GenLists.ListLength( TheList) DO
- tmpsize := ElmtSize( TheList, cnt );
- (* we assign this out here to make it easier to see in
- the RTD *)
- IF tmpsize > LngthLimit THEN
- GenLists.GetElmtAdr( TheList, cnt, tmpadr, tmpsize, DumType );
- tmpsize := LowLevel.ScanEQ( tmpsize, 0C, tmpadr );
- (*reduce size to real string length*)
- BreakSpot := PosUtils.BreakPtAdr( tmpadr, tmpsize, LngthLimit,
- delimiters) + 1;
- GenLists.ListInsertAdr( LowLevel.AddAddr(tmpadr,
- BreakSpot), (tmpsize -BreakSpot) + LeftMargin + 1,
- 0, TheList, cnt + 1 );
- (* We can't use StrCode as the type in this
- ListInsertAdr because we need to reserve room in
- the list element beyond the null. *)
- GenLists.ChangeTypeCode( TheList, cnt + 1, GenLists.StrCode );
- LowLevel.Fill( LowLevel.AddAddr(tmpadr, BreakSpot), 1, 0C );
- (*Make sure there's a null terminator at end of old
- string.*)
- IF LeftMargin > 0 THEN
- GenLists.GetElmtAdr( TheList, cnt + 1, tmpadr, tmpsize, DumType );
- LowLevel.ShiftArrayRight( tmpadr, tmpsize, LeftMargin );
- LowLevel.Fill( tmpadr, LeftMargin, ' ' );
- END;
- END;
- INC( cnt );
- END;
- END CheckLength;
- PROCEDURE IndentationAt( TheList : GenLists.GenList;
- Line : CARDINAL ): CARDINAL;
- VAR
- tmpsize, indent, DumType: CARDINAL;
- tmpadr: SYSTEM.ADDRESS;
- BEGIN
- GenLists.GetElmtAdr( TheList, Line, tmpadr, tmpsize, DumType );
- tmpsize := LowLevel.ScanEQ( tmpsize, 0C, tmpadr );
- IF tmpsize = 0 THEN
- RETURN 65535;
- END;
- indent := LowLevel.ScanNE(tmpsize, ' ', tmpadr);
- RETURN indent;
- END IndentationAt;
- PROCEDURE ReformPara( VAR TheList : GenLists.GenList;
- LeftMargin, RightMargin : CARDINAL; VAR
- StartLine, CursorLine, CursorCol: CARDINAL;
- VAR LinesAdded, BytesAdded: INTEGER; VAR
- CursorBytePos: LONGINT );
- VAR
- blank : ARRAY [0..0] OF CHAR;
- delimiters : ARRAY [0..15] OF CHAR;
- tmpsize, cnt, indent, DumType, BreakSpot : CARDINAL;
- tmpadr: SYSTEM.ADDRESS;
- done : BOOLEAN;
- BEGIN
- blank[0] := ' ';
- delimiters := ' -,)]?+';
- cnt := StartLine;
- LinesAdded := 0;
- BytesAdded := 0;
- done := FALSE;
- WHILE (NOT done) AND (cnt <= GenLists.ListLength( TheList)) DO
- IF cnt = GenLists.ListLength( TheList ) THEN
- StartLine := cnt;
- done := TRUE;
- ELSE
- indent := IndentationAt( TheList, cnt + 1 );
- END;
- IF (NOT done) AND (indent = LeftMargin) THEN
- (* We bring the next line up and append it to this one. Means the
- reformat stops when we reach a line where indentation <>
- LeftMargin. *)
- GenLists.GetElmtAdr( TheList, cnt, tmpadr, tmpsize, DumType );
- tmpsize := LowLevel.ScanEQ( tmpsize, 0C, tmpadr );
- (*reduce size to real string length*)
- IF (tmpsize > 0) AND (ByteFiddler.PeekChar(
- LowLevel.AddAddr( tmpadr, tmpsize - 1 )) # ' ') THEN
- (* If this line doesn't end with a blank. *)
- InsertIntoElmt( TheList, cnt, SYSTEM.ADR(blank), 1, 65535 );
- (*Append a blank to this line because we're not going to
- insert leading blanks from the line below.*)
- INC( BytesAdded );
- END;
- IF CursorLine > (cnt + 1) THEN
- DEC( CursorLine );
- ELSIF (CursorLine = (cnt + 1)) THEN
- DEC( CursorLine );
- CursorCol := CursorCol + ElmtSize(TheList, cnt);
- END;
- GenLists.GetElmtAdr( TheList, cnt + 1, tmpadr, tmpsize, DumType );
- InsertIntoElmt( TheList, cnt, LowLevel.AddAddr(tmpadr, indent),
- ElmtSize(TheList, cnt + 1) - indent, 65535 );
- BytesAdded := BytesAdded - INTEGER(indent) - 2;
- (* We've deleted leading spaces and separating CR/LF. *)
- GenLists.ListDelete( TheList, cnt + 1, 1 );
- DEC( LinesAdded );
- ELSE
- done := TRUE;
- END;
- GenLists.GetElmtAdr( TheList, cnt, tmpadr, tmpsize, DumType );
- tmpsize := LowLevel.ScanEQ( tmpsize, 0C, tmpadr );
- (*reduce size to real string length*)
- IF (tmpsize > RightMargin) THEN
- done := FALSE;
- BreakSpot := PosUtils.BreakPtAdr( tmpadr, tmpsize, RightMargin,
- delimiters) + 1;
- IF CursorLine > cnt THEN
- INC( CursorLine );
- ELSIF (CursorLine = cnt) AND (CursorCol >= BreakSpot) THEN
- INC( CursorLine );
- CursorCol := CursorCol - BreakSpot;
- END;
- GenLists.ListInsertAdr( LowLevel.AddAddr(tmpadr,
- BreakSpot), (tmpsize -BreakSpot) + LeftMargin + 1,
- 0, TheList, cnt + 1 );
- (* We can't use StrCode as the type in this
- ListInsertAdr because we need to reserve room in
- the list element beyond the null. *)
- INC( LinesAdded );
- GenLists.ChangeTypeCode( TheList, cnt + 1, GenLists.StrCode );
- LowLevel.Fill( LowLevel.AddAddr(tmpadr, BreakSpot), 1, 0C );
- (*Make sure there's a null terminator at end of old
- string.*)
- IF LeftMargin > 0 THEN
- GenLists.GetElmtAdr( TheList, cnt + 1, tmpadr, tmpsize, DumType );
- LowLevel.ShiftArrayRight( tmpadr, tmpsize, LeftMargin );
- LowLevel.Fill( tmpadr, LeftMargin, ' ' );
- IF CursorLine = (cnt + 1) THEN
- CursorCol := CursorCol + LeftMargin;
- END;
- BytesAdded := BytesAdded + INTEGER(LeftMargin) + 2 ;
- (* We've added leading spaces on new line plus CR/LF
- on this one. *)
- ELSE
- BytesAdded := BytesAdded + 2;
- (* We've added only the CR/LF. *)
- END;
- END;
- INC( cnt );
- END;
- IF (CursorBytePos > NumTypes.L0) THEN
- (* They want us to compute new byte position. *)
- IF CursorLine > 1 THEN
- CursorBytePos := CharCount( TheList, 1, CursorLine - 1 ) +
- Numbers.Lc( CursorCol );
- ELSE
- CursorBytePos := Numbers.Lc( CursorCol );
- END;
- END;
- StartLine := cnt;
- END ReformPara;
- PROCEDURE DeTabList( VAR TheList: GenLists.GenList; VAR
- ListChanged: BOOLEAN );
- VAR
- TmpStr: ARRAY [0..255] OF CHAR;
- ListEnd, StartingSpot, StrSpot: CARDINAL;
- TabStr: ARRAY [0..0] OF CHAR;
- BEGIN
- TabStr[0] := 11C;
- ListEnd := GenLists.ListLength( TheList );
- StartingSpot := 1;
- ListChanged := FALSE;
- WHILE (StartingSpot <= ListEnd) AND (StartingSpot # 0) DO
- StartingSpot := GenLists.ScanList( TabStr, TheList, StartingSpot,
- ListEnd, StrSpot );
- IF StartingSpot > 0 THEN
- ListChanged := TRUE;
- GetStr( TheList, StartingSpot, TmpStr );
- StrEdit.CutTrailingChars( ' ', TmpStr );
- StrEdit.ReplaceTabs( TmpStr, 8 );
- GenLists.ListReplace( TmpStr, GenLists.StrCode, TheList,
- StartingSpot );
- END;
- END;
- END DeTabList;
- PROCEDURE EnTabList( VAR TheList: GenLists.GenList; LeadingOnly: BOOLEAN; VAR
- ListChanged: BOOLEAN );
- VAR
- TmpStr: ARRAY [0..255] OF CHAR;
- ListEnd, StartingSpot, StrSpot: CARDINAL;
- BlankStr: ARRAY [0..8] OF CHAR;
- BEGIN
- BlankStr := ' ';
- ListEnd := GenLists.ListLength( TheList );
- StartingSpot := 1;
- ListChanged := FALSE;
- WHILE (StartingSpot <= ListEnd) AND (StartingSpot # 0) DO
- StartingSpot := GenLists.ScanList( BlankStr, TheList, StartingSpot,
- ListEnd, StrSpot );
- IF StartingSpot > 0 THEN
- ListChanged := TRUE;
- GetStr( TheList, StartingSpot, TmpStr );
- StrEdit.CutTrailingChars( ' ', TmpStr );
- StrEdit.InsertTabs( TmpStr, 8, LeadingOnly );
- GenLists.ListReplace( TmpStr, GenLists.StrCode, TheList,
- StartingSpot );
- END;
- END;
- END EnTabList;
- PROCEDURE ElmtSize( TheList: GenLists.GenList; spot: CARDINAL ): CARDINAL;
- VAR
- TheAddr: SYSTEM.ADDRESS;
- TheSize, TypeCode: CARDINAL;
- BEGIN
- GenLists.GetElmtAdr( TheList, spot, TheAddr, TheSize, TypeCode );
- IF TypeCode = GenLists.StrCode THEN
- TheSize := LowLevel.ScanEQ( TheSize, 0C, TheAddr );
- END;
- RETURN TheSize;
- END ElmtSize;
- PROCEDURE GetStr( TheList: GenLists.GenList; spot: CARDINAL; VAR
- TheStr: ARRAY OF CHAR );
- VAR
- TypeCode: CARDINAL;
- BEGIN
- GenLists.GetElmt( TheList, spot, TheStr, TypeCode );
- IF TypeCode # GenLists.StrCode THEN
- ErrorManager.WARN('Not a string');
- END;
- END GetStr;
- PROCEDURE HandleToList( TheHandle : VStorage.MemHandle;
- BlockSize : CARDINAL; delimiter1, delimiter2 : ARRAY OF
- CHAR; RecSize, TypeCode : CARDINAL; VAR TheList : GenLists.GenList);
- VAR
- BytesDone, Delim1Len, Delim2Len : CARDINAL;
- TwoDelimiters, FixedLengthRecs : BOOLEAN;
- PROCEDURE AnElmtStartsHere( OffSet: CARDINAL ): BOOLEAN;
- VAR
- TmpAdr: SYSTEM.ADDRESS;
- BEGIN
- IF FixedLengthRecs OR (NOT TwoDelimiters) THEN
- RETURN FALSE;
- END;
- TmpAdr := VStorage.LockMem( TheHandle );
- VStorage.UnLockMem( TheHandle );
- LowLevel.IncAddr( TmpAdr, OffSet );
- IF (BytesDone >= BlockSize) OR (0 = PosUtils.PosAdr(
- delimiter1, TmpAdr, BlockSize - BytesDone)) THEN
- RETURN TRUE;
- END;
- RETURN FALSE;
- END AnElmtStartsHere;
- PROCEDURE AnElmtEndsHere( OffSet: CARDINAL ): BOOLEAN;
- VAR
- TmpAdr: SYSTEM.ADDRESS;
- BEGIN
- IF FixedLengthRecs OR (NOT TwoDelimiters) THEN
- RETURN FALSE;
- END;
- TmpAdr := VStorage.LockMem( TheHandle );
- VStorage.UnLockMem( TheHandle );
- LowLevel.IncAddr( TmpAdr, OffSet );
- IF (BytesDone >= BlockSize) OR (0 = PosUtils.PosAdr(
- delimiter2, TmpAdr, BlockSize - BytesDone)) THEN
- RETURN TRUE;
- END;
- RETURN FALSE;
- END AnElmtEndsHere;
- PROCEDURE SizeOfElement( OldAdr: SYSTEM.ADDRESS ): CARDINAL;
- (*Returns the address of the first byte following delimiter2,
- but dist includes only the bytes preceding delimiter2.*)
- BEGIN
- IF FixedLengthRecs THEN
- RETURN RecSize;
- ELSE
- RETURN PosUtils.PosAdr( delimiter2, OldAdr, BlockSize-BytesDone);
- END;
- END SizeOfElement;
- PROCEDURE MakeOneList( TheList : GenLists.GenList );
- VAR
- TmpTypeCode, TmpSize: CARDINAL;
- TmpAdr: SYSTEM.ADDRESS;
- SubList : GenLists.GenList;
- BEGIN
- LOOP
- IF TwoDelimiters THEN
- LOOP
- (*Skip the leading delim1, if there is one, and
- move at least to the byte just beyond the next
- delim1.*)
- IF AnElmtStartsHere(BytesDone) THEN
- INC( BytesDone, Delim1Len );
- EXIT;
- ELSE
- INC( BytesDone, Delim1Len );
- END;
- END;
- END;
- IF (BytesDone >= BlockSize) THEN
- EXIT;
- END;
- IF (TypeCode < 65000)
- AND (NOT FixedLengthRecs)
- AND TwoDelimiters THEN
- TmpAdr := VStorage.LockMem( TheHandle );
- LowLevel.IncAddr( TmpAdr, BytesDone );
- LowLevel.Move( TmpAdr, SYSTEM.ADR(TmpTypeCode), 2);
- VStorage.UnLockMem( TheHandle );
- INC( BytesDone, 2 );
- ELSE
- TmpTypeCode := TypeCode;
- END;
- IF (TmpTypeCode = GenLists.ListCode) OR AnElmtStartsHere(
- BytesDone ) THEN
- GenLists.NewList( SubList );
- IF AnElmtEndsHere( BytesDone ) THEN
- (*Null list.*)
- INC( BytesDone, Delim2Len );
- ELSE
- MakeOneList( SubList );
- END;
- GenLists.ListInsert( SubList, GenLists.ListCode, TheList, 65535 );
- ELSE
- TmpAdr := VStorage.LockMem( TheHandle );
- VStorage.UnLockMem( TheHandle );
- LowLevel.IncAddr( TmpAdr, BytesDone );
- TmpSize := SizeOfElement( TmpAdr );
- GenLists.ListInsertAdr( TmpAdr, TmpSize, TmpTypeCode,
- TheList, 65535 );
- INC( BytesDone, TmpSize + Delim2Len );
- END;
- IF (BytesDone >= BlockSize) OR (AnElmtEndsHere(BytesDone)) THEN
- (*Increment past the delimiter2 that ends the whole list.*)
- INC( BytesDone, Delim2Len );
- EXIT;
- END;
- END;
- END MakeOneList;
- BEGIN
- (*HandleToList*)
- IF NOT GenLists.Initialized( TheList ) THEN
- InitResponse( 'HandleToList' );
- END;
- Delim1Len := M2Strings.Length(delimiter1);
- Delim2Len := M2Strings.Length(delimiter2);
- TwoDelimiters := FALSE;
- IF ((Delim1Len>0) OR (Delim2Len>0)) AND (RecSize>0) THEN
- ErrorManager.WARN("Delim-RecSize conflict");
- RETURN;
- END;
- FixedLengthRecs := RecSize>0;
- IF FixedLengthRecs THEN
- IF ((BlockSize MOD RecSize) # 0) THEN
- ErrorManager.WARN('Bad Recsize');
- RETURN;
- END;
- ELSE
- IF NOT PosUtils.Equal(delimiter1,delimiter2) THEN
- TwoDelimiters := TRUE;
- END;
- END;
- BytesDone := 0;
- MakeOneList( TheList );
- VStorage.DeallocMem( TheHandle, BlockSize );
- END HandleToList;
- (*$O-*)
- (*We turn off optimization for this procedure because of a bug in
- Logitech's v3.0.*)
- PROCEDURE ListToFileHandle( TheList: GenLists.GenList; TheHandle:
- CARDINAL; delim1, delim2: ARRAY OF CHAR;
- InitialNestingLevel: CARDINAL; VAR BytesWritten:
- LONGINT ): CARDINAL;
- VAR
- TmpAdr: SYSTEM.ADDRESS;
- LstCount, LstLngth, TypeCode, TmpSize, DumRecSz,
- Delim1Lngth, Delim2Lngth, tmpc: CARDINAL;
- SubList: GenLists.GenList;
- NilList, TwoDelimiters: BOOLEAN;
- SavedMessage: CARDINAL;
- TmpL, TmpBytesWritten: LONGINT;
- BEGIN
- BytesWritten := NumTypes.L0;
- Delim1Lngth := M2Strings.Length( delim1 );
- Delim2Lngth := M2Strings.Length( delim2 );
- TwoDelimiters := (Delim1Lngth > 0) AND (Delim2Lngth > 0);
- (*We begin and end the procedure by bracketing the
- entire block with a StartSep and EndSep, if the
- parameter list indicates that they're in use. That's
- the convention NdxFiles uses to indicate that the block
- as a whole represents a list.*)
- IF (Delim1Lngth > 0) AND (InitialNestingLevel = 0) THEN
- SavedMessage := HandleIO.BlockWrite( TheHandle,
- SYSTEM.ADR(delim1), Delim1Lngth );
- TmpL := Numbers.Lc(Delim1Lngth);
- (*Necessary because of a bug in Logitech's LONGINT
- addition.*)
- BytesWritten := BytesWritten + TmpL;
- END;
- IF TwoDelimiters AND (InitialNestingLevel = 0) THEN
- tmpc := GenLists.ListCode;
- (*We have to do this because some implementations won't
- give us the address of a constant.*)
- SavedMessage := HandleIO.BlockWrite( TheHandle,
- SYSTEM.ADR(tmpc), SYSTEM.TSIZE(CARDINAL) );
- BytesWritten := BytesWritten + Numbers.Lc(SYSTEM.TSIZE(CARDINAL));
- END;
- IF GenLists.Initialized( TheList ) THEN
- NilList := FALSE;
- ELSE
- GenLists.NewList( TheList );
- NilList := TRUE;
- END;
- GenLists.ListToBlock( TheList, delim1, delim2,
- TmpAdr, TmpSize, DumRecSz);
- IF (GenLists.ErrorFlag = GenLists.NoListError) THEN
- SavedMessage := HandleIO.BlockWrite( TheHandle,
- TmpAdr, TmpSize );
- (*Write the Ndx as a single block.*)
- VStorage.DosDealloc( TmpAdr, TmpSize);
- (*Get rid of temporary buffer space used.*)
- BytesWritten := BytesWritten + Numbers.Lc(TmpSize);
- IF (Delim2Lngth > 0) AND (InitialNestingLevel = 0) THEN
- SavedMessage := HandleIO.BlockWrite( TheHandle,
- SYSTEM.ADR(delim2), Delim2Lngth );
- BytesWritten := BytesWritten + Numbers.Lc(Delim2Lngth);
- END;
- IF NilList THEN
- GenLists.DisposeList( TheList );
- END;
- RETURN SavedMessage;
- END;
- (*Write the NdxElements one by one if there isn't
- enough memory to write them as a block.*)
- LstLngth := GenLists.ListLength( TheList );
- LstCount := 1;
- WHILE LstCount <= LstLngth DO
- GenLists.GetElmtAdr( TheList, LstCount, TmpAdr,
- TmpSize, TypeCode );
- IF Delim1Lngth > 0 THEN
- SavedMessage := HandleIO.BlockWrite( TheHandle,
- SYSTEM.ADR(delim1), Delim1Lngth );
- BytesWritten := BytesWritten + Numbers.Lc(Delim1Lngth);
- END;
- IF TwoDelimiters THEN
- SavedMessage := HandleIO.BlockWrite( TheHandle,
- SYSTEM.ADR(TypeCode), SYSTEM.TSIZE(CARDINAL) );
- BytesWritten := BytesWritten + Numbers.Lc(SYSTEM.TSIZE(CARDINAL));
- END;
- IF TypeCode = GenLists.ListCode THEN
- GenLists.GetChildList( TheList, LstCount, SubList );
- SavedMessage := ListToFileHandle( SubList, TheHandle,
- delim1, delim2, InitialNestingLevel + 1,
- TmpBytesWritten );
- BytesWritten := BytesWritten + TmpBytesWritten;
- IF SavedMessage # StringIO.NoError THEN
- IF NilList THEN
- GenLists.DisposeList( TheList );
- END;
- RETURN SavedMessage;
- END;
- ELSE
- SavedMessage := HandleIO.BlockWrite( TheHandle,
- TmpAdr, TmpSize );
- BytesWritten := BytesWritten + Numbers.Lc( TmpSize );
- END;
- IF Delim2Lngth > 0 THEN
- SavedMessage := HandleIO.BlockWrite( TheHandle,
- SYSTEM.ADR(delim2), Delim2Lngth );
- BytesWritten := BytesWritten + Numbers.Lc(Delim2Lngth);
- END;
- INC(LstCount);
- END;
- IF (Delim2Lngth > 0) AND (InitialNestingLevel = 0) THEN
- SavedMessage := HandleIO.BlockWrite( TheHandle,
- SYSTEM.ADR(delim2), Delim2Lngth );
- BytesWritten := BytesWritten + Numbers.Lc(Delim2Lngth);
- END;
- IF NilList THEN
- GenLists.DisposeList( TheList );
- END;
- RETURN SavedMessage;
- END ListToFileHandle;
- (*$O=*)
- PROCEDURE InsertElmtsOf( List1: GenLists.GenList; StartingAt,
- NumberOfLines: CARDINAL; VAR List2: GenLists.GenList;
- InsertionPoint: CARDINAL );
- VAR
- cnt, tmpsize, TypeCode, List2Lngth : CARDINAL;
- tmpadr: SYSTEM.ADDRESS;
- BEGIN
- NumberOfLines := Numbers.Min( NumberOfLines,
- GenLists.ListLength( List1 ) );
- List2Lngth := GenLists.ListLength( List2 );
- IF Numbers.Lc(InsertionPoint) +
- Numbers.Lc( NumberOfLines ) > NumTypes.L65535 THEN
- InsertionPoint := List2Lngth + 1;
- END;
- FOR cnt := 1 TO NumberOfLines DO
- GenLists.GetElmtAdr( List1, StartingAt + cnt - 1, tmpadr,
- tmpsize, TypeCode );
- GenLists.ListInsertAdr( tmpadr, tmpsize, TypeCode, List2,
- InsertionPoint + (cnt - 1) );
- END;
- END InsertElmtsOf;
- PROCEDURE InsertIntoElmt( VAR TheList: GenLists.GenList;
- ListSpot: CARDINAL; StrAdr: SYSTEM.ADDRESS; StrSize:
- CARDINAL; ElmtSpot: CARDINAL );
- VAR
- tmpadr1, tmpadr2: SYSTEM.ADDRESS;
- TypeCode, tmpsize: CARDINAL;
- BEGIN
- GenLists.GetElmtAdr( TheList, ListSpot, tmpadr1, tmpsize, TypeCode );
- (* Make sure we're inserting into a string. *)
- IF TypeCode # GenLists.StrCode THEN
- ErrorManager.WARN('Not a string');
- END;
- tmpsize := LowLevel.ScanEQ( tmpsize, 0C, tmpadr1 );
- (* This means you can insert your string at ElmtSpot 65535 and
- have it neatly appended. *)
- IF ElmtSpot > tmpsize THEN
- ElmtSpot := tmpsize;
- END;
- VStorage.DosAlloc( tmpadr2, tmpsize + StrSize );
- LowLevel.Move( tmpadr1, tmpadr2, ElmtSpot );
- LowLevel.Move( StrAdr, LowLevel.AddAddr(tmpadr2, ElmtSpot), StrSize );
- LowLevel.Move( LowLevel.AddAddr(tmpadr1, ElmtSpot),
- LowLevel.AddAddr(tmpadr2, ElmtSpot + StrSize), tmpsize - ElmtSpot );
- GenLists.ListReplaceAdr( tmpadr2, tmpsize + StrSize, GenLists.StrCode,
- TheList, ListSpot );
- VStorage.DosDealloc( tmpadr2, tmpsize + StrSize );
- END InsertIntoElmt;
- PROCEDURE IsBlankList( TheList: GenLists.GenList ): BOOLEAN;
- (*We use this procedure to test Editor fields that have been
- marked "required."*)
- VAR
- SomethingFound: BOOLEAN;
- lngth, cnt, TypeCode: CARDINAL;
- LocalStr: ARRAY [0..127] OF CHAR;
- BEGIN
- IF NOT GenLists.Initialized(TheList) THEN
- RETURN TRUE;
- END;
- SomethingFound := FALSE;
- lngth := GenLists.ListLength( TheList );
- cnt := 1;
- WHILE (cnt <= lngth) AND (NOT SomethingFound) DO
- GenLists.GetElmt( TheList, cnt, LocalStr, TypeCode );
- SomethingFound := (TypeCode # GenLists.StrCode) OR (NOT
- PosUtils.IsBlank( LocalStr ));
- INC(cnt);
- END;
- RETURN NOT SomethingFound;
- END IsBlankList;
- PROCEDURE ListToString( TheList: GenLists.GenList; VAR TheStr: ARRAY OF CHAR);
- VAR
- tmpstr: ARRAY [0..255] OF CHAR;
- lngth, TypeCode, cnt: CARDINAL;
- BEGIN
- lngth := GenLists.ListLength( TheList );
- StrEdit.SetLength( TheStr, 0 );
- FOR cnt := 1 TO lngth DO
- GenLists.GetElmt( TheList, cnt, tmpstr, TypeCode );
- IF TypeCode = GenLists.StrCode THEN
- StrEdit.Append( TheStr, tmpstr );
- END;
- END;
- END ListToString;
- PROCEDURE LongestLine( TheList: GenLists.GenList ): CARDINAL;
- VAR
- LstLngth, lngth, cnt, longest: CARDINAL;
- BEGIN
- LstLngth := GenLists.ListLength( TheList );
- longest := 0;
- FOR cnt := 1 TO LstLngth DO
- lngth := ElmtSize( TheList, cnt );
- IF lngth > longest THEN
- longest := lngth;
- END;
- END;
- RETURN longest;
- END LongestLine;
- PROCEDURE OverwriteElmt( VAR TheList: GenLists.GenList;
- ListSpot: CARDINAL; StrAdr: SYSTEM.ADDRESS; StrSize:
- CARDINAL; ElmtSpot: CARDINAL );
- VAR
- tmpadr1, tmpadr2: SYSTEM.ADDRESS;
- excess, TypeCode, tmpsize: CARDINAL;
- BEGIN
- GenLists.GetElmtAdr( TheList, ListSpot, tmpadr1, tmpsize, TypeCode );
- IF TypeCode # GenLists.StrCode THEN
- ErrorManager.WARN('Not a string');
- END;
- IF tmpsize >= (ElmtSpot + StrSize) THEN
- LowLevel.Move( StrAdr, LowLevel.AddAddr(tmpadr1, ElmtSpot), StrSize );
- ELSE
- excess := (ElmtSpot + StrSize) - tmpsize;
- VStorage.DosAlloc( tmpadr2, tmpsize + excess );
- LowLevel.Move( tmpadr1, tmpadr2, ElmtSpot );
- LowLevel.Move( StrAdr, LowLevel.AddAddr(tmpadr2, ElmtSpot), StrSize );
- GenLists.ListReplaceAdr( tmpadr2, tmpsize + excess,
- GenLists.StrCode, TheList, ListSpot );
- VStorage.DosDealloc( tmpadr2, tmpsize + excess );
- END;
- END OverwriteElmt;
- PROCEDURE ObjectSpot( BinaryObject : ARRAY OF SYSTEM.BYTE;
- TheList : GenLists.GenList; StartingAt, EndingAt :
- CARDINAL) : CARDINAL;
- VAR
- cnt, ListEnd, ObjSize, TmpSize, TypeCode : CARDINAL;
- TmpAdr : SYSTEM.ADDRESS;
- BEGIN
- (*ObjectSpot*)
- ListEnd := GenLists.ListLength( TheList );
- IF ListEnd < EndingAt THEN
- EndingAt := ListEnd;
- END;
- IF StartingAt > EndingAt THEN
- RETURN 0;
- END;
- ObjSize := HIGH( BinaryObject ) + 1;
- FOR cnt := StartingAt TO EndingAt DO
- GenLists.GetElmtAdr( TheList, cnt, TmpAdr, TmpSize, TypeCode );
- IF TmpSize = ObjSize THEN
- IF PosUtils.PatternScan( SYSTEM.ADR(BinaryObject), ObjSize,
- TmpAdr, TmpSize ) = 0 THEN
- RETURN cnt;
- END;
- END;
- END;
- RETURN 0;
- (*BinaryObject not found between StartingAt and EndingAt.*)
- END ObjectSpot;
- PROCEDURE PrintList( fhandle: CARDINAL; TheList : GenLists.GenList;
- LeftMargin: CARDINAL; Separator: ARRAY OF CHAR );
- PROCEDURE PrintRecursive( fhandle: CARDINAL; TheList :
- GenLists.GenList; Separator: ARRAY OF CHAR; InSubList:
- BOOLEAN );
- VAR
- SubLeader, TmpStr : ARRAY [0..80] OF CHAR;
- SubList : GenLists.GenList;
- TmpSiz, cnt, ListLen, TypeCode, spot : CARDINAL;
- FirstTime: BOOLEAN;
- TmpAdr: SYSTEM.ADDRESS;
- BEGIN
- IF InSubList THEN
- StringIO.PrintMessage( HandleIO.FillFile( fhandle,
- LeftMargin, ' ' ) );
- StringIO.WriteStr( fhandle, '{' );
- END;
- FirstTime := TRUE;
- spot := 1;
- ListLen := GenLists.ListLength(TheList);
- IF GenLists.ErrorFlag # GenLists.NoListError THEN
- ErrorManager.WARN('Uninitialized list?');
- END;
- REPEAT
- IF spot<=ListLen THEN
- GenLists.GetElmtAdr( TheList, spot, TmpAdr, TmpSiz, TypeCode );
- IF TypeCode=GenLists.ListCode THEN
- GenLists.GetChildList(TheList, spot, SubList);
- PrintRecursive( fhandle, SubList, Separator, TRUE);
- ELSE
- IF FirstTime THEN
- FirstTime := FALSE;
- ELSE
- StringIO.WriteStr( fhandle, Separator );
- END;
- IF TypeCode = GenLists.StrCode THEN
- GetStr( TheList, spot, TmpStr );
- IF PosUtils.Present( Separator, TmpStr ) THEN
- StringIO.WriteStr( fhandle, '"' );
- StringIO.WriteStr( fhandle, TmpStr );
- StringIO.WriteStr( fhandle, '"' );
- ELSE
- StringIO.PrintMessage( HandleIO.FillFile( fhandle,
- LeftMargin, ' ' ) );
- StringIO.WriteStr( fhandle, TmpStr );
- END;
- ELSE
- StrConv.CardinalToStr( spot, 2, TmpStr );
- StringIO.PrintMessage( HandleIO.FillFile( fhandle,
- LeftMargin, ' ' ) );
- StringIO.WriteStr( fhandle, TmpStr );
- StringIO.WriteStr( fhandle, ': ' );
- StringIO.WriteStr( fhandle, 'Size = ' );
- StrConv.CardinalToStr( TmpSiz, 4, TmpStr );
- StringIO.WriteStr( fhandle, TmpStr );
- StringIO.WriteStr( fhandle, '; Type = ' );
- StrConv.CardinalToStr( TypeCode, 0, TmpStr );
- StringIO.WriteStr( fhandle, TmpStr );
- END;
- END;
- END;
- INC(spot);
- UNTIL spot>ListLen;
- IF InSubList THEN
- StringIO.WriteStr( fhandle, '}' );
- END;
- END PrintRecursive;
- BEGIN (* PrintList *)
- PrintRecursive( fhandle, TheList, Separator, FALSE );
- (*We don't call PrintList itself recursively because we
- don't want the CrLf from the WriteEol below to follow
- embedded lists.*)
- StringIO.WriteEol( fhandle, '' );
- END PrintList;
- PROCEDURE TextFileToList( VAR TheFile: ARRAY OF CHAR;
- VAR TheList: GenLists.GenList): CARDINAL;
- (* finds the file, reads it into the list, closes the file *)
- VAR
- SizeLeft, SizeOK, DoSizeL : LONGINT;
- ResultErr: CARDINAL;
- NextList: GenLists.GenList;
- DoSizeC, TheHandl : CARDINAL;
- GoBack : INTEGER;
- buffer: SYSTEM.ADDRESS;
- BEGIN
- IF NOT GenLists.Initialized( TheList ) THEN
- InitResponse( 'TextFileToList' );
- END;
- ResultErr := HandleIO.FindFile( TheHandl, TheFile, 'PATH');
- IF StringIO.NoError # ResultErr THEN
- RETURN ResultErr;
- END;
- SizeLeft := HandleIO.FileLength( TheHandl);
- WHILE SizeLeft # Numbers.Lc( 0) DO
- (* first, get a mem block <= 65000 bytes *)
- DoSizeC := 65000;
- IF NOT VStorage.DosAvail( DoSizeC) THEN
- (* If there's not a 64K chunk available, get as much as there
- is.*)
- DoSizeC := EnvironUtils.MemAvail( 100);
- END;
- SizeOK := Numbers.Lc( DoSizeC);
- IF ( SizeLeft > SizeOK)
- AND ( Numbers.Lc( 64000) > SizeLeft) THEN
- GenLists.DisposeList( TheList );
- ResultErr := HandleIO.CloseHandle( TheHandl);
- RETURN StringIO.TooLittleMemory;
- END;
- IF SizeLeft > SizeOK THEN
- DoSizeL := SizeOK;
- ELSE
- DoSizeL := SizeLeft;
- END;
- SizeLeft := SizeLeft - DoSizeL;
- DoSizeC := Numbers.C( DoSizeL );
- IF NOT VStorage.DosAvail( DoSizeC ) THEN
- ResultErr := HandleIO.CloseHandle( TheHandl);
- RETURN StringIO.TooLittleMemory;
- END;
- VStorage.DosAlloc( buffer, DoSizeC );
- ResultErr := HandleIO.BlockRead( TheHandl, buffer, DoSizeC);
- IF StringIO.NoError # ResultErr THEN
- ResultErr := HandleIO.CloseHandle( TheHandl);
- RETURN ResultErr;
- END;
- IF SizeLeft # Numbers.Lc( 0) THEN
- GoBack := LowLevel.ScanEQ( -32000, 12C,
- LowLevel.AddAddr(buffer, DoSizeC - 1) );
- (* to locate a cut-ff line, look for the last
- line-feed character before the end of the block *)
- IF GoBack = -32000 THEN
- (* No LF found in last 32000 bytes of block *)
- ResultErr := HandleIO.CloseHandle( TheHandl);
- RETURN StringIO.BadData;
- END;
- DoSizeL := Numbers.Lc( -GoBack );
- SizeLeft := SizeLeft + DoSizeL;
- DoSizeL := -DoSizeL;
- HandleIO.SetFilePtr( TheHandl, HandleIO.FromCurrent, DoSizeL);
- (* change file position and counters to start from
- beginning of the line that was cut off *)
- END;
- GenLists.NewList( NextList );
- GenLists.BlockToList( buffer, DoSizeC, StringIO.CrLf,
- StringIO.CrLf, 0, GenLists.StrCode, NextList);
- GenLists.JoinLists( NextList, TheList, 65535);
- END;
- ResultErr := HandleIO.CloseHandle( TheHandl);
- RETURN ResultErr;
- END TextFileToList;
- PROCEDURE TextListToFile( VAR TheList: GenLists.GenList;
- TheFile: ARRAY OF CHAR): CARDINAL;
- (* creates the file; writes the list to it and closes file *)
- VAR
- StrAdr1, StrAdr2: SYSTEM.ADDRESS;
- StrSize, DumType, SizeL, TheHandl, cnt: CARDINAL;
- ResultErr: CARDINAL;
- TmpCrLf: ARRAY [0..2] OF CHAR;
- BEGIN
- StrEdit.AssignStr( StringIO.CrLf, TmpCrLf );
- ResultErr := HandleIO.CreateFile( TheHandl, TheFile);
- IF StringIO.NoError # ResultErr THEN
- RETURN ResultErr;
- END;
- SizeL := GenLists.ListLength( TheList);
- FOR cnt := 1 TO SizeL DO
- GenLists.GetElmtAdr( TheList, cnt, StrAdr1, StrSize, DumType);
- StrSize := LowLevel.ScanEQ( StrSize, 0C, StrAdr1 );
- (* Reduce StrSize to number of bytes before the null. *)
- VStorage.DosAlloc( StrAdr2, StrSize + 2 );
- LowLevel.Move( StrAdr1, StrAdr2, StrSize );
- LowLevel.Move( SYSTEM.ADR(TmpCrLf),
- LowLevel.AddAddr(StrAdr2, StrSize), 2 );
- ResultErr := HandleIO.BlockWrite( TheHandl,
- StrAdr2, StrSize + 2 );
- VStorage.DosDealloc( StrAdr2, StrSize + 2 );
- IF StringIO.NoError # ResultErr THEN
- RETURN ResultErr;
- END;
- END;
- ResultErr := HandleIO.CloseHandle( TheHandl);
- RETURN ResultErr;
- END TextListToFile;
- PROCEDURE TypeCheck( TheList: GenLists.GenList; spot: CARDINAL ): CARDINAL;
- VAR
- DumAddr: SYSTEM.ADDRESS;
- TheSize, TypeCode: CARDINAL;
- BEGIN
- GenLists.GetElmtAdr( TheList, spot, DumAddr, TheSize, TypeCode );
- RETURN TypeCode;
- END TypeCheck;
- BEGIN
- Initialized := FALSE;
- Init();
- END ListUtils.
|