summaryrefslogtreecommitdiff
path: root/src/SearchTable.pas
diff options
context:
space:
mode:
authorGraeme Geldenhuys <graeme@mastermaths.co.za>2009-09-29 16:38:12 +0200
committerGraeme Geldenhuys <graeme@mastermaths.co.za>2009-09-29 16:38:12 +0200
commit6c9bd169bdcab488387518eb071532f1e62c564a (patch)
tree772020b52e93506aa4d4c30cbe96a5e668c1836d /src/SearchTable.pas
parent9b0b9ab54c4d1d4f9e3627747ece6a988968b412 (diff)
downloadfpGUI-6c9bd169bdcab488387518eb071532f1e62c564a.tar.xz
Add more INF required units. Converted them all to be FPC compatible.
Signed-off-by: Graeme Geldenhuys <graeme@mastermaths.co.za>
Diffstat (limited to 'src/SearchTable.pas')
-rw-r--r--src/SearchTable.pas297
1 files changed, 297 insertions, 0 deletions
diff --git a/src/SearchTable.pas b/src/SearchTable.pas
new file mode 100644
index 00000000..ffbd3ee9
--- /dev/null
+++ b/src/SearchTable.pas
@@ -0,0 +1,297 @@
+Unit SearchTable;
+
+{$mode objfpc}{$H+}
+
+// NewView - a new OS/2 Help Viewer
+// Copyright 2001 Aaron Lawrence (aaronl at consultant dot com)
+// This software is released under the Gnu Public License - see readme.txt
+
+Interface
+
+uses
+ Classes, DataTypes;
+
+// Code to read and use IPF search tables
+// NB The RLE decompression was arrived at by trial and error
+// it seems to be correct but it's difficult to test.
+
+type
+ TSearchTable = class
+ protected
+ _Data: pointer;
+ _Entries: TList; // pointers to panel flag records
+ _RecordLengthIs16Bit: boolean;
+ _DictionaryCount: longint;
+ _TopicCount: longint;
+
+ procedure ReadEntries;
+
+ Procedure Check1ByteOfFlags( b: byte;
+ StartingIndex: longint;
+ Results: Int32ArrayPointer );
+
+ procedure DoRLESearch( p: pbyte;
+ pDataEnd: pointer;
+ Results: Int32ArrayPointer );
+
+ public
+ constructor Create( Data: pointer;
+ RecordLengthIs16Bit: boolean;
+ DictionaryCount: longint;
+ TopicCount: longint );
+ destructor Destroy; override;
+
+ procedure Search( DictIndex: int16;
+ Results: Int32ArrayPointer );
+
+ end;
+
+Implementation
+
+constructor TSearchTable.Create( Data: pointer;
+ RecordLengthIs16Bit: boolean;
+ DictionaryCount: longint;
+ TopicCount: longint );
+begin
+ _Data := Data;
+ _RecordLengthIs16Bit :=
+ RecordLengthIs16Bit;
+ _Entries := TList.Create;
+ _DictionaryCount := DictionaryCount;
+ _TopicCount := TopicCount;
+ ReadEntries;
+end;
+
+destructor TSearchTable.Destroy;
+begin
+ _Entries.Destroy;
+end;
+
+procedure TSearchTable.ReadEntries;
+var
+ pWordRecord: pointer;
+ RecordLen: int16;
+ WordIndex: int16;
+begin
+ pWordRecord:= _Data;
+
+ for WordIndex:= 0 to _DictionaryCount - 1 do
+ begin
+ _Entries.Add( pWordRecord );
+
+ if _RecordLengthIs16Bit then
+ RecordLen:= pint16( pWordRecord )^
+ else // 8 bit
+ RecordLen:= pint8( pWordRecord )^;
+ inc( pWordRecord, RecordLen );
+ end;
+end;
+
+
+// Search table decompression
+
+// Looks through a single byte of 8 flags, given by b,
+// and updates topic entries within results for any flags
+// that are set.
+Procedure TSearchTable.Check1ByteOfFlags( b: byte;
+ StartingIndex: longint;
+ Results: Int32ArrayPointer );
+var
+ TopicIndex: longint;
+begin
+ TopicIndex:= StartingIndex;
+ while b > 0 do
+ begin
+ if b and $80 > 0 then
+ Results^[ TopicIndex ] := 1;
+ inc( TopicIndex );
+ b:= b shl 1;
+ end;
+end;
+
+// Decompress RLE compressed data starting at p,
+// running til pDataEnd. Update topic entries in Results.
+procedure TSearchTable.DoRLESearch( p: pbyte;
+ pDataEnd: pointer;
+ Results: Int32ArrayPointer );
+var
+ TopicIndex: integer;
+
+ N: integer;
+ thebyte: byte;
+ byte1, byte2: byte;
+begin
+ assert( pbyte( p )^ = 1, 'Unexpected RLE type' );
+ inc( p ); // skip header, always 1?
+
+ TopicIndex:= 0;
+
+ while p < pDataEnd do
+ begin
+ thebyte:= p^;
+ inc( p );
+
+ if thebyte = $80 then
+ begin
+ // escape
+ thebyte := p^;
+ inc( p );
+
+ if thebyte = 0 then
+ begin
+ // 16 bit repeat of zeroes??
+ N := pint16( p )^ + 1;
+ inc( p, 2 );
+ inc( TopicIndex, N );
+ end
+ else
+ begin
+ // n+1 repeats of next 2 bytes???
+ N := thebyte + 1;
+ byte1 := p^;
+ inc( p );
+ byte2 := p^;
+ inc( p );
+ while N > 0 do
+ begin
+ Check1ByteOfFlags( byte1,
+ TopicIndex,
+ Results );
+ inc( TopicIndex, 8 );
+ Check1ByteOfFlags( byte2,
+ TopicIndex,
+ Results );
+ inc( TopicIndex, 8 );
+ dec( N );
+ end;
+ end;
+ end
+ else
+ begin
+ N:= thebyte and $7f + 1;
+
+ if thebyte and $80 > 0 then
+ begin
+ // literal data
+ while N > 0 do
+ begin
+ Check1ByteOfFlags( p^,
+ TopicIndex,
+ Results );
+ inc( TopicIndex, 8 );
+ inc( p );
+ dec( N );
+ end;
+ end
+ else
+ begin
+ // repeat of next byte
+ thebyte := p^;
+ inc( p );
+ while N > 0 do
+ begin
+ Check1ByteOfFlags( thebyte,
+ TopicIndex,
+ Results );
+ inc( TopicIndex, 8 );
+ dec( N );
+ end;
+ end;
+ end;
+ end;
+end;
+
+// This function finds uses of the given word (DictIndex)
+// using the search table. Results[ topic ] is set to
+// non-zero for topics which contain the word.
+procedure TSearchTable.Search( DictIndex: int16;
+ Results: Int32ArrayPointer );
+var
+ TopicIndex: integer;
+ pWordRecord: pointer;
+ RecordLen: int16;
+ CompressionCode: int8;
+ pData: pointer;
+ pDataEnd: pointer;
+ Flags: int8;
+begin
+ FillInt32Array( Results, _TopicCount, 0 );
+
+ pWordRecord:= _Entries[ DictIndex ];
+
+ // Check search table format
+ if _RecordLengthIs16Bit then
+ begin
+ RecordLen:= pint16( pWordRecord )^;
+ CompressionCode:= pint8( pWordRecord + 2 )^;
+ pData:= pWordRecord + 3;
+ end
+ else // 8 bit
+ begin
+ RecordLen:= pint8( pWordRecord )^;
+ CompressionCode:= pint8( pWordRecord + 1 )^;
+ pData:= pWordRecord + 2;
+ end;
+
+ // Decompress the search table for this word
+ pDataEnd:= pWordRecord + RecordLen;
+ case CompressionCode of
+ 0: // word not used anywhere.
+ ;
+
+ 1: // used in all panels
+ FillInt32Array( Results, _TopicCount, 1 );
+
+ 2: // RLE
+ begin
+ DoRLESearch( pData,
+ pDataEnd,
+ Results );
+ end;
+
+ 3: // list of topics containing word
+ while pData < pDataEnd do
+ begin
+ TopicIndex:= pint16( pData )^;
+ Results^[ TopicIndex ] := 1;
+ inc( pData, 2 );
+ end;
+
+ 4: // list of topics NOT containing word
+ begin
+ FillInt32Array( Results, _TopicCount, 1 );
+
+ while pData < pDataEnd do
+ begin
+ TopicIndex:= pint16( pData )^;
+ Results^[ TopicIndex ] := 0;
+ inc( pData, 2 );
+ end;
+ end;
+
+ 5, // compressed by truncating bit stream at last byte containing a set bit.
+ 6: // same as above but starting at non-zero byte
+ begin
+ if CompressionCode = 5 then
+ TopicIndex:= 0
+ else
+ begin
+ TopicIndex:= pInt16( pData )^ * 8;
+ inc( pData, 2 );
+ end;
+
+ while pData < pDataEnd do
+ begin
+ Flags:= pInt8( pData )^;
+ Check1ByteOfFlags( Flags,
+ TopicIndex,
+ Results );
+ inc( TopicIndex, 8 );
+ inc( pData );
+ end;
+ end;
+ end;
+end;
+
+Initialization
+End.