1 {
2 Copyright (C) Alexey Torgashin, uvviewsoft.com
3 License: MPL 2.0 or LGPL
4 }
5 unit ATSynEdit_LinkCache;
6 
7 {$mode objfpc}{$H+}
8 {$ModeSwitch advancedrecords}
9 
10 interface
11 
12 uses
13   SysUtils,
14   ATSynEdit_fgl;
15 
16 const
17   cMaxLinksPerLine = 15;
18 
19 type
20   TATLinkPair = record
21     NFrom, NLen: integer;
22   end;
23 
24   PATLinkArray = ^TATLinkArray;
25   TATLinkArray = array[0..cMaxLinksPerLine-1] of TATLinkPair;
26 
27 type
28   { TATLinkCacheItem }
29 
30   PATLinkCacheItem = ^TATLinkCacheItem;
31   TATLinkCacheItem = record
32     LineIndex: integer;
33     Data: TATLinkArray;
34     class operator =(const a, b: TATLinkCacheItem): boolean;
35   end;
36 
37   TATLinkCache = class(specialize TFPGList<TATLinkCacheItem>)
38   private
39     FMaxCount: integer;
40     procedure SetMaxCount(AValue: integer);
41   public
42     property MaxCount: integer read FMaxCount write SetMaxCount;
43     constructor Create;
FindDatanull44     function FindData(ALineIndex: integer): PATLinkArray;
45     procedure AddData(ALineIndex: integer; const AData: TATLinkArray);
46     procedure DeleteData(ALineIndex: integer);
47     procedure DeleteDataOutOfRange(ALine1, ALine2: integer);
DebugTextnull48     function DebugText: string;
49   end;
50 
51 implementation
52 
CompareItemsnull53 function CompareItems(const a, b: TATLinkCacheItem): integer;
54 begin
55   Result:= a.LineIndex - b.LineIndex;
56 end;
57 
58 { TATLinkCacheItem }
59 
60 class operator TATLinkCacheItem.=(const a, b: TATLinkCacheItem): boolean;
61 begin
62   Result:= false;
63 end;
64 
65 { TATLinkCache }
66 
67 procedure TATLinkCache.SetMaxCount(AValue: integer);
68 begin
69   if FMaxCount=AValue then Exit;
70   FMaxCount:= AValue;
71   if FMaxCount<2 then
72     FMaxCount:= 2;
73 
74   while Count>FMaxCount do
75     Delete(0);
76 end;
77 
78 constructor TATLinkCache.Create;
79 begin
80   inherited Create;
81   MaxCount:= 80;
82 end;
83 
FindDatanull84 function TATLinkCache.FindData(ALineIndex: integer): PATLinkArray;
85 var
86   Ptr: PATLinkCacheItem;
87   a, b, m: integer;
88   dif: integer;
89 begin
90   a:= 0;
91   b:= Count-1;
92   while a<=b do
93   begin
94     m:= (a+b+1) div 2;
95     Ptr:= PATLinkCacheItem(InternalGet(m));
96     dif:= Ptr^.LineIndex-ALineIndex;
97     if dif=0 then
98       exit(@Ptr^.Data);
99     if dif<0 then
100       a:= m+1
101     else
102       b:= m-1;
103   end;
104   Result:= nil;
105 end;
106 
107 procedure TATLinkCache.AddData(ALineIndex: integer; const AData: TATLinkArray);
108 var
109   Item: TATLinkCacheItem;
110 begin
111   Item.LineIndex:= ALineIndex;
112   Item.Data:= AData;
113   Add(Item);
114   Sort(@CompareItems);
115 end;
116 
117 procedure TATLinkCache.DeleteData(ALineIndex: integer);
118 var
119   Ptr: PATLinkCacheItem;
120   i: integer;
121 begin
122   for i:= 0 to Count-1 do
123   begin
124     Ptr:= InternalGet(i);
125     if Ptr^.LineIndex=ALineIndex then
126     begin
127       Delete(i);
128       exit;
129     end;
130   end;
131 end;
132 
133 procedure TATLinkCache.DeleteDataOutOfRange(ALine1, ALine2: integer);
134 var
135   Ptr: PATLinkCacheItem;
136   i: integer;
137 begin
138   for i:= Count-1 downto 0 do
139   begin
140     Ptr:= InternalGet(i);
141     if (Ptr^.LineIndex<ALine1) or (Ptr^.LineIndex>ALine2) then
142       Delete(i);
143   end;
144 end;
145 
DebugTextnull146 function TATLinkCache.DebugText: string;
147 var
148   Ptr: PATLinkCacheItem;
149   iCache, iPair: integer;
150 begin
151   Result:= '';
152   for iCache:= 0 to Count-1 do
153   begin
154     Ptr:= InternalGet(iCache);
155     Result+= '['+IntToStr(Ptr^.LineIndex)+'] ';
156     for iPair:= 0 to High(TATLinkArray) do
157       with Ptr^.Data[iPair] do
158       begin
159         if NLen=0 then Break;
160         Result+= IntToStr(NFrom)+','+IntToStr(NLen)+' ';
161       end;
162   end;
163 end;
164 
165 end.
166 
167