summaryrefslogtreecommitdiff
path: root/docview/src/CompareWordUnit.pas
blob: 05f32cc82eabae3a3baaccffcf62a3d66a1048c4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
Unit CompareWordUnit;

{$mode objfpc}{$H+}

interface

// Compares words and produces a match level (relevance) based
// on the relative sizes etc. Used in searching help files
// to sort by relevance.

const
  // word weightings
  mwExactWord = 20;
  mwWordStart = 10;
  mwWordWithin = 5;

// 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;


implementation

uses
  SysUtils;

// Looks for string a within string b, case insensitively
function CaseInsensitivePos( const a, b: string ): longint;
begin
  // Budget implementation to begin with.
  Result := Pos( UpperCase( a ), UpperCase( b ) );
end;

function CompareWord( const SearchWord: string;
                      const ReferenceWord: string ): longint;
var
  OccurrencePos: longint;
begin
  Result := 0;
  // First up, if the word we're searching for is longer than
  // this word, then it can't match at all.
  if Length( SearchWord ) > Length( ReferenceWord ) then
    exit;

  OccurrencePos := CaseInsensitivePos( SearchWord, ReferenceWord );
  if OccurrencePos = 0 then
    // no match.
    exit;

  if Length( SearchWord ) = Length( ReferenceWord ) then
  begin
    // exact word match (except case)
    Result := mwExactWord;
    exit;
  end;

  // partial word match
  if OccurrencePos = 1 then
  begin
    // word starts with searchword
    Result := mwWordStart * Length(SearchWord) div Length(ReferenceWord);
    if Result = 0 then
      Result := 1;
    exit;
  end;

  // Matched searchword somewhere within word
  Result := mwWordWithin * Length(SearchWord) div Length(ReferenceWord);
  if Result = 0 then
    Result := 1;
end;

{// Note: searchstring must be uppercase,
function IsMatching( const SearchString: string;
                     const SearchType: TSearchType;
                     const Item: string ): boolean;
var
  temp: string;
begin
  case SearchType of
    stStarts:
       Result:= StrStarts( SearchString, Item );

    stContains:
    begin
      temp:= UpperCase( Item );
      Result:= Pos( SearchString, temp ) <> 0;
    end;

    stMatches:
      Result:= CompareText( SearchString,
                            Item )= 0;
  end;
end;
}

end.