summaryrefslogtreecommitdiff
path: root/plugins/HistoryPlusPlus/hpp_events.pas
diff options
context:
space:
mode:
authorAlexey Kulakov <panda75@bk.ru>2012-07-04 13:17:29 +0000
committerAlexey Kulakov <panda75@bk.ru>2012-07-04 13:17:29 +0000
commita5a3db4393d85407ff4c5668d88860e06158abd0 (patch)
treebcc8f716833034e33984a539ab7d1debfdd6a7d3 /plugins/HistoryPlusPlus/hpp_events.pas
parent88ec2ae53ddc811d08763b2fb3a0073b571a321c (diff)
History++ sources upload (all files, no project)
git-svn-id: http://svn.miranda-ng.org/main/trunk@756 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'plugins/HistoryPlusPlus/hpp_events.pas')
-rw-r--r--plugins/HistoryPlusPlus/hpp_events.pas1049
1 files changed, 1049 insertions, 0 deletions
diff --git a/plugins/HistoryPlusPlus/hpp_events.pas b/plugins/HistoryPlusPlus/hpp_events.pas
new file mode 100644
index 0000000000..88f8a5d388
--- /dev/null
+++ b/plugins/HistoryPlusPlus/hpp_events.pas
@@ -0,0 +1,1049 @@
+(*
+ History++ plugin for Miranda IM: the free IM client for Microsoft* Windows*
+
+ Copyright (C) 2006-2009 theMIROn, 2003-2006 Art Fedorov.
+ History+ parts (C) 2001 Christian Kastner
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*)
+
+{-----------------------------------------------------------------------------
+ hpp_events (historypp project)
+
+ Version: 1.5
+ Created: 05.08.2004
+ Author: Oxygen
+
+ [ Description ]
+
+ Some refactoring we have here, so now all event reading
+ routines are here. By event reading I mean getting usefull
+ info out of DB and translating it into human words,
+ like reading different types of messages and such.
+
+ [ History ]
+
+ 1.5 (05.08.2004)
+ First version
+
+ [ Modifications ]
+ none
+
+ [ Known Issues ]
+ none
+
+ Contributors: theMIROn, Art Fedorov
+-----------------------------------------------------------------------------}
+
+unit hpp_events;
+
+interface
+
+{$I compilers.inc}
+
+uses
+ Windows, SysUtils,
+ m_api,
+ hpp_global, hpp_contacts;
+
+type
+ TTextFunction = procedure(EventInfo: TDBEventInfo; var Hi: THistoryItem);
+
+ TEventTableItem = record
+ EventType: Word;
+ MessageType: TMessageType;
+ TextFunction: TTextFunction;
+ end;
+
+ PEventRecord = ^TEventRecord;
+ TEventRecord = record
+ Name: String;
+ XML: AnsiString;
+ i: SmallInt;
+ iName: PAnsiChar;
+ iSkin: SmallInt;
+ end;
+
+const
+ EVENTTYPE_STATUSCHANGE = 25368; // from srmm's
+ EVENTTYPE_SMTPSIMPLE = 2350; // from SMTP Simple
+ EVENTTYPE_NICKNAMECHANGE = 9001; // from pescuma
+ EVENTTYPE_STATUSMESSAGECHANGE = 9002; // from pescuma
+ EVENTTYPE_AVATARCHANGE = 9003; // from pescuma
+ EVENTTYPE_CONTACTLEFTCHANNEL = 9004; // from pescuma
+ EVENTTYPE_VOICE_CALL = 8739; // from pescuma
+
+ EventRecords: array[TMessageType] of TEventRecord = (
+ (Name:'Unknown'; XML:''; i:-1; iSkin:-1),
+ (Name:'Incoming events'; XML:''; i:HPP_ICON_EVENT_INCOMING; iName:'hppevn_inc'; iSkin:-1),
+ (Name:'Outgoing events'; XML:''; i:HPP_ICON_EVENT_OUTGOING; iName:'hppevn_out'; iSkin:-1),
+ (Name:'Message'; XML:'MSG'; i:HPP_SKIN_EVENT_MESSAGE; iSkin: SKINICON_EVENT_MESSAGE),
+ (Name:'Link'; XML:'URL'; i:HPP_SKIN_EVENT_URL; iSkin:SKINICON_EVENT_URL),
+ (Name:'File transfer'; XML:'FILE'; i:HPP_SKIN_EVENT_FILE; iSkin:SKINICON_EVENT_FILE),
+ (Name:'System message'; XML:'SYS'; i:HPP_ICON_EVENT_SYSTEM; iName:'hppevn_sys'; iSkin:-1),
+ (Name:'Contacts'; XML:'ICQCNT'; i:HPP_ICON_EVENT_CONTACTS; iName:'hppevn_icqcnt'; iSkin:-1),
+ (Name:'SMS message'; XML:'SMS'; i:HPP_ICON_EVENT_SMS; iName:'hppevn_sms'; iSkin:-1),
+ (Name:'Webpager message'; XML:'ICQWP'; i:HPP_ICON_EVENT_WEBPAGER; iName:'hppevn_icqwp'; iSkin:-1),
+ (Name:'EMail Express message'; XML:'ICQEX'; i:HPP_ICON_EVENT_EEXPRESS; iName:'hppevn_icqex'; iSkin:-1),
+ (Name:'Status changes'; XML:'STATUSCNG'; i:HPP_ICON_EVENT_STATUS; iName:'hppevn_status'; iSkin:-1),
+ (Name:'SMTP Simple Email'; XML:'SMTP'; i:HPP_ICON_EVENT_SMTPSIMPLE; iName:'hppevn_smtp'; iSkin:-1),
+ (Name:'Other events (unknown)'; XML:'OTHER'; i:HPP_SKIN_OTHER_MIRANDA; iSkin:SKINICON_OTHER_MIRANDA),
+ (Name:'Nick changes'; XML:'NICKCNG'; i:HPP_ICON_EVENT_NICK; iName:'hppevn_nick'; iSkin:-1),
+ (Name:'Avatar changes'; XML:'AVACNG'; i:HPP_ICON_EVENT_AVATAR; iName:'hppevn_avatar'; iSkin:-1),
+ (Name:'WATrack notify'; XML:'WATRACK'; i:HPP_ICON_EVENT_WATRACK; iName:'hppevn_watrack'; iSkin:-1),
+ (Name:'Status message changes'; XML:'STATUSMSGCHG'; i:HPP_ICON_EVENT_STATUSMES; iName:'hppevn_statuschng'; iSkin:-1),
+ (Name:'Voice call'; XML:'VCALL'; i:HPP_ICON_EVENT_VOICECALL; iName:'hppevn_vcall'; iSkin:-1),
+ (Name:'Custom'; XML:''; i:-1; iSkin:-1)
+ );
+
+// General timstamp function
+function UnixTimeToDateTime(const UnixTime: DWord): TDateTime;
+function DateTimeToUnixTime(const DateTime: TDateTime): DWord;
+// Miranda timestamp to TDateTime
+function TimestampToDateTime(const Timestamp: DWord): TDateTime;
+function TimestampToString(const Timestamp: DWord): String;
+// general routine
+function ReadEvent(hDBEvent: THandle; UseCP: Cardinal = CP_ACP): THistoryItem;
+function GetEventInfo(hDBEvent: DWord): TDBEventInfo;
+function GetEventTimestamp(hDBEvent: THandle): DWord;
+function GetEventMessageType(hDBEvent: THandle): TMessageTypes;
+function GetEventDateTime(hDBEvent: THandle): TDateTime;
+function GetEventRecord(const Hi: THistoryItem): PEventRecord;
+function GetMessageType(EventInfo: TDBEventInfo; var EventIndex: Integer): TMessageTypes;
+// global routines
+function GetEventCoreText(EventInfo: TDBEventInfo; var Hi: THistoryItem): Boolean;
+function GetEventModuleText(EventInfo: TDBEventInfo; var Hi: THistoryItem): Boolean;
+// specific routines
+procedure GetEventTextForMessage(EventInfo: TDBEventInfo; var Hi: THistoryItem);
+procedure GetEventTextForFile(EventInfo: TDBEventInfo; var Hi: THistoryItem);
+procedure GetEventTextForUrl(EventInfo: TDBEventInfo; var Hi: THistoryItem);
+procedure GetEventTextForAuthRequest(EventInfo: TDBEventInfo; var Hi: THistoryItem);
+procedure GetEventTextForYouWereAdded(EventInfo: TDBEventInfo; var Hi: THistoryItem);
+procedure GetEventTextForSms(EventInfo: TDBEventInfo; var Hi: THistoryItem);
+procedure GetEventTextForContacts(EventInfo: TDBEventInfo; var Hi: THistoryItem);
+procedure GetEventTextForWebPager(EventInfo: TDBEventInfo; var Hi: THistoryItem);
+procedure GetEventTextForEmailExpress(EventInfo: TDBEventInfo; var Hi: THistoryItem);
+procedure GetEventTextForStatusChange(EventInfo: TDBEventInfo; var Hi: THistoryItem);
+procedure GetEventTextForAvatarChange(EventInfo: TDBEventInfo; var Hi: THistoryItem);
+procedure GetEventTextForICQAuthGranted(EventInfo: TDBEventInfo; var Hi: THistoryItem);
+procedure GetEventTextForICQAuthDenied(EventInfo: TDBEventInfo; var Hi: THistoryItem);
+procedure GetEventTextForICQSelfRemove(EventInfo: TDBEventInfo; var Hi: THistoryItem);
+procedure GetEventTextForICQFutureAuth(EventInfo: TDBEventInfo; var Hi: THistoryItem);
+procedure GetEventTextForICQClientChange(EventInfo: TDBEventInfo; var Hi: THistoryItem);
+procedure GetEventTextForICQCheckStatus(EventInfo: TDBEventInfo; var Hi: THistoryItem);
+procedure GetEventTextForICQIgnoreCheckStatus(EventInfo: TDBEventInfo; var Hi: THistoryItem);
+procedure GetEventTextForICQBroadcast(EventInfo: TDBEventInfo; var Hi: THistoryItem);
+procedure GetEventTextForJabberChatStates(EventInfo: TDBEventInfo; var Hi: THistoryItem);
+procedure GetEventTextWATrackRequest(EventInfo: TDBEventInfo; var Hi: THistoryItem);
+procedure GetEventTextWATrackAnswer(EventInfo: TDBEventInfo; var Hi: THistoryItem);
+procedure GetEventTextWATrackError(EventInfo: TDBEventInfo; var Hi: THistoryItem);
+procedure GetEventTextForOther(EventInfo: TDBEventInfo; var Hi: THistoryItem);
+// service routines
+function TextHasUrls(var Text: String): Boolean;
+function Utf8ToWideChar(Dest: PWideChar; MaxDestChars: Integer; Source: PAnsiChar; SourceBytes: Integer; CodePage: Cardinal = CP_ACP): Integer;
+
+implementation
+
+uses
+ hpp_options;
+
+{$include inc\m_music.inc}
+
+const // registered Jabber db event types (not public)
+ JABBER_DB_EVENT_TYPE_CHATSTATES = 2000;
+// JS_DB_GETEVENTTEXT_CHATSTATES = '/GetEventText2000';
+ JABBER_DB_EVENT_CHATSTATES_GONE = 1;
+
+const // ICQ db events (didn't found anywhere)
+ //auth
+ //db event added to NULL contact
+ //blob format is:
+ //ASCIIZ text
+ //DWORD uin
+ //HANDLE hContact
+ ICQEVENTTYPE_AUTH_GRANTED = 2004; //database event type
+ ICQEVENTTYPE_AUTH_DENIED = 2005; //database event type
+ ICQEVENTTYPE_SELF_REMOVE = 2007; //database event type
+ ICQEVENTTYPE_FUTURE_AUTH = 2008; //database event type
+ ICQEVENTTYPE_CLIENT_CHANGE = 2009; //database event type
+ ICQEVENTTYPE_CHECK_STATUS = 2010; //database event type
+ ICQEVENTTYPE_IGNORECHECK_STATUS = 2011;//database event type
+ //broadcast from server
+ //ASCIIZ text
+ //ASCIIZ from name
+ //ASCIIZ from e-mail
+ ICQEVENTTYPE_BROADCAST = 2006; //database event type
+
+type
+ TModuleEventRecord = record
+ EventDesc: PDBEVENTTYPEDESCR;
+ EventRecord: TEventRecord;
+ end;
+
+// OXY:
+// Routines UnixTimeToDate and DateTimeToUnixTime are taken
+// from JclDateTime.pas
+// See JclDateTime.pas for copyright and license information
+// JclDateTime.pas is part of Project JEDI Code Library (JCL)
+// [http://www.delphi-jedi.org], [http://jcl.sourceforge.net]
+const
+ // 1970-01-01T00:00:00 in TDateTime
+ UnixTimeStart = 25569;
+ SecondsPerDay = 60* 24 * 60;
+
+var
+ EventTable: array[0..28] of TEventTableItem = (
+ // must be the first item in array for unknown events
+ (EventType: MaxWord; MessageType: mtOther; TextFunction: GetEventTextForOther),
+ // events definitions
+ (EventType: EVENTTYPE_MESSAGE; MessageType: mtMessage; TextFunction: GetEventTextForMessage),
+ (EventType: EVENTTYPE_FILE; MessageType: mtFile; TextFunction: GetEventTextForFile),
+ (EventType: EVENTTYPE_URL; MessageType: mtUrl; TextFunction: GetEventTextForUrl),
+ (EventType: EVENTTYPE_AUTHREQUEST; MessageType: mtSystem; TextFunction: GetEventTextForAuthRequest),
+ (EventType: EVENTTYPE_ADDED; MessageType: mtSystem; TextFunction: GetEventTextForYouWereAdded),
+ (EventType: EVENTTYPE_CONTACTS; MessageType: mtContacts; TextFunction: GetEventTextForContacts),
+ (EventType: EVENTTYPE_STATUSCHANGE; MessageType: mtStatus; TextFunction: GetEventTextForStatusChange),
+ (EventType: EVENTTYPE_SMTPSIMPLE; MessageType: mtSMTPSimple; TextFunction: GetEventTextForMessage),
+ (EventType: ICQEVENTTYPE_SMS; MessageType: mtSMS; TextFunction: GetEventTextForSMS),
+ (EventType: ICQEVENTTYPE_WEBPAGER; MessageType: mtWebPager; TextFunction: GetEventTextForWebPager),
+ (EventType: ICQEVENTTYPE_EMAILEXPRESS; MessageType: mtEmailExpress; TextFunction: GetEventTextForEmailExpress),
+ (EventType: EVENTTYPE_NICKNAMECHANGE; MessageType: mtNickChange; TextFunction: GetEventTextForMessage),
+ (EventType: EVENTTYPE_STATUSMESSAGECHANGE; MessageType: mtStatusMessage; TextFunction: GetEventTextForMessage),
+ (EventType: EVENTTYPE_AVATARCHANGE; MessageType: mtAvatarChange; TextFunction: GetEventTextForAvatarChange),
+ (EventType: ICQEVENTTYPE_AUTH_GRANTED; MessageType: mtSystem; TextFunction: GetEventTextForICQAuthGranted),
+ (EventType: ICQEVENTTYPE_AUTH_DENIED; MessageType: mtSystem; TextFunction: GetEventTextForICQAuthDenied),
+ (EventType: ICQEVENTTYPE_SELF_REMOVE; MessageType: mtSystem; TextFunction: GetEventTextForICQSelfRemove),
+ (EventType: ICQEVENTTYPE_FUTURE_AUTH; MessageType: mtSystem; TextFunction: GetEventTextForICQFutureAuth),
+ (EventType: ICQEVENTTYPE_CLIENT_CHANGE; MessageType: mtSystem; TextFunction: GetEventTextForICQClientChange),
+ (EventType: ICQEVENTTYPE_CHECK_STATUS; MessageType: mtSystem; TextFunction: GetEventTextForICQCheckStatus),
+ (EventType: ICQEVENTTYPE_IGNORECHECK_STATUS; MessageType: mtSystem; TextFunction: GetEventTextForICQIgnoreCheckStatus),
+ (EventType: ICQEVENTTYPE_BROADCAST; MessageType: mtSystem; TextFunction: GetEventTextForICQBroadcast),
+ (EventType: JABBER_DB_EVENT_TYPE_CHATSTATES; MessageType: mtStatus; TextFunction: GetEventTextForJabberChatStates),
+ (EventType: EVENTTYPE_CONTACTLEFTCHANNEL; MessageType: mtStatus; TextFunction: GetEventTextForMessage),
+ (EventType: EVENTTYPE_WAT_REQUEST; MessageType: mtWATrack; TextFunction: GetEventTextWATrackRequest),
+ (EventType: EVENTTYPE_WAT_ANSWER; MessageType: mtWATrack; TextFunction: GetEventTextWATrackAnswer),
+ (EventType: EVENTTYPE_WAT_ERROR; MessageType: mtWATrack; TextFunction: GetEventTextWATrackError),
+ (EventType: EVENTTYPE_VOICE_CALL; MessageType: mtVoiceCall; TextFunction: GetEventTextForMessage)
+ );
+
+var
+ ModuleEventRecords: array of TModuleEventRecord;
+ RecentEvent: THandle = 0;
+ RecentEventInfo: TDBEventInfo;
+
+const
+ SHRINK_ON_CALL = 50;
+ SHRINK_TO_LEN = 512;
+
+var
+ EventBuffer: THppBuffer;
+ TextBuffer: THppBuffer;
+
+function UnixTimeToDateTime(const UnixTime: DWord): TDateTime;
+begin
+ Result:= UnixTimeStart + (UnixTime / SecondsPerDay);
+end;
+
+function DateTimeToUnixTime(const DateTime: TDateTime): DWord;
+begin
+ Result := Trunc((DateTime-UnixTimeStart) * SecondsPerDay);
+end;
+
+// Miranda timestamp to TDateTime
+function TimestampToDateTime(const Timestamp: DWord): TDateTime;
+begin
+ Result := UnixTimeToDateTime(CallService(MS_DB_TIME_TIMESTAMPTOLOCAL,WPARAM(Timestamp),0));
+end;
+
+// should probably add function param to use
+// custom grid options object and not the global one
+function TimestampToString(const Timestamp: DWord): String;
+begin
+ Result := FormatDateTime(GridOptions.DateTimeFormat,TimestampToDateTime(Timestamp));
+end;
+
+function GetEventTimestamp(hDBEvent: THandle): DWord;
+begin
+ if RecentEvent <> hDBEvent then
+ begin
+ ZeroMemory(@RecentEventInfo, SizeOf(RecentEventInfo));
+ RecentEventInfo.cbSize := SizeOf(RecentEventInfo);
+ RecentEventInfo.cbBlob := 0;
+ CallService(MS_DB_EVENT_GET, hDBEvent, LPARAM(@RecentEventInfo));
+ RecentEvent := hDBEvent;
+ end;
+ Result := RecentEventInfo.timestamp;
+end;
+
+function GetEventMessageType(hDBEvent: THandle): TMessageTypes;
+var
+ EventIndex: Integer;
+begin
+ if RecentEvent <> hDBEvent then
+ begin
+ ZeroMemory(@RecentEventInfo, SizeOf(RecentEventInfo));
+ RecentEventInfo.cbSize := SizeOf(RecentEventInfo);
+ RecentEventInfo.cbBlob := 0;
+ CallService(MS_DB_EVENT_GET, hDBEvent, LPARAM(@RecentEventInfo));
+ RecentEvent := hDBEvent;
+ end;
+ Result := GetMessageType(RecentEventInfo,EventIndex);
+end;
+
+function GetEventDateTime(hDBEvent: THandle): TDateTime;
+begin
+ Result := TimestampToDateTime(GetEventTimestamp(hDBEvent));
+end;
+
+function GetEventRecord(const Hi: THistoryItem): PEventRecord;
+var
+ MesType: TMessageTypes;
+ mt: TMessageType;
+ etd: PDBEVENTTYPEDESCR;
+ i,count: integer;
+begin
+ MesType := Hi.MessageType;
+ exclude(MesType, mtIncoming);
+ exclude(MesType, mtOutgoing);
+ exclude(MesType, mtOther);
+ for mt := Low(EventRecords) to High(EventRecords) do
+ begin
+ if mt in MesType then
+ begin
+ Result := @EventRecords[mt];
+ exit;
+ end;
+ end;
+ etd := Pointer(CallService(MS_DB_EVENT_GETTYPE, WPARAM(PAnsiChar(Hi.Module)),
+ LPARAM(Hi.EventType)));
+ if etd = nil then
+ begin
+ Result := @EventRecords[mtOther];
+ exit;
+ end;
+ count := Length(ModuleEventRecords);
+ for i := 0 to count - 1 do
+ if ModuleEventRecords[i].EventDesc = etd then
+ begin
+ Result := @ModuleEventRecords[i].EventRecord;
+ exit;
+ end;
+ SetLength(ModuleEventRecords, count + 1);
+ ModuleEventRecords[count].EventDesc := etd;
+ ModuleEventRecords[count].EventRecord := EventRecords[mtOther];
+ ModuleEventRecords[count].EventRecord.Name := AnsiToWideString(etd.descr, CP_ACP);
+ Result := @ModuleEventRecords[count].EventRecord;
+end;
+
+function Utf8ToWideChar(Dest: PWideChar; MaxDestChars: Integer; Source: PAnsiChar; SourceBytes: Integer; CodePage: Cardinal = CP_ACP): Integer;
+const
+ MB_ERR_INVALID_CHARS = 8;
+var
+ Src,SrcEnd: PAnsiChar;
+ Dst,DstEnd: PWideChar;
+begin
+ if (Source = nil) or (SourceBytes <= 0) then
+ begin
+ Result := 0;
+ end
+ else if (Dest = nil) or (MaxDestChars <= 0) then
+ begin
+ Result := -1;
+ end
+ else
+ begin
+ Src := Source;
+ SrcEnd := Source + SourceBytes;
+ Dst := Dest;
+ DstEnd := Dst + MaxDestChars;
+ while (PAnsiChar(Src) < PAnsiChar(SrcEnd)) and (Dst < DstEnd) do
+ begin
+ if (Byte(Src[0]) and $80) = 0 then
+ begin
+ Dst[0] := WideChar(Src[0]);
+ Inc(Src);
+ end
+ else if (Byte(Src[0]) and $E0) = $E0 then
+ begin
+ if Src + 2 >= SrcEnd then
+ break;
+ if (Src[1] = #0) or ((Byte(Src[1]) and $C0) <> $80) then
+ break;
+ if (Src[2] = #0) or ((Byte(Src[2]) and $C0) <> $80) then
+ break;
+ Dst[0] := WideChar(((Byte(Src[0]) and $0F) shl 12) + ((Byte(Src[1]) and $3F) shl 6) +
+ ((Byte(Src[2]) and $3F)));
+ Inc(Src, 3);
+ end
+ else if (Byte(Src[0]) and $E0) = $C0 then
+ begin
+ if Src + 1 >= SrcEnd then
+ break;
+ if (Src[1] = #0) or ((Byte(Src[1]) and $C0) <> $80) then
+ break;
+ Dst[0] := WideChar(((Byte(Src[0]) and $1F) shl 6) + ((Byte(Src[1]) and $3F)));
+ Inc(Src, 2);
+ end
+ else
+ begin
+ if MultiByteToWideChar(CodePage, MB_ERR_INVALID_CHARS, Src, 1, Dst, 1) = 0 then
+ Dst[0] := '?';
+ Inc(Src);
+ end;
+ Inc(Dst);
+ end;
+ Dst[0] := #0;
+ Inc(Dst);
+ Result := Dst - Dest;
+ end;
+end;
+
+function TextHasUrls(var Text: String): Boolean;
+var
+ i,len,lenW: Integer;
+ pText,pPos: PChar;
+begin
+ Result := False;
+ len := Length(Text);
+ if len=0 then exit;
+
+ pText := PChar(Text);
+ for i := 0 to High(UrlPrefix) do
+ begin
+ pPos := StrPos(pText, PChar(UrlPrefix[i]));
+ if not Assigned(pPos) then
+ continue;
+ Result := ((uint_ptr(pPos) = uint_ptr(pText)) or not IsWideCharAlphaNumeric((pPos - 1)^)) and
+ IsWideCharAlphaNumeric((pPos + Length(UrlPrefix[i]))^);
+ if Result then
+ exit;
+ end;
+
+ if not Assigned(StrPos(PChar(Text),':/')) then exit;
+
+ lenW := (len+1)*SizeOf(Char);
+
+ TextBuffer.Lock;
+ TextBuffer.Allocate(lenW);
+ Move(Text[1],TextBuffer.Buffer^,lenW);
+ CharLowerBuffW(PChar(TextBuffer.Buffer),len);
+ for i := 0 to High(UrlProto) do
+ begin
+ pPos := StrPos(PChar(TextBuffer.Buffer), PChar(UrlProto[i].proto));
+ if not Assigned(pPos) then
+ continue;
+ Result := ((uint_ptr(pPos) = uint_ptr(TextBuffer.Buffer)) or
+ not IsWideCharAlphaNumeric((pPos - 1)^));
+ if Result then
+ break;
+ end;
+ TextBuffer.Unlock;
+end;
+
+function GetEventInfo(hDBEvent: DWord): TDBEventInfo;
+var
+ BlobSize: integer;
+begin
+ ZeroMemory(@Result, SizeOf(Result));
+ Result.cbSize := SizeOf(Result);
+ BlobSize := CallService(MS_DB_EVENT_GETBLOBSIZE, hDBEvent, 0);
+ if BlobSize > 0 then
+ begin
+ EventBuffer.Allocate(BlobSize);
+ Result.pBlob := EventBuffer.Buffer;
+ end
+ else
+ BlobSize := 0;
+ Result.cbBlob := BlobSize;
+ if CallService(MS_DB_EVENT_GET, hDBEvent, LPARAM(@Result)) = 0 then
+ Result.cbBlob := BlobSize
+ else
+ Result.cbBlob := 0;
+end;
+
+function GetMessageType(EventInfo: TDBEventInfo; var EventIndex: Integer): TMessageTypes;
+var
+ i: Integer;
+begin
+ EventIndex := 0;
+ for i := 1 to High(EventTable) do
+ if EventTable[i].EventType = EventInfo.EventType then
+ begin
+ EventIndex := i;
+ break;
+ end;
+ Result := [EventTable[EventIndex].MessageType];
+ if (EventInfo.flags and DBEF_SENT) = 0 then
+ include(Result, mtIncoming)
+ else
+ include(Result, mtOutgoing);
+end;
+
+// reads event from hDbEvent handle
+// reads all THistoryItem fields
+// *EXCEPT* Proto field. Fill it manually, plz
+function ReadEvent(hDBEvent: THandle; UseCP: Cardinal = CP_ACP): THistoryItem;
+var
+ EventInfo: TDBEventInfo;
+ EventIndex: integer;
+ Handled: Boolean;
+begin
+ ZeroMemory(@Result,SizeOf(Result));
+ Result.Height := -1;
+ EventBuffer.Lock;
+ EventInfo := GetEventInfo(hDBEvent);
+ try
+ Result.Module := EventInfo.szModule;
+ Result.proto := '';
+ Result.Time := EventInfo.Timestamp;
+ Result.EventType := EventInfo.EventType;
+ Result.IsRead := Boolean(EventInfo.flags and DBEF_READ);
+ // enable autoRTL feature
+ if Boolean(EventInfo.flags and DBEF_RTL) then
+ Result.RTLMode := hppRTLEnable;
+ Result.MessageType := GetMessageType(EventInfo, EventIndex);
+ Result.CodePage := UseCP;
+ // Handled := true;
+ // if Handled then Handled := GetEventCoreText(EventInfo,Result);
+ { if Handled then } Handled := GetEventModuleText(EventInfo, Result);
+ if not Handled then
+ EventTable[EventIndex].TextFunction(EventInfo, Result);
+ Result.Text := AdjustLineBreaks(Result.Text);
+ Result.Text := TrimRight(Result.Text);
+ if mtMessage in Result.MessageType then
+ if TextHasUrls(Result.Text) then
+ begin
+ exclude(Result.MessageType, mtMessage);
+ include(Result.MessageType, mtUrl);
+ end;
+ finally
+ EventBuffer.Unlock;
+ end;
+end;
+
+procedure ReadStringTillZeroA(Text: PAnsiChar; Size: LongWord; var Result: AnsiString; var Pos: LongWord);
+begin
+ while (Pos < Size) and ((Text+Pos)^ <> #0) do
+ begin
+ Result := Result + (Text+Pos)^;
+ Inc(Pos);
+ end;
+ Inc(Pos);
+end;
+
+procedure ReadStringTillZeroW(Text: PChar; Size: LongWord; var Result: String; var Pos: LongWord);
+begin
+ while (Pos < Size) and ((Text+Pos)^ <> #0) do
+ begin
+ Result := Result + (Text+Pos)^;
+ Inc(Pos,SizeOf(Char));
+ end;
+ Inc(Pos,SizeOf(Char));
+end;
+
+function GetEventCoreText(EventInfo: TDBEventInfo; var Hi: THistoryItem): Boolean;
+var
+ dbegt: TDBEVENTGETTEXT;
+ msg: Pointer;
+begin
+ Result := False;
+ dbegt.dbei := @EventInfo;
+ dbegt.datatype := DBVT_WCHAR;
+ dbegt.codepage := hi.Codepage;
+ msg := nil;
+ try
+ msg := Pointer(CallService(MS_DB_EVENT_GETTEXT,0,LPARAM(@dbegt)));
+ Result := Assigned(msg);
+ except
+ if Assigned(msg) then mir_free(msg);
+ end;
+ if Result then
+ begin
+ SetString(hi.Text,PChar(msg),StrLen(PChar(msg)));
+ mir_free(msg);
+ end;
+end;
+
+function GetEventModuleText(EventInfo: TDBEventInfo; var Hi: THistoryItem): Boolean;
+const
+ maxServiceLength = 99;
+var
+ dbegt: TDBEVENTGETTEXT;
+ msg: Pointer;
+ szServiceName: array[0..maxServiceLength] of AnsiChar;
+begin
+ Result := False;
+ dbegt.dbei := @EventInfo;
+ dbegt.datatype := DBVT_WCHAR;
+ dbegt.codepage := hi.Codepage;
+ try
+ StrLFmt(szServiceName,maxServiceLength,'%s/GetEventText%u',[EventInfo.szModule,EventInfo.eventType]);
+ Result := Boolean(ServiceExists(szServiceName));
+ except
+ end;
+ if not Result then exit;
+ msg := nil;
+ try
+ msg := Pointer(CallService(szServiceName,0,LPARAM(@dbegt)));
+ Result := Assigned(msg);
+ except
+ if Assigned(msg) then mir_free(msg);
+ end;
+ if Result then begin
+ SetString(hi.Text,PChar(msg),StrLen(PChar(msg)));
+ mir_free(msg);
+ end;
+end;
+
+procedure GetEventTextForMessage(EventInfo: TDBEventInfo; var Hi: THistoryItem);
+var
+ msgA: PAnsiChar;
+ msgW: PChar;
+ msglen,lenW: Cardinal;
+ i: integer;
+begin
+ msgA := PAnsiChar(EventInfo.pBlob);
+ msgW := nil;
+ msglen := lstrlenA(PAnsiChar(EventInfo.pBlob)) + 1;
+ if msglen > Cardinal(EventInfo.cbBlob) then
+ msglen := EventInfo.cbBlob;
+ if Boolean(EventInfo.flags and DBEF_UTF) then
+ begin
+ SetLength(Hi.Text, msglen);
+ lenW := Utf8ToWideChar(PChar(Hi.Text), msglen, msgA, msglen - 1, Hi.CodePage);
+ if Integer(lenW) > 0 then
+ SetLength(Hi.Text, lenW - 1)
+ else
+ Hi.Text := AnsiToWideString(msgA, Hi.CodePage, msglen - 1);
+ end
+ else
+ begin
+ lenW := 0;
+ if Cardinal(EventInfo.cbBlob) >= msglen * SizeOf(Char) then
+ begin
+ msgW := PChar(msgA + msglen);
+ for i := 0 to ((Cardinal(EventInfo.cbBlob) - msglen) div SizeOf(Char)) - 1 do
+ if msgW[i] = #0 then
+ begin
+ lenW := i;
+ break;
+ end;
+ end;
+ if (lenW > 0) and (lenW < msglen) then
+ SetString(Hi.Text, msgW, lenW)
+ else
+ Hi.Text := AnsiToWideString(msgA, Hi.CodePage, msglen - 1);
+ end;
+end;
+
+procedure GetEventTextForUrl(EventInfo: TDBEventInfo; var Hi: THistoryItem);
+var
+ BytePos:LongWord;
+ Url,Desc: AnsiString;
+ cp: Cardinal;
+begin
+ BytePos:=0;
+ ReadStringTillZeroA(Pointer(EventInfo.pBlob),EventInfo.cbBlob,Url,BytePos);
+ ReadStringTillZeroA(Pointer(EventInfo.pBlob),EventInfo.cbBlob,Desc,BytePos);
+ if Boolean(EventInfo.flags and DBEF_UTF) then
+ cp := CP_UTF8
+ else
+ cp := Hi.CodePage;
+ hi.Text := Format(TranslateW('URL: %s'),[AnsiToWideString(url+#13#10+desc,cp)]);
+ hi.Extended := Url;
+end;
+
+procedure GetEventTextForFile(EventInfo: TDBEventInfo; var Hi: THistoryItem);
+var
+ BytePos: LongWord;
+ FileName,Desc: AnsiString;
+ cp: Cardinal;
+begin
+ //blob is: sequenceid(DWORD),filename(ASCIIZ),description(ASCIIZ)
+ BytePos := 4;
+ ReadStringTillZeroA(Pointer(EventInfo.pBlob), EventInfo.cbBlob, FileName, BytePos);
+ ReadStringTillZeroA(Pointer(EventInfo.pBlob), EventInfo.cbBlob, Desc, BytePos);
+ if Boolean(EventInfo.flags and DBEF_SENT) then
+ Hi.Text := 'Outgoing file transfer: %s'
+ else
+ Hi.Text := 'Incoming file transfer: %s';
+ if Boolean(EventInfo.flags and DBEF_UTF) then
+ cp := CP_UTF8
+ else
+ cp := Hi.CodePage;
+ Hi.Text := Format(TranslateUnicodeString(Hi.Text), [AnsiToWideString(FileName + #13#10 + Desc, cp)]);
+ Hi.Extended := FileName;
+end;
+
+procedure GetEventTextForAuthRequest(EventInfo: TDBEventInfo; var Hi: THistoryItem);
+var
+ BytePos: LongWord;
+ uin:integer;
+ hContact: THandle;
+ Nick,Name,Email,Reason: AnsiString;
+ NickW,ReasonW,ReasonUTF,ReasonACP: String;
+begin
+ // blob is: uin(DWORD), hContact(THANDLE), nick(ASCIIZ), first(ASCIIZ), last(ASCIIZ), email(ASCIIZ)
+ uin := PDWord(EventInfo.pBlob)^;
+ hContact := PInt_ptr(int_ptr(Pointer(EventInfo.pBlob)) + SizeOf(dword))^;
+ BytePos := SizeOf(dword) + SizeOf(THandle); // !!
+ // read nick
+ ReadStringTillZeroA(Pointer(EventInfo.pBlob), EventInfo.cbBlob, Nick, BytePos);
+ if Nick = '' then
+ NickW := GetContactDisplayName(hContact, '', true)
+ else
+ NickW := AnsiToWideString(Nick, CP_ACP);
+ // read first name
+ ReadStringTillZeroA(Pointer(EventInfo.pBlob), EventInfo.cbBlob, Name, BytePos);
+ Name := Name + ' ';
+ // read last name
+ ReadStringTillZeroA(Pointer(EventInfo.pBlob), EventInfo.cbBlob, Name, BytePos);
+ Name := AnsiString(Trim(String(Name)));
+ if Name <> '' then
+ Name := Name + ', ';
+ // read Email
+ ReadStringTillZeroA(Pointer(EventInfo.pBlob), EventInfo.cbBlob, Email, BytePos);
+ if Email <> '' then
+ Email := Email + ', ';
+ // read reason
+ ReadStringTillZeroA(Pointer(EventInfo.pBlob), EventInfo.cbBlob, Reason, BytePos);
+
+ ReasonUTF := AnsiToWideString(Reason, CP_UTF8);
+ ReasonACP := AnsiToWideString(Reason, hppCodepage);
+ if (Length(ReasonUTF) > 0) and (Length(ReasonUTF) < Length(ReasonACP)) then
+ ReasonW := ReasonUTF
+ else
+ ReasonW := ReasonACP;
+ Hi.Text := Format(TranslateW('Authorisation request by %s (%s%d): %s'),
+ [NickW, AnsiToWideString(Name + Email, hppCodepage), uin, ReasonW]);
+end;
+
+procedure GetEventTextForYouWereAdded(EventInfo: TDBEventInfo; var Hi: THistoryItem);
+var
+ BytePos: LongWord;
+ uin: integer;
+ hContact:THandle;
+ Nick,Name,Email: AnsiString;
+ NickW: String;
+begin
+ // blob is: uin(DWORD), hContact(THANDLE), nick(ASCIIZ), first(ASCIIZ), last(ASCIIZ), email(ASCIIZ)
+ uin := PDWord(EventInfo.pBlob)^;
+ hContact := PInt_ptr(int_ptr(Pointer(EventInfo.pBlob)) + SizeOf(dword))^;
+ BytePos := SizeOf(dword) + SizeOf(THandle); // !!
+ // read nick
+ ReadStringTillZeroA(Pointer(EventInfo.pBlob), EventInfo.cbBlob, Nick, BytePos);
+ if Nick = '' then
+ NickW := GetContactDisplayName(hContact, '', true)
+ else
+ NickW := AnsiToWideString(Nick, CP_ACP);
+ // read first name
+ ReadStringTillZeroA(Pointer(EventInfo.pBlob), EventInfo.cbBlob, Name, BytePos);
+ Name := Name + ' ';
+ // read last name
+ ReadStringTillZeroA(Pointer(EventInfo.pBlob), EventInfo.cbBlob, Name, BytePos);
+ Name := AnsiString(Trim(String(Name)));
+ if Name <> '' then
+ Name := Name + ', ';
+ ReadStringTillZeroA(Pointer(EventInfo.pBlob), EventInfo.cbBlob, Email, BytePos);
+ if Email <> '' then
+ Email := Email + ', ';
+ Hi.Text := Format(TranslateW('You were added by %s (%s%d)'),
+ [NickW, AnsiToWideString(Name + Email, hppCodepage), uin]);
+end;
+
+procedure GetEventTextForSms(EventInfo: TDBEventInfo; var Hi: THistoryItem);
+var
+ cp: Cardinal;
+begin
+ if Boolean(EventInfo.flags and DBEF_UTF) then
+ cp := CP_UTF8
+ else
+ cp := Hi.CodePage;
+ Hi.Text := AnsiToWideString(PAnsiChar(EventInfo.pBlob), cp);
+end;
+
+procedure GetEventTextForContacts(EventInfo: TDBEventInfo; var Hi: THistoryItem);
+var
+ BytePos: LongWord;
+ Contacts: AnsiString;
+ cp: Cardinal;
+begin
+ BytePos := 0;
+ Contacts := '';
+ While BytePos < Cardinal(EventInfo.cbBlob) do
+ begin
+ Contacts := Contacts + #13#10;
+ ReadStringTillZeroA(Pointer(EventInfo.pBlob), EventInfo.cbBlob, Contacts, BytePos);
+ Contacts := Contacts + ' (ICQ: ';
+ ReadStringTillZeroA(Pointer(EventInfo.pBlob), EventInfo.cbBlob, Contacts, BytePos);
+ Contacts := Contacts + ')';
+ end;
+ if Boolean(EventInfo.flags and DBEF_SENT) then
+ Hi.Text := 'Outgoing contacts: %s'
+ else
+ Hi.Text := 'Incoming contacts: %s';
+ if Boolean(EventInfo.flags and DBEF_UTF) then
+ cp := CP_UTF8
+ else
+ cp := Hi.CodePage;
+ hi.Text := Format(TranslateUnicodeString(hi.Text),[AnsiToWideString(Contacts,cp)]);
+end;
+
+procedure GetEventTextForWebPager(EventInfo: TDBEventInfo; var Hi: THistoryItem);
+var
+ BytePos: LongWord;
+ Body,Name,Email: AnsiString;
+ cp: Cardinal;
+begin
+ BytePos := 0;
+ ReadStringTillZeroA(Pointer(EventInfo.pBlob),EventInfo.cbBlob,Body,BytePos);
+ ReadStringTillZeroA(Pointer(EventInfo.pBlob),EventInfo.cbBlob,Name,BytePos);
+ ReadStringTillZeroA(Pointer(EventInfo.pBlob),EventInfo.cbBlob,Email,BytePos);
+ if Boolean(EventInfo.flags and DBEF_UTF) then
+ cp := CP_UTF8
+ else
+ cp := hppCodepage;
+ hi.Text := Format(TranslateW('Webpager message from %s (%s): %s'),
+ [AnsiToWideString(Name,cp),
+ AnsiToWideString(Email,cp),
+ AnsiToWideString(#13#10+Body,cp)]);
+end;
+
+procedure GetEventTextForEmailExpress(EventInfo: TDBEventInfo; var Hi: THistoryItem);
+var
+ BytePos: LongWord;
+ Body,Name,Email: AnsiString;
+ cp: Cardinal;
+begin
+ BytePos := 0;
+ ReadStringTillZeroA(Pointer(EventInfo.pBlob),EventInfo.cbBlob,Body,BytePos);
+ ReadStringTillZeroA(Pointer(EventInfo.pBlob),EventInfo.cbBlob,Name,BytePos);
+ ReadStringTillZeroA(Pointer(EventInfo.pBlob),EventInfo.cbBlob,Email,BytePos);
+ if Boolean(EventInfo.flags and DBEF_UTF) then
+ cp := CP_UTF8
+ else
+ cp := hppCodepage;
+ Hi.Text := Format(TranslateW('Email express from %s (%s): %s'),
+ [AnsiToWideString(Name, cp), AnsiToWideString(Email, cp),
+ AnsiToWideString(#13#10 + Body, cp)]);
+end;
+
+procedure GetEventTextForStatusChange(EventInfo: TDBEventInfo; var Hi: THistoryItem);
+var
+ tmp: THistoryItem;
+begin
+ tmp.Codepage := hppCodepage;
+ GetEventTextForMessage(EventInfo,tmp);
+ hi.Text := Format(TranslateW('Status change: %s'),[tmp.Text]);
+end;
+
+procedure GetEventTextForAvatarChange(EventInfo: TDBEventInfo; var Hi: THistoryItem);
+var
+ msgA: PAnsiChar;
+ msgW: PWideChar;
+ msglen,lenW: Cardinal;
+ i: integer;
+begin
+ msgA := PAnsiChar(EventInfo.pBlob);
+ msgW := nil;
+ msglen := lstrlenA(PAnsiChar(EventInfo.pBlob)) + 1;
+ if msglen > Cardinal(EventInfo.cbBlob) then
+ msglen := EventInfo.cbBlob;
+ if Boolean(EventInfo.flags and DBEF_UTF) then
+ begin
+ SetLength(Hi.Text, msglen);
+ lenW := Utf8ToWideChar(PWideChar(Hi.Text), msglen, msgA, msglen - 1, Hi.CodePage);
+ if Integer(lenW) > 0 then
+ SetLength(Hi.Text, lenW - 1)
+ else
+ Hi.Text := AnsiToWideString(msgA, Hi.CodePage, msglen - 1);
+ end
+ else
+ begin
+ lenW := 0;
+ if Cardinal(EventInfo.cbBlob) >= msglen * SizeOf(WideChar) then
+ begin
+ msgW := PWideChar(msgA + msglen);
+ for i := 0 to ((Cardinal(EventInfo.cbBlob) - msglen) div SizeOf(WideChar)) - 1 do
+ if msgW[i] = #0 then
+ begin
+ lenW := i;
+ break;
+ end;
+ end;
+ if (lenW > 0) and (lenW < msglen) then
+ SetString(Hi.Text, msgW, lenW)
+ else
+ Hi.Text := AnsiToWideString(msgA, Hi.CodePage, msglen - 1);
+ msglen := msglen + (lenW + 1) * SizeOf(WideChar);
+ end;
+ if msglen < Cardinal(EventInfo.cbBlob) then
+ begin
+ msgA := msgA + msglen;
+ if lstrlenA(msgA) > 0 then
+ Hi.Extended := msgA;
+ end;
+end;
+
+function GetEventTextForICQSystem(EventInfo: TDBEventInfo; Template: String): String;
+var
+ BytePos: LongWord;
+ Body: AnsiString;
+ uin: Integer;
+ Name: WideString;
+ cp: Cardinal;
+begin
+ BytePos := 0;
+ ReadStringTillZeroA(Pointer(EventInfo.pBlob), EventInfo.cbBlob, Body, BytePos);
+ if Cardinal(EventInfo.cbBlob) < (BytePos + 4) then
+ uin := 0
+ else
+ uin := PDWord(PAnsiChar(EventInfo.pBlob) + BytePos)^;
+ if Cardinal(EventInfo.cbBlob) < (BytePos + 8) then
+ Name := TranslateW('''(Unknown Contact)''' { TRANSLATE-IGNORE } )
+ else
+ Name := GetContactDisplayName(PDWord(PAnsiChar(EventInfo.pBlob) + BytePos + 4)^, '', true);
+ if Boolean(EventInfo.flags and DBEF_UTF) then
+ cp := CP_UTF8
+ else
+ cp := hppCodepage;
+ Result := Format(Template, [Name, uin, AnsiToWideString(#13#10 + Body, cp)]);
+end;
+
+procedure GetEventTextForICQAuthGranted(EventInfo: TDBEventInfo; var Hi: THistoryItem);
+begin
+ hi.Text := GetEventTextForICQSystem(EventInfo,
+ TranslateW('Authorization request granted by %s (%d): %s'));
+end;
+
+procedure GetEventTextForICQAuthDenied(EventInfo: TDBEventInfo; var Hi: THistoryItem);
+begin
+ hi.Text := GetEventTextForICQSystem(EventInfo,
+ TranslateW('Authorization request denied by %s (%d): %s'));
+end;
+
+procedure GetEventTextForICQSelfRemove(EventInfo: TDBEventInfo; var Hi: THistoryItem);
+begin
+ hi.Text := GetEventTextForICQSystem(EventInfo,
+ TranslateW('User %s (%d) removed himself from your contact list: %s'));
+end;
+
+procedure GetEventTextForICQFutureAuth(EventInfo: TDBEventInfo; var Hi: THistoryItem);
+begin
+ hi.Text := GetEventTextForICQSystem(EventInfo,
+ TranslateW('Authorization future request by %s (%d): %s'));
+end;
+
+procedure GetEventTextForICQClientChange(EventInfo: TDBEventInfo; var Hi: THistoryItem);
+begin
+ hi.Text := GetEventTextForICQSystem(EventInfo,
+ TranslateW('User %s (%d) changed icq client: %s'));
+end;
+
+procedure GetEventTextForICQCheckStatus(EventInfo: TDBEventInfo; var Hi: THistoryItem);
+begin
+ hi.Text := GetEventTextForICQSystem(EventInfo,
+ TranslateW('Status request by %s (%d):%s'));
+end;
+
+procedure GetEventTextForICQIgnoreCheckStatus(EventInfo: TDBEventInfo; var Hi: THistoryItem);
+begin
+ hi.Text := GetEventTextForICQSystem(EventInfo,
+ TranslateW('Ignored status request by %s (%d):%s'));
+end;
+
+procedure GetEventTextForICQBroadcast(EventInfo: TDBEventInfo; var Hi: THistoryItem);
+var
+ BytePos: LongWord;
+ Body,Name,Email: AnsiString;
+ cp: Cardinal;
+begin
+ BytePos := 0;
+ ReadStringTillZeroA(Pointer(EventInfo.pBlob),EventInfo.cbBlob,Body,BytePos);
+ ReadStringTillZeroA(Pointer(EventInfo.pBlob),EventInfo.cbBlob,Name,BytePos);
+ ReadStringTillZeroA(Pointer(EventInfo.pBlob),EventInfo.cbBlob,Email,BytePos);
+ hi.Text := TranslateW('Broadcast message from %s (%s): %s');
+ if Boolean(EventInfo.flags and DBEF_UTF) then
+ cp := CP_UTF8
+ else
+ cp := hppCodepage;
+ hi.Text := Format(hi.Text,[AnsiToWideString(Name,cp),
+ AnsiToWideString(Email,cp),
+ AnsiToWideString(#13#10+Body,cp)]);
+end;
+
+procedure GetEventTextForJabberChatStates(EventInfo: TDBEventInfo; var Hi: THistoryItem);
+begin
+ if EventInfo.cbBlob = 0 then exit;
+ case PByte(EventInfo.pBlob)^ of
+ JABBER_DB_EVENT_CHATSTATES_GONE:
+ hi.Text := TranslateW('closed chat session');
+ end;
+end;
+
+procedure GetEventTextWATrackRequest(EventInfo: TDBEventInfo; var Hi: THistoryItem);
+begin
+ hi.Text := TranslateW('WATrack: information request');
+end;
+
+procedure GetEventTextWATrackAnswer(EventInfo: TDBEventInfo; var Hi: THistoryItem);
+var
+ BytePos: LongWord;
+ Artist,Title,Album,Template: String;
+begin
+ BytePos := 0;
+ ReadStringTillZeroW(Pointer(EventInfo.pBlob),EventInfo.cbBlob,Artist,BytePos);
+ ReadStringTillZeroW(Pointer(EventInfo.pBlob),EventInfo.cbBlob,Title,BytePos);
+ ReadStringTillZeroW(Pointer(EventInfo.pBlob),EventInfo.cbBlob,Album,BytePos);
+ ReadStringTillZeroW(Pointer(EventInfo.pBlob),EventInfo.cbBlob,Template,BytePos);
+ if (Artist <> '') or (Title <> '') or (Album <> '') then
+ begin
+ if Template <> '' then
+ Template := Template + #13#10;
+ Template := Template + WideFormat
+ (FormatCString(TranslateW('Artist: %s\r\nTitle: %s\r\nAlbum: %s')),
+ [Artist, Title, Album]);
+ end;
+ hi.Text := Format(TranslateW('WATrack: %s'),[Template]);
+end;
+
+procedure GetEventTextWATrackError(EventInfo: TDBEventInfo; var Hi: THistoryItem);
+begin
+ hi.Text := TranslateW('WATrack: request denied');
+end;
+
+procedure GetEventTextForOther(EventInfo: TDBEventInfo; var Hi: THistoryItem);
+var
+ cp: Cardinal;
+begin
+ TextBuffer.Allocate(EventInfo.cbBlob+1);
+ StrLCopy(TextBuffer.Buffer,PAnsiChar(EventInfo.pBlob),EventInfo.cbBlob);
+ if Boolean(EventInfo.flags and DBEF_UTF) then
+ cp := CP_UTF8
+ else
+ cp := Hi.CodePage;
+ hi.Text := AnsiToWideString(PAnsiChar(TextBuffer.Buffer),cp);
+end;
+
+initialization
+ EventBuffer := THppBuffer.Create;
+ TextBuffer := THppBuffer.Create;
+
+finalization
+ EventBuffer.Destroy;
+ TextBuffer.Destroy;
+ SetLength(ModuleEventRecords,0);
+
+end.