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/outboxLib.pas

422 lines
9.3 KiB
Plaintext

{
This file is part of R&Q.
Under same license
}
unit outboxLib;
{$I RnQConfig.inc}
interface
uses
Classes, SysUtils, RnQStrings, RDGlobal, ICQContacts;
{$I NoRTTI.inc}
const
OE_msg = 1;
OE_contacts = 2;
OE_addedYou = 3;
OE_auth = 4;
OE_authDenied = 5;
OEvent2ShowStr: array [OE_msg .. OE_authDenied] of string = (Str_message, 'Contacts', 'Added you', 'Authorization given',
'Authorization denied');
type
POEvent = ^TOEvent;
TOEvent = class
public
kind: integer;
flags: Cardinal;
whom: TICQContact;
info: string;
cl: TRnQCList;
wrote, lastmodify: Tdatetime;
// ack fields
timeSent: Tdatetime;
ID: Integer;
sID: String;
filepos: integer;
constructor Create(pKind: Integer); // override;
destructor Destroy; override;
function ToString: RawByteString;
function FromString(const s: RawByteString): Boolean;
function Clone: TOEvent;
end;
Toutbox = class(Tlist)
public
// destructor Destroy; override;
function ToString: RawByteString;
procedure FromString(s: RawByteString);
function Empty: Boolean;
function Pop: TOEvent;
procedure Clear; override;
procedure ClearU;
protected
procedure Notify(Ptr: Pointer; Action: TListNotification); OverRide;
public
function Add(kind: integer; dest: TICQContact; flags: integer = 0; const info: string = ''): TOEvent; overload;
function Add(kind: integer; dest: TICQContact; flags: integer; cl: TRnQCList): TOEvent; overload;
function GetAt(idx: integer): TOEvent;
function Remove(ev: TOEvent): Boolean; overload;
function StFor(who: TICQContact): Boolean;
function FindID(const sID: String): Integer;
procedure UpdateScreenFor(cnt: TICQContact);
end;
implementation
uses
SciterLib, globalLib, mainDlg, utilLib, roasterLib,
RnQCrypt, RQUtil, RnQDialogs, RDUtils, RnQBinUtils, ICQCommon;
{ destructor Toutbox.Destroy;
begin
clear;
inherited
end; // destroy
}
function Toutbox.ToString: RawByteString;
var
s: RawByteString;
res: RawByteString;
i: integer;
begin
res := ''; // file version
if count > 0 then
begin
for i := 0 to count - 1 do
begin
s := getAt(i).ToString;
res := res + int2str(Length(s)) + s;
end;
i := StrToIntDef(TICQContact.TrimUID(Account.AccProto.MyAccNum), 0);
critt(res, i);
end;
Result := 'VER' + int2str(1) + res;
end;
procedure Toutbox.FromString(s: RawByteString);
var
i, l: integer;
ev: TOEvent;
begin
i := StrToIntDef(String(TICQContact.TrimUID(Account.AccProto.MyAccNum)), 0);
s := decritted(Copy(s, 8, Length(s)), i);
ClearU;
i := 1;
if Length(s) < 4 then
Exit;
try
while i < Length(s) do
begin
l := Integer((@s[i])^);
Inc(i, 4);
ev := TOEvent.Create(OE_msg);
if ev.FromString(copy(s, i, l)) then
add(ev)
else
ev.Free;
inc(i, l);
end;
UpdateScreenFor(nil);
except
msgDlg('Error on load outbox', True, mtError);
end;
end;
procedure Toutbox.Clear;
begin
inherited;
ActionManager.Execute(AK_SAVEOUTBOX, SaveDelay);
end;
procedure Toutbox.ClearU;
var
i: integer;
oe: TOEvent;
begin
for i := count - 1 downto 0 do
begin
oe := getAt(i);
if oe <> nil then
with oe do
try
UpdateScreenFor(whom);
Items[i] := nil;
except end;
end;
inherited;
ActionManager.Execute(AK_SAVEOUTBOX, SaveDelay);
end;
function Toutbox.add(kind: integer; dest: TICQContact; flags: integer; cl: TRnQCList): TOEvent;
begin
result := add(kind, dest, flags);
result.cl := TRnQCList.Create;
result.cl.assign(cl);
end;
function Toutbox.add(kind: integer; dest: TICQContact; flags: integer = 0; const info: string = ''): TOEvent;
var
found: Boolean;
i: integer;
begin
Result := nil;
Found := False;
if (kind in [OE_addedYou, OE_auth, OE_authDenied]) then
for i := 0 to count - 1 do
begin
result := getAt(i);
if (kind = result.kind) and (dest.equals(result.whom)) then
begin
found := True;
Break;
end;
end;
if not found then
begin
Result := TOEvent.Create(kind);
add(result);
end;
Result.kind := kind;
Result.flags := flags;
Result.whom := dest;
Result.info := info;
Result.wrote := now;
Result.lastmodify := now;
Result.cl := nil;
UpdateScreenFor(result.whom);
ActionManager.Execute(AK_SAVEOUTBOX, SaveDelay);
end;
function Toutbox.getAt(idx: integer): TOEvent;
begin
if (idx >= 0) and (idx < count) then
result := list[idx]
else
result := nil;
end;
procedure Toutbox.Notify(Ptr: Pointer; Action: TListNotification);
begin
inherited;
if (Action = lnDeleted) and (Ptr <> nil) then
TOEvent(Ptr).Free;
end;
function Toutbox.remove(ev: TOEvent): Boolean;
var
i: integer;
begin
// Result := inherited remove(ev)>=0;
i := IndexOf(ev);
if i >= 0 then
begin
result := True;
list[i] := nil;
Delete(i);
UpdateScreenFor(ev.whom);
ActionManager.Execute(AK_SAVEOUTBOX, SaveDelay);
end else
Result := False;
end;
function Toutbox.Pop: TOEvent;
begin
Result := nil;
if Count > 0 then
begin
Result := getAt(0);
List[0] := nil;
Delete(0);
UpdateScreenFor(result.whom);
ActionManager.Execute(AK_SAVEOUTBOX, SaveDelay);
end;
end;
function Toutbox.Empty: Boolean;
begin
Result := Count = 0
end;
function Toutbox.stFor(who: TICQContact): Boolean;
var
i: integer;
ev: TOEvent;
begin
Result := False;
if Assigned(who) and (who is TICQContact) then
for i := 0 to count - 1 do
begin
ev := getAt(i);
if Assigned(ev) and Assigned(ev.whom) and who.equals(ev.whom) then
begin
Result := True;
Exit;
end;
end;
end;
procedure Toutbox.UpdateScreenFor(cnt: TICQContact);
begin
UI.CL.UpdateAdditionalImage;
if (cnt = nil) or (cnt.UID = '0') then
Exit;
if Assigned(UI.Chat) then
with UI.Chat do
if Assigned(CurrentContact) and CurrentContact.Equals(cnt) then
UpdateStatusBar;
roasterLib.UpdateInPlace(cnt);
end;
function Toutbox.FindID(const sID: String): Integer;
var
e: TOEvent;
begin
for Result := Count - 1 downto 0 do
begin
e := GetAt(Result);
if Assigned(e) and (e.sID = sID) then
Exit;
end;
Result := -1;
end;
/// /////////////////////////////////////////////////////////////////////
const
OEK_kind = 1;
OEK_flags = 2;
OEK_email = 3;
OEK_uin = 4;
OEK_info = 5;
OEK_wrote = 6;
OEK_cl = 7;
OEK_lastmod = 8;
OEK_UID = 10;
function TOEvent.ToString: RawByteString;
procedure WriteDown(Code: integer; const Data: RawByteString);
begin
Result := Result + int2str(Length(data)) + int2str(code) + Data
end;
begin
Result := '';
WriteDown(OEK_kind, int2str(kind));
WriteDown(OEK_flags, int2str(flags));
if Assigned(whom) then
WriteDown(OEK_UID, UTF(whom.UID));
WriteDown(OEK_info, UTF(info));
WriteDown(OEK_wrote, dt2str(wrote));
WriteDown(OEK_lastmod, dt2str(lastmodify));
if Assigned(cl) then
WriteDown(OEK_cl, cl.toString);
end;
function TOEvent.FromString(const s: RawByteString): Boolean;
var
i, l, code, next: integer;
uid: TUID;
begin
i := 1;
Result := True;
try
while i+8 < Length(s) do
begin
l := Integer((@s[i])^);
Inc(i, 4);
code := Integer((@s[i])^);
Inc(i, 4);
next := i + l;
case code of
OEK_kind:
kind := Integer((@s[i])^);
OEK_flags:
flags := Integer((@s[i])^);
OEK_wrote:
wrote := TDateTime((@s[i])^);
OEK_lastmod:
lastmodify := TDateTime((@s[i])^);
OEK_info:
info := UnUTF(Copy(s, i, l));
OEK_uin:
begin
{$IFDEF UID_IS_UNICODE}
uid := IntToStr(Integer((@s[i])^));
{$ELSE ansi}
uid := IntToStr(Integer((@s[i])^));
{$ENDIF UID_IS_UNICODE}
whom := Account.AccProto.GetContact(uid);
end;
OEK_UID:
begin
{$IFDEF UID_IS_UNICODE}
uid := UnUTF(Copy(s, i, l));
{$ELSE ansi}
uid := Copy(s, i, l);
{$ENDIF UID_IS_UNICODE}
whom := Account.AccProto.getContact(uid);
end;
OEK_cl:
begin
if cl = nil then
cl := TRnQCList.Create;
cl.FromString(Copy(s, i, l), Account.AccProto.contactsDB);
end;
end;
i := next;
end;
except
Result := False;
end;
end;
function TOEvent.Clone: TOEvent;
begin
Result := TOEvent.Create(Self.kind);
result.flags := Self.flags;
result.whom := Self.whom;
result.info := Self.info;
if Self.cl <> nil then
result.cl := cl.Clone
else
result.cl := nil;
result.wrote := Self.wrote;
result.lastmodify := lastmodify;
result.timeSent := timeSent;
result.ID := ID;
result.filepos := filepos;
end;
destructor TOEvent.Destroy;
begin
if Assigned(cl) then
FreeAndNil(cl);
whom := nil;
SetLength(info, 0);
inherited;
end;
constructor TOEvent.Create(pKind: Integer);
begin
kind := pKind;
flags := 0;
whom := nil;
info := '';
cl := nil;
end;
end.