anchor.diff:  {$mode objfpc}{$H+}
   
   // NewView - a new OS/2 Help Viewer
  -// Copyright 2001 Aaron Lawrence (aaronl at consultant dot com)
  +// Copyright 2003 Aaron Lawrence (aaronl at consultant dot com)
   // This software is released under the Gnu Public License - see readme.txt
   
   Interface
  
positive.code:   IndexIndex: longint;
    IndexEntry: string;
    IndexEntryWord: string;
    Topic: TTopic;
    IndexEntryWordIndex: longint;
    WordRelevance: longint;
    IndexEntryWordRelevance: longint;
  begin
    for IndexIndex:= 0 to HelpFile.Index.Count - 1 do
    begin
      Topic:= HelpFile.Index.Objects[ IndexIndex ] as TTopic;
      IndexEntry:= HelpFile.Index[ IndexIndex ];
      IndexEntryWordIndex := 0;
      while IndexEntry <> '' do
      begin
        IndexEntryWord:= ExtractNextValue( IndexEntry, ' ' );
        WordRelevance := CompareWord( SearchWord, IndexEntryWord );
        if WordRelevance > 0 then
        begin
          if IndexEntryWordIndex = 0 then
            // matching the first word is best
            IndexEntryWordRelevance := mwFirstIndexWord * WordRelevance
          else
            IndexEntryWordRelevance := mwIndexWord * WordRelevance;
          inc( Results^[ Topic.Index ], IndexEntryWordRelevance );
        end;
        inc( IndexEntryWordIndex );
      end;
    end;
  end;
  
  // Utility function used in decompression of search table.
  // Updates the appropriate entry in Results array.
  // The word being matched is given in DictIndex and is
  // used to count the actual occurrences of the word
  // within the topic
  {procedure AddTopicFoundInTopicText( TopicIndex: int16;
                                      Results: Int32ArrayPointer;
                                       DictIndex: longint;
                                                WordRelevance: longint );
  var
    Topic: TTopic;
    Relevance: longint;
  begin
    Topic:= _Topics[ TopicIndex ];
    Relevance := mwTopicTextWord
              * Topic.CountWord( DictIndex )
              * WordRelevance;
    inc( Results^[ TopicIndex ], Relevance );
  
  end;}
  
  // ------------------------------------------------------
  
  
negative.code: //  ACLUtility, ACLStringUtility,
    HelpTopic, CompareWordUnit, nvUtilities;
  
  type
    TSearchType = ( stGeneral, stStarts, stExactMatch, stEnds );
  
  procedure ClearWordSequence( WordSequence: TList;
                               DictionaryCount: longint );
  var
    StepIndex: longint;
    DictionaryRelevances: UInt32ArrayPointer;
  begin
    for StepIndex := 0 to WordSequence.Count - 1 do
    begin
      DictionaryRelevances := WordSequence[ StepIndex ];
      FreeUInt32Array( DictionaryRelevances, DictionaryCount );
    end;
    WordSequence.Clear;
  end;
  
  procedure ClearWordSequences( WordSequence: TList;
                                DictionaryCount: longint );
  var
    SequenceIndex: longint;
    WordSequence: TList;
  begin
    for SequenceIndex := 0 to WordSequences.Count - 1 do
    begin
      WordSequence := WordSequences[ SequenceIndex ];
      ClearWordSequence( WordSequence, DictionaryCount );
      WordSequence.Destroy;
    end;
    WordSequences.Clear;
  end;
  
  // given a search word which is known to matche Reference word,
  // return the relevance
  function MatchedWordRelevance( const SearchWord: string;
                                 const ReferenceWord: string ): longint;
  begin
    Result := mwExactWord
              * Length( SearchWord )
              div Length( ReferenceWord );
    if Result = 0 then
      Result := 1;
  end;
  
  // Compares the given search word against the given
  // reference word. Returns a value indicating how well the
  // search word matches, 0 = not at all.
  function CompareWord( const SearchWord: string;
                        const ReferenceWord: string ): longint;
  var
    OccurrencePos: longint;
  begin
    Result := 0;
    OccurrencePos := CaseInsensitivePos( SearchWord, ReferenceWord );
    if OccurrencePos = 0 then
    begin
      // no match
      exit;
    end;
  
    Result := MatchedWordRelevance( SearchWord, ReferenceWord );
  end;
  
  // Search the help file dictionary for words that match
  // the given search word. Partial matches are considered.
  // Results returns the matching word indexes.
  procedure SearchDictionary( HelpFile: THelpFile;
                              SearchWord: string;
                              Results: UInt32ArrayPointer );
  var
    DictIndex: integer;
    pDictWord: pstring;
  begin
    for DictIndex := 0 to HelpFile.DictionaryCount - 1 do
    begin
      pDictWord := HelpFile.DictionaryWordPtrs[ DictIndex ];
      Results[ DictIndex ] := CompareWord( SearchWord,
                                           pDictWord^ );
    end;
  end;
  
  // Search the help file dictionary for words that
  // match the given search word exactly (except for case-insensitive)
  procedure SearchDictionaryExact( HelpFile: THelpFile;
                                   SearchWord: string;
                                   Results: UInt32ArrayPointer );
  var
    DictIndex: integer;
    pDictWord: pstring;
  begin
    FillUInt32Array( Results, HelpFile.DictionaryCount, 0 );
  
    for DictIndex := 0 to HelpFile.DictionaryCount - 1 do
    begin
      pDictWord := HelpFile.DictionaryWordPtrs[ DictIndex ];
      if StrEqualIgnoringCase( SearchWord, pDictWord^ ) then
        Results[ DictIndex ] := mwExactWord;
    end;
  end;
  
  // Search the help file dictionary for words that
  // start with the given word
  procedure SearchDictionaryStarts( HelpFile: THelpFile;
                                    SearchWord: string;
                                    Results: UInt32ArrayPointer );
  var
    DictIndex: integer;
    DictWord: string;
  begin
    FillUInt32Array( Results, HelpFile.DictionaryCount, 0 );
  
    for DictIndex := 0 to HelpFile.DictionaryCount - 1 do
    begin
      DictWord := HelpFile.DictionaryWords[ DictIndex ];
      if StrStartsWithIgnoringCase(DictWord, SearchWord) then
        Results[ DictIndex ] := MatchedWordRelevance( SearchWord, DictWord );
    end;
  end;
  
  // Search the help file dictionary for words that
  // end with the given word
  procedure SearchDictionaryEnds( HelpFile: THelpFile;
                                  SearchWord: string;
                                  Results: UInt32ArrayPointer );
  var
    DictIndex: integer;
    DictWord: string;
  begin
    FillUInt32Array( Results, HelpFile.DictionaryCount, 0 );
  
    for DictIndex := 0 to HelpFile.DictionaryCount - 1 do
    begin
      DictWord := HelpFile.DictionaryWords[ DictIndex ];
      if StrEndsWithIgnoringCase( SearchWord, DictWord ) then
        Results^[ DictIndex ] := MatchedWordRelevance( SearchWord, DictWord );
    end;
  end;
  
  