You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
RnQ/RnQ/HistAllSearch.pas

911 lines
24 KiB
Plaintext

{
This file is part of R&Q.
Under same license
}
unit HistAllSearch;
{$I RnQConfig.inc}
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Types, Generics.Collections, Vcl.AppEvnts, Vcl.Menus,
StdCtrls, ExtCtrls, RnQGlobal, RnQButtons, VirtualTrees, DateUtils, Threading,
Sciter, SciterAPI, GR32, ICQCommon, ICQContacts, ICQConsts, ICQSession, ChatBox, history;
{$I NoRTTI.inc}
const
WM_AFTERSHOW = WM_USER + 1;
type
TAllHistSrchForm = class(TForm)
split: TSplitter;
pnl: TPanel;
caseChk: TCheckBox;
RoasterChk: TCheckBox;
SchAllBtn: TRnQButton;
SchBtn: TRnQButton;
direction: TComboBox;
HistPosTree: TVirtualDrawTree;
radioAll: TRadioButton;
radioCurrent: TRadioButton;
HistPosTreeAll: TVirtualDrawTree;
loading: TPanel;
AppEvents: TApplicationEvents;
SearchEdit: TEdit;
HistMenu: TPopupMenu;
Copy1: TMenuItem;
procedure SchAllBtnClick(Sender: TObject);
procedure HistPosTreeFreeNode(Sender: TBaseVirtualTree; Node: PVirtualNode);
procedure FormCreate(Sender: TObject);
procedure HistPosTreeDrawNode(Sender: TBaseVirtualTree; const PaintInfo: TVTPaintInfo);
procedure FormShow(Sender: TObject);
procedure FormAfterShow(var Msg: TMessage); message WM_AFTERSHOW;
procedure DoAfterShow;
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure SchBtnClick(Sender: TObject);
procedure FormResize(Sender: TObject);
procedure keyEvent(Sender: TObject; var Key: Char);
procedure OpenPreview(Node: PVirtualNode);
procedure updateSearchFrmXY;
procedure applyFormXY;
procedure radioAllClick(Sender: TObject);
procedure radioCurrentClick(Sender: TObject);
procedure SwitchSource(srcAll: Boolean);
procedure HistPosTreeAllDrawNode(Sender: TBaseVirtualTree; const PaintInfo: TVTPaintInfo);
procedure HistPosTreeChange(Sender: TBaseVirtualTree; Node: PVirtualNode);
procedure UpdateChatSettings;
procedure UpdateChatSmiles;
procedure LoadHistory;
procedure SelectTarget;
procedure MeasureHeight(doAll: Boolean = False);
procedure HistPosTreeAllNodeDblClick(Sender: TBaseVirtualTree; const HitInfo: THitInfo);
procedure HistPosTreeScroll(Sender: TBaseVirtualTree; DeltaX, DeltaY: Integer);
procedure AppEventsMessage(var Msg: tagMSG; var Handled: Boolean);
procedure HistPosTreeMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
procedure HistPosTreeKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
procedure FormDestroy(Sender: TObject);
procedure Copy1Click(Sender: TObject);
procedure HistPosTreeResize(Sender: TObject);
private
{ Private declarations }
stop2search: Boolean;
thisProto: TICQSession;
procedure CopySelectedNodes;
public
{ Public declarations }
contact: TICQContact;
all: Boolean;
targetTime: TDateTime;
ChatBox: TChatBox;
end;
var
AllHistSrchForm: TAllHistSrchForm;
Task: ITask;
HistWidth: Integer;
bmps: array of TBitmap32;
DC: HDC;
implementation
{$R *.dfm}
uses
StrUtils, Clipbrd, RDFileUtil, RQUtil, RDGlobal, RnQLangs, RQThemes,
RnQSysUtils, RnQPics, RnQDialogs, chatDlg, events, globalLib, themesLib, utilLib, SciterLib;
type
PHSItem = ^THSItem;
THSItem = record
NodeType: (NT_MY, NT_HIS, NT_UID, NT_POSITION);
rowId: Integer;
displayed: String;
sUID: TUID;
pos: Integer;
header: THeader;
time: TDateTime;
body: String;
measured: Boolean;
binary: Boolean;
end;
procedure TAllHistSrchForm.FormClose(Sender: TObject; var Action: TCloseAction);
begin
updateSearchFrmXY;
if not stop2search then
begin
stop2search := True;
if Assigned(task) and not (task.Status = TTaskStatus.Canceled) then
task.Cancel;
HistPosTree.Clear;
HistPosTreeAll.Clear;
end;
if Assigned(ChatBox) then
begin
ChatBox.ClosePage;
FreeAndNil(ChatBox);
end;
AllHistSrchForm := nil;
Action := caFree;
end;
procedure TAllHistSrchForm.FormCreate(Sender: TObject);
var
bmp: TBitmap32;
i: Integer;
const
ECM_FIRST = $1500;
EM_SETCUEBANNER = ECM_FIRST + 1;
begin
targetTime := 0;
DoubleBuffered := False;
HistPosTree.NodeDataSize := SizeOf(THSItem);
HistPosTreeAll.NodeDataSize := SizeOf(THSItem);
SendMessage(SearchEdit.Handle, EM_SETCUEBANNER, WParam(True), LParam(PWideChar(WideString(GetTranslation('Text to search')))));
Randomize;
SetLength(bmps, System.CPUCount);
for i := 0 to System.CPUCount - 1 do
begin
bmp := TBitmap32.Create;
bmp.SetSize(1, 1);
bmp.Canvas.Font.Assign(Application.DefaultFont);
bmps[i] := bmp;
end;
end;
procedure TAllHistSrchForm.FormDestroy(Sender: TObject);
var
bmp: TBitmap32;
begin
for bmp in bmps do
bmp.Free;
SetLength(bmps, 0);
end;
procedure TAllHistSrchForm.FormResize(Sender: TObject);
begin
updateSearchFrmXY;
if HistPosTree.Visible and (HistPosTree.Height < 100) then
ChatBox.Height := ClientHeight - split.Height - HistPosTree.Height - pnl.Height - ChatBox.Margins.Top - ChatBox.Margins.Bottom
else if HistPosTreeAll.Visible and (HistPosTreeAll.Height < 100) then
ChatBox.Height := ClientHeight - split.Height - HistPosTreeAll.Height - pnl.Height - ChatBox.Margins.Top - ChatBox.Margins.Bottom;
end;
procedure TAllHistSrchForm.updateSearchFrmXY;
begin
if not Visible then
Exit;
if WindowState <> wsMaximized then
begin
searchfrmXY.Top := Top;
searchfrmXY.Left := Left;
searchfrmXY.Height := Height;
searchfrmXY.Width := Width;
end;
if WindowState <> wsMinimized then
searchfrmXY.maximized := WindowState = wsMaximized;
end;
procedure TAllHistSrchForm.AppEventsMessage(var Msg: tagMSG; var Handled: Boolean);
begin
if Msg.message = WM_MOUSEWHEEL then
if Msg.hwnd = HistPosTree.Handle then
HistPosTree.Perform(CM_MOUSEWHEEL, Msg.wParam, Msg.lParam)
else if Msg.hwnd = HistPosTreeAll.Handle then
HistPosTreeAll.Perform(CM_MOUSEWHEEL, Msg.wParam, Msg.lParam);
end;
procedure TAllHistSrchForm.applyFormXY;
begin
with searchfrmXY do
if Width > 0 then
begin
if maximized then
begin
SetBounds(Left, Top, Width, height);
windowState := wsMaximized;
end
else
begin
SetBounds(Left, Top, Width, height);
windowState := wsNormal
end;
end;
end;
procedure TAllHistSrchForm.CopySelectedNodes;
var
text, multi: String;
begin
with HistPosTree.SelectedNodes.GetEnumerator do
repeat
if not MoveNext then
Break;
with PHSItem(HistPosTree.GetNodeData(Current))^ do
begin
if Length(header.prefix) > 0 then
multi := ' (' + multi + ')'
else
multi := '';
text := text + ' ' + header.date + ', ' + header.what + multi + CRLF + body + CRLF;
end;
until not Assigned(Current);
if not (text = '') then
clipboard.AsText := text.TrimRight;
end;
procedure TAllHistSrchForm.Copy1Click(Sender: TObject);
begin
CopySelectedNodes;
end;
procedure TAllHistSrchForm.FormShow(Sender: TObject);
begin
applyTaskButton(self);
theme.pic2ico(RQteFormIcon, PIC_SEARCH, icon);
stop2search := True;
thisProto := Account.AccProto;
applyFormXY;
PostMessage(Handle, WM_AFTERSHOW, 0, 0);
end;
procedure TAllHistSrchForm.FormAfterShow(var Msg: TMessage);
begin
DoAfterShow;
end;
procedure TAllHistSrchForm.DoAfterShow;
begin
radioCurrent.Checked := not all;
radioAll.Checked := all;
SwitchSource(all);
end;
procedure TAllHistSrchForm.keyEvent(Sender: TObject; var Key: Char);
begin
if Key = ^C then
ChatBox.copySel2Clpb;
end;
procedure TAllHistSrchForm.HistPosTreeAllDrawNode(Sender: TBaseVirtualTree; const PaintInfo: TVTPaintInfo);
var
s: String;
begin
PaintInfo.Canvas.Font.Assign(Application.DefaultFont);
with PHSItem(Sender.GetNodeData(PaintInfo.Node))^ do
begin
SetBkMode(PaintInfo.Canvas.Handle, TRANSPARENT);
if vsSelected in PaintInfo.Node^.States then
PaintInfo.Canvas.Font.Color := $00000000
else
PaintInfo.Canvas.Font.Color := $00333333;
case NodeType of
NT_UID:
begin
// if contactsDB.exists(Account.AccProto, hsItem.sUID) then
if thisProto.ContactExists(sUID) then
with thisProto.getContact(sUID) do
if displayed <> UID then
s := displayed + ' "' + sUID + '" (' + IntToStr(PaintInfo.Node.ChildCount) + ')'
else
s := '"' + sUID + '" (' + IntToStr(PaintInfo.Node.ChildCount) + ')';
PaintInfo.Canvas.TextOut(PaintInfo.ContentRect.Left, 3, s);
end;
NT_POSITION:
PaintInfo.canvas.textout(PaintInfo.ContentRect.Left, 3, DateTimeToStr(time));
end;
end;
end;
procedure TAllHistSrchForm.HistPosTreeAllNodeDblClick(Sender: TBaseVirtualTree; const HitInfo: THitInfo);
begin
if HitInfo.HitNode <> nil then
with PHSItem(Sender.GetNodeData(HitInfo.HitNode))^ do
if NodeType = NT_POSITION then
begin
if thisProto.ContactExists(sUID) then
begin
contact := thisProto.getContact(sUID);
targetTime := time;
radioCurrent.Checked := True;
end;
end else
inherited;
end;
procedure TAllHistSrchForm.HistPosTreeChange(Sender: TBaseVirtualTree; Node: PVirtualNode);
begin
if Assigned(Node) then
targetTime := 0;
if HistPosTree.SelectedCount > 0 then
OpenPreview(HistPosTree.GetFirstSelected)
else
begin
ChatBox.ClearEvents;
if HistPosTree.SelectedCount = 0 then
ChatBox.ShowSearchHere;
end;
end;
procedure TAllHistSrchForm.HistPosTreeDrawNode(Sender: TBaseVirtualTree; const PaintInfo: TVTPaintInfo);
var
r: TRect;
s: String;
begin
r := PaintInfo.CellRect;
inc(r.Left, 6);
dec(r.Right, 3);
inc(r.Top, 8);
PaintInfo.Canvas.Font.Assign(Application.DefaultFont);
with PHSItem(Sender.GetNodeData(PaintInfo.Node))^ do
begin
SetBkMode(PaintInfo.Canvas.Handle, TRANSPARENT);
if NodeType = NT_HIS then
PaintInfo.Canvas.Font.Color := $00034184
else if NodeType = NT_MY then
PaintInfo.Canvas.Font.Color := $00933528;
s := header.what + ' ' + header.date;
if not (header.prefix = '') then
s := s + ' ' + header.prefix;
DrawText(PaintInfo.Canvas.Handle, s, Length(s), r, DT_WORDBREAK or DT_EXTERNALLEADING or DT_NOPREFIX);
if vsSelected in PaintInfo.Node^.States then
PaintInfo.Canvas.Font.Color := $00000000
else
PaintInfo.Canvas.Font.Color := $00333333;
if not (body = '') then
DrawText(PaintInfo.Canvas.Handle, CRLF + body, Length(CRLF + body), r, DT_WORDBREAK or DT_EXTERNALLEADING or DT_NOPREFIX);
end;
end;
procedure TAllHistSrchForm.HistPosTreeFreeNode(Sender: TBaseVirtualTree; Node: PVirtualNode);
begin
Sender.SetNodeData(Node, Default(THSItem));
end;
procedure TAllHistSrchForm.HistPosTreeKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
if (Shift = [ssCtrl]) and (Key = VK_C) then
CopySelectedNodes;
end;
procedure TAllHistSrchForm.HistPosTreeMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
if (Button = mbRight) and (HistPosTree.SelectedCount > 0) then
HistMenu.Popup(Mouse.CursorPos.X, Mouse.CursorPos.Y);
end;
procedure TAllHistSrchForm.HistPosTreeResize(Sender: TObject);
var
Node: PVirtualNode;
begin
if HistPosTree.Visible then
with HistPosTree do
if not (HistWidth = ClientWidth) then
begin
HistWidth := ClientWidth;
Node := GetFirst;
while Assigned(Node) do
begin
PHSItem(GetNodeData(Node))^.measured := False;
Node := GetNextSibling(Node);
end;
MeasureHeight;
end;
end;
procedure TAllHistSrchForm.HistPosTreeScroll(Sender: TBaseVirtualTree; DeltaX, DeltaY: Integer);
begin
MeasureHeight;
end;
procedure TAllHistSrchForm.OpenPreview(Node: PVirtualNode);
var
Sel: THSItem;
hev: Thevent;
Params: TParams;
MsgData: TMessageData;
begin
if not Assigned(Node) or not Visible then
Exit;
Sel := PHSItem(HistPosTree.GetNodeData(Node))^;
hev := ChatBox.GetHistory(Sel.sUID).getByRowId(Sel.rowId);
if Assigned(hev) then
with ChatBox do
begin
ClearEvents;
AddChatItem(Params, MsgData, hev, False, True);
SendChatItems(Sel.sUID, params);
ScrollToTop(False);
FreeAndNil(hev);
end;
end;
procedure TAllHistSrchForm.radioAllClick(Sender: TObject);
begin
SwitchSource(True);
end;
procedure TAllHistSrchForm.radioCurrentClick(Sender: TObject);
begin
SwitchSource(False);
end;
procedure TAllHistSrchForm.SwitchSource(srcAll: Boolean);
begin
if Assigned(contact) then
begin
radioCurrent.Caption := contact.displayed.Replace('&', '&&');
radioCurrent.Visible := True;
end
else
begin
srcAll := True;
radioCurrent.Visible := False;
end;
all := srcAll;
HistPosTreeAll.Visible := srcAll;
SchBtn.Visible := not srcAll;
SchAllBtn.Visible := srcAll;
RoasterChk.Visible := srcAll;
direction.Visible := not srcAll;
SearchEdit.SetFocus;
SearchEdit.SelStart := Length(SearchEdit.Text);
if Assigned(ChatBox) then
ChatBox.Visible := not srcAll;
if not srcAll then
LoadHistory;
end;
procedure TAllHistSrchForm.LoadHistory;
var
events: Thevents;
Node: PVirtualNode;
hsItem: PHSItem;
hist: Thistory;
begin
if Assigned(ChatBox) then
begin
hist := ChatBox.GetHistory(contact.UID2cmp);
if Assigned(hist) then
begin
ChatBox.Top := split.Top + split.Height + 1;
SelectTarget;
Exit;
end;
end;
loading.Caption := GetTranslation('Loading history...');
loading.Show;
loading.BringToFront;
AllHistSrchForm.Refresh;
if not Assigned(ChatBox) then
begin
ChatBox := TChatBox.Create(AllHistSrchForm);
with ChatBox do
begin
Hide;
Align := alBottom;
AlignWithMargins := True;
Margins.Top := 0;
Margins.Bottom := 8;
Margins.Left := 8;
Margins.Right := 8;
Constraints.MinHeight := 100;
Height := Round(AllHistSrchForm.Height / 4);
OnKeyPress := keyEvent;
Load;
InitSettings;
end;
end else
ChatBox.ClosePage;
ChatBox.OpenPage(contact, True, True);
HistPosTree.Clear;
HistPosTree.BeginUpdate;
stop2search := False;
events := ChatBox.GetHistory(contact.UID2cmp).getAllEvents;
task := TTask.Create(procedure
var
hev: Thevent;
begin
with ChatBox do
begin
if Assigned(events) then
for hev in events do
if Assigned(hev) then
begin
if stop2search or Application.Terminated then
Exit;
Node := HistPosTree.AddChild(nil);
hsItem := HistPosTree.GetNodeData(Node);
hsItem.rowId := hev.rowId;
hsItem.sUID := contact.UID;
hsItem.displayed := hev.who.displayed;
hsItem.pos := Node.Index;
hsItem.time := hev.when;
hsItem.header := hev.getHeaderTexts;
hsItem.binary := False;
if not (hev.getBodyText = '') then
hsItem.body := Trim(hev.getBodyText)
else if (Length(hev.getBodyBin) > 0) and (hev.kind = EK_msg) then
begin
hsItem.body := '[' + GetTranslation('Binary data, %u B', [Length(hev.getBodyBin)]) + ']';
hsItem.binary := True;
end else
hsItem.body := '';
hsItem.measured := False;
Include(Node.States, vsHeightMeasured);
if hev.outgoing then
hsItem.NodeType := NT_MY
else
hsItem.NodeType := NT_HIS;
hev.Free;
end;
if Assigned(events) then
SetLength(events, 0);
TThread.Synchronize(nil, procedure
begin
if stop2search or Application.Terminated then
Exit;
MeasureHeight(True);
HistPosTree.EndUpdate;
HistPosTree.Show;
Show;
Top := split.Top + split.Height + 1;
ShowSearchHere;
loading.Hide;
SelectTarget;
stop2search := True;
end);
end;
end);
task.Start;
end;
procedure TAllHistSrchForm.SelectTarget;
var
Node: PVirtualNode;
begin
if not (targetTime = 0) then
begin
HistPosTree.ClearSelection;
Node := HistPosTree.GetFirst;
while Assigned(Node) do
begin
if CompareDateTime(targetTime, PHSItem(HistPosTree.GetNodeData(Node))^.time) = 0 then
begin
HistPosTree.Selected[Node] := True;
HistPosTree.ScrollIntoView(Node, True);
OpenPreview(Node);
Break;
end else
Node := HistPosTree.GetNextSibling(Node)
end;
end;
end;
function MeasureNode(const data: PHSItem): Integer;
var
s: string;
r, r2: TRect;
bmp: TBitmap32;
i: Integer;
begin
bmp := nil;
for i := 0 to System.CPUCount - 1 do
if bmps[i].Canvas.LockCount = 0 then
begin
bmp := bmps[i];
Break;
end;
if not Assigned(bmp) then
bmp := bmps[Random(Length(bmps)-1)];
bmp.Canvas.Lock;
try
r := Rect(6, 8, HistWidth-3, 0);
with data^ do
begin
s := header.what + ' ' + header.date;
if not (header.prefix = '') then
s := s + ' ' + header.prefix;
if not (body = '') then
s := s + CRLF + body;
r2 := r;
DrawText(bmp.Canvas.Handle, s, Length(s), r2, DT_EXTERNALLEADING or DT_NOPREFIX or DT_CALCRECT);
if r2.Width > r.Width then
DrawText(bmp.Canvas.Handle, s, Length(s), r, DT_WORDBREAK or DT_EXTERNALLEADING or DT_NOPREFIX or DT_CALCRECT)
else
r := r2;
Result := r.Bottom + 9;
end;
finally
bmp.Canvas.Unlock;
end;
end;
procedure TAllHistSrchForm.MeasureHeight(doAll: Boolean = False);
var
Node, BottomNode: PVirtualNode;
Data: PHSItem;
Task: ITask;
TaskList: TList;
NodeHeights: TDictionary;
NH: TPair;
// Freq, StartCount, StopCount: Int64;
// TimingSeconds: Real;
procedure MeasureTask(const n: PVirtualNode; const d: PHSItem);
begin
Task := TTask.Run(procedure
var
h: Integer;
begin
h := MeasureNode(d);
d.measured := True;
MonitorEnter(NodeHeights);
try
NodeHeights.AddOrSetValue(n, h);
finally
MonitorExit(NodeHeights);
end;
end);
TaskList.Add(Task);
end;
begin
//QueryPerformanceFrequency(Freq);
//QueryPerformanceCounter(StartCount);
if doAll then
begin
Node := HistPosTree.GetFirstChild(nil);
BottomNode := nil;
end
else
begin
Node := HistPosTree.TopNode;
if Assigned(Node) and Assigned(Node.PrevSibling) then
Node := Node.PrevSibling;
// BottomNode := HistPosTree.GetNextSibling(HistPosTree.GetNodeAt(Types.Point(HistPosTree.ClientWidth - 1, HistPosTree.ClientHeight - 1)));
BottomNode := HistPosTree.BottomNode;
if Assigned(BottomNode) and Assigned(BottomNode.NextSibling) then
BottomNode := BottomNode.NextSibling;
end;
if not Assigned(Node) and not Assigned(BottomNode) then
Exit;
HistWidth := HistPosTree.ClientWidth;
TaskList := TList.Create;
NodeHeights := TDictionary.Create;
while Assigned(Node) do
begin
Data := PHSItem(HistPosTree.GetNodeData(Node));
if not Data.measured and Assigned(Node) and Assigned(Data) then
MeasureTask(Node, Data);
Node := HistPosTree.GetNextSibling(Node);
if Node = BottomNode then
Break;
end;
TTask.WaitForAll(TaskList.ToArray);
TaskList.Free;
for NH in NodeHeights do
HistPosTree.NodeHeight[NH.Key] := NH.Value;
NodeHeights.Free;
//QueryPerformanceCounter(StopCount);
//TimingSeconds := (StopCount - StartCount) / Freq;
//OutputDebugString(PChar(floattostr(TimingSeconds)));
end;
procedure TAllHistSrchForm.SchAllBtnClick(Sender: TObject);
var
ParentNode: PVirtualNode;
procedure addPosition(const uid: TUID; pos: Integer; time: TDateTime);
var
n: PVirtualNode;
hsItem: PHSItem;
begin
if ParentNode = nil then
begin
ParentNode := HistPosTreeAll.AddChild(nil);
hsItem := HistPosTreeAll.GetNodeData(ParentNode);
hsItem.NodeType := NT_UID;
hsItem.sUID := uid;
end;
n := HistPosTreeAll.AddChild(ParentNode);
hsItem := HistPosTreeAll.GetNodeData(n);
hsItem.NodeType := NT_POSITION;
hsItem.sUID := uid;
hsItem.pos := pos;
hsItem.time := time;
// n.CheckType := ctCheckBox;
end;
var
hist: Thistory;
i: Integer;
uid: TUID;
uids: TUIDS;
ev: Thevent;
events: Thevents;
begin
if not SchAllBtn.Visible then
Exit;
if (SearchEdit.Text = '') then
begin
SearchEdit.SetFocus;
Exit;
end;
if stop2search then
begin
stop2search := False;
SchAllBtn.Caption := getTranslation('&Stop');
HistPosTreeAll.Clear;
uids := Thistory.getExistingChats;
for uid in uids do
if not RoasterChk.Checked or (RoasterChk.Checked and Account.AccProto.readList(LT_ROSTER).exists(uid)) then
begin
hist := Thistory.Create(uid);
events := hist.dataSearch(SearchEdit.Text, caseChk.Checked);
ParentNode := nil;
i := 0;
if Length(events) > 0 then
for ev in events do
begin
if not Assigned(ev) then
Continue;
addPosition(uid, i, ev.when);
inc(i);
ev.Free;
end;
if Assigned(events) then
SetLength(events, 0);
hist.Free;
// cnt := Account.AccProto.getContact(fnUID);
end;
SchAllBtn.Caption := getTranslation('&Search');
stop2search := True;
end else
stop2search := True;
end;
procedure NoMoreMatchesDlg;
begin
MessageBox(AllHistSrchForm.Handle, PChar(GetTranslation('Nothing can be found')), PChar(GetTranslation('Search')), MB_OK);
end;
procedure TAllHistSrchForm.SchBtnClick(Sender: TObject);
var
Data: PHSItem;
Node, NextNode: PVirtualNode;
found: Boolean;
begin
if not SchBtn.Visible then
Exit;
if (SearchEdit.Text = '') then
begin
SearchEdit.SetFocus;
Exit;
end;
Node := nil;
case direction.ItemIndex of
0: Node := HistPosTree.GetFirst;
1:
begin
Node := HistPosTree.GetFirstSelected;
if Node = nil then
Node := HistPosTree.GetFirst;
end;
2:
begin
Node := HistPosTree.GetFirstSelected;
if Node = nil then
Node := HistPosTree.GetLast;
end;
3: Node := HistPosTree.GetLast;
end;
if Node = nil then
Exit;
if vsSelected in Node.States then
if direction.ItemIndex <= 1 then
Node := Node.NextSibling
else
Node := Node.PrevSibling;
found := False;
if (Node = nil) then
begin
NoMoreMatchesDlg;
SearchEdit.SetFocus;
end else
while Assigned(Node) do
begin
Data := HistPosTree.GetNodeData(Node);
if not Data.binary then
if caseChk.Checked then
found := ContainsStr(Data.body, SearchEdit.Text)
else
found := ContainsText(Data.body, SearchEdit.Text);
if found then
begin
HistPosTree.ClearSelection;
HistPosTree.Selected[Node] := True;
HistPosTree.ScrollIntoView(Node, True);
OpenPreview(Node);
if direction.ItemIndex = 0 then
direction.ItemIndex := 1
else if direction.ItemIndex = 3 then
direction.ItemIndex := 2;
direction.Refresh;
Break
end;
if direction.ItemIndex <= 1 then
NextNode := HistPosTree.GetNextSibling(Node)
else
NextNode := HistPosTree.GetPreviousSibling(Node);
if (NextNode = nil) then
begin
NoMoreMatchesDlg;
SearchEdit.SetFocus;
Break;
end else
Node := NextNode;
end;
end;
procedure TAllHistSrchForm.UpdateChatSettings;
begin
ChatBox.InitSettings;
end;
procedure TAllHistSrchForm.UpdateChatSmiles;
begin
ChatBox.UpdateSmiles;
end;
end.