Why Gemfury? Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Debian packages RPM packages NuGet packages

Repository URL to install this package:

Details    
fpc-src / usr / share / fpcsrc / 3.0.0 / packages / chm / examples / chmsearch.lpr
Size: Mime:
program chmsearch;
{ Fulltext search demo by Reinier Olislagers}
{$mode objfpc}{$H+}

uses
  Classes, SysUtils, ChmReader, chmfiftimain;


type
  TChmWLCTopic = record
    TopicIndex: DWord;
    LocationCodes: array of DWord;
  end;

  TChmWLCTopicArray = array of TChmWLCTopic;

procedure DoSearch(CHMFileName: string; Keyword: string);
type
  TTopicEntry = record
    Topic:Integer;
    Hits: Integer;
    TitleHits: Integer;
    FoundForThisRound: Boolean;
  end;
  TFoundTopics = array of TTopicEntry;
var
  FoundTopics: TFoundTopics;

  procedure DeleteTopic(ATopicIndex: Integer);
  var
    MoveSize: DWord;
  begin
    WriteLn('Deleting Topic');
    if ATopicIndex < High(FoundTopics) then
    begin
      MoveSize := SizeOf(TTopicEntry) * (High(FoundTopics) - (ATopicIndex+1));
      Move(FoundTopics[ATopicIndex+1], FoundTopics[ATopicIndex], MoveSize);
    end;
    SetLength(FoundTopics, Length(FoundTopics) -1);
  end;

  function GetTopicIndex(ATopicID: Integer): Integer;
  var
    i: Integer;
  begin
    Result := -1;
    for i := 0 to High(FoundTopics) do
    begin
      if FoundTopics[i].Topic = ATopicID then
        Exit(i);
    end;
  end;

  procedure UpdateTopic(TopicID: Integer; NewHits: Integer; NewTitleHits: Integer; AddNewTopic: Boolean);
  var
    TopicIndex: Integer;
  begin
    //WriteLn('Updating topic');
    TopicIndex := GetTopicIndex(TopicID);
    if TopicIndex = -1 then
    begin
      if AddNewTopic = False then
        Exit;
      SetLength(FoundTopics, Length(FoundTopics)+1);
      TopicIndex := High(FoundTopics);
      FoundTopics[TopicIndex].Topic := TopicID;
    end;

    FoundTopics[TopicIndex].FoundForThisRound := True;
    if NewHits > 0 then
      Inc(FoundTopics[TopicIndex].Hits, NewHits);
    if NewTitleHits > 0 then
      Inc(FoundTopics[TopicIndex].TitleHits, NewTitleHits);
  end;

var
  CHMRead: TCHMReader;
  CHMStream: TFileStream;
  TopicResults: chmfiftimain.TChmWLCTopicArray;
  TitleResults: chmfiftimain.TChmWLCTopicArray;
  FIftiMainStream: TMemoryStream;
  SearchReader: TChmSearchReader;
  DocTitle: String;
  DocURL: String;
  CurrTopic: Integer;
  k: Integer;

begin
  CHMStream := TFileStream.Create(CHMFileName, fmOpenRead or fmShareDenyWrite);
  ChmRead := TChmReader.Create(CHMStream,false);
  try
    FIftiMainStream := CHMRead.GetObject('/$FIftiMain');
    if FIftiMainStream = nil then
    begin
      writeln('Could not assign fiftimainstream. Aborting.');
      halt(3);
    end;
    SearchReader := TChmSearchReader.Create(FIftiMainStream, True); //frees the stream when done
    CHMRead.SearchReader := SearchReader;
    TopicResults := SearchReader.LookupWord(Keyword, TitleResults);
    //TopicResults := SearchReader.LookupWord(SearchWords[CurrTopic], TitleResults);
    // Body results
    for k := 0 to High(TopicResults) do
    begin
      UpdateTopic(TopicResults[k].TopicIndex, High(TopicResults[k].LocationCodes), 0, CurrTopic = 0);
      writeln('Updated topic body with index '+inttostr(TopicResults[k].TopicIndex));
    end;
    // Title results
    for k := 0 to High(TitleResults) do
    begin
      UpdateTopic(TitleResults[k].TopicIndex, 0, High(TitleResults[k].LocationCodes), CurrTopic = 0);
      writeln('Updated title topic with index '+inttostr(TitleResults[k].TopicIndex));
    end;

    // Remove documents that don't have results
    k := 0;
    writeln('Going to remove docs without results; count: '+Inttostr(Length(FoundTopics)));
    while k <= High(FoundTopics) do
    begin
      if FoundTopics[k].FoundForThisRound = False then
        DeleteTopic(k)
      else
      begin
        FoundTopics[k].FoundForThisRound := False;
        Inc(k);
      end;
    end;

    // Clear out results that don't contain all the words we are looking for
    // Now lookup titles and urls to add to final search results
    writeln('Found '+inttostr(Length(FoundTopics))+' topics');
    for CurrTopic := 0 to High(FoundTopics) do
    begin
      try
        DocURL := CHMRead.LookupTopicByID(FoundTopics[CurrTopic].Topic, DocTitle);
        if (Length(DocURL) > 0) and (DocURL[1] <> '/') then
          Insert('/', DocURL, 1);
        if DocTitle = '' then
          DocTitle := 'untitled';
        writeln('DocURL    : '+DocURL);
        writeln('DocTitle  : '+DocTitle);
      except
        on E: Exception do
        begin
          WriteLn('Exception');
          writeln(E.Message);
        end;
      end;
    end;
  finally
    CHMRead.Free;
    CHMStream.Free;
    //SearchReader.Free; //apparently not needed?!?!
  end;
end;

var
  SearchFor: string;
begin
  if paramstr(1)='' then
  begin
    writeln('No .chm file specified.');
    writeln('Substituting hardcoded value lcl.chm');
  end;
  writeln('Enter search keyword or blank to exit:');
  readln(SearchFor);
  while (trim(SearchFor)<>'') do
  begin
    if paramstr(1)='' then
      DoSearch('lcl.chm',SearchFor)
    else
      DoSearch(paramstr(1),SearchFor);
    writeln('Enter search keyword or blank to exit:');
    readln(SearchFor);
  end;
end.