Browse Source

420x200 taskbar preview

Fixed error with animated avatars on taskbar buttons
Restored contact e-mail retrieval
Fixed contacts sending
Attempt to fix "canvas does not allow drawing" error
Lang updated
oldchat
Mikanoshi 6 years ago
parent
commit
44c162eca6
33 changed files with 1118 additions and 930 deletions
  1. +2
    -1
      Distro/.gitignore
  2. BIN
      Distro/RnQ1124_m.zLng
  3. +77
    -21
      Distro/RnQ1124_rus.utflng
  4. +9
    -2
      README.html
  5. +4
    -38
      RnQ/ICQ/ICQConsts.pas
  6. +85
    -71
      RnQ/ICQ/ICQv9.pas
  7. +53
    -44
      RnQ/ICQ/Protocol_ICQ.pas
  8. +2
    -1
      RnQ/ICQ/RQ_ICQ.pas
  9. +6
    -2
      RnQ/ICQ/Stickers.pas
  10. +22
    -0
      RnQ/ICQ/icq_fr.dfm
  11. +1
    -1
      RnQ/ICQ/icq_fr.pas
  12. +2
    -2
      RnQ/ICQ/viewinfoDlg.dfm
  13. +13
    -13
      RnQ/ICQ/viewinfoDlg.pas
  14. +53
    -1
      RnQ/Protocols_all.pas
  15. +2
    -2
      RnQ/RnQBuiltTime.inc
  16. +49
    -22
      RnQ/RnQProtocol.pas
  17. +28
    -20
      RnQ/RnQTips.pas
  18. +2
    -2
      RnQ/RnQ_Avatars.pas
  19. +4
    -0
      RnQ/RnQdbDlg.dfm
  20. +1
    -1
      RnQ/RnQdbDlg.pas
  21. +24
    -24
      RnQ/RnQx64.dproj
  22. +1
    -1
      RnQ/ThemesLib.pas
  23. +426
    -0
      RnQ/ViewPicDimmedDlg.pas
  24. +2
    -0
      RnQ/chatDlg.dfm
  25. +166
    -188
      RnQ/chatDlg.pas
  26. +9
    -9
      RnQ/events.pas
  27. +1
    -1
      RnQ/globalLib.pas
  28. +2
    -2
      RnQ/historyVCL.pas
  29. +5
    -400
      RnQ/utilLib.pas
  30. +46
    -42
      for.RnQ/RQThemes.pas
  31. +4
    -4
      for.RnQ/RTL/RnQGraphics32.pas
  32. +13
    -11
      for.RnQ/RnQLangs.pas
  33. +4
    -4
      for.RnQ/tipDlg.pas

+ 2
- 1
Distro/.gitignore View File

@ -8,4 +8,5 @@ common.ini
/5104073/
/662846976/
/694631417/
/Stickers/
/Stickers/
/Cache/

BIN
Distro/RnQ1124_m.zLng View File


+ 77
- 21
Distro/RnQ1124_rus.utflng View File

@ -507,33 +507,35 @@ HTML
[left:]
осталось:
[(multi-send)]
(Отправлено списком)
(отправлено списком)
[%2:s %0:s, %1:s]
%2:s %0:s, %1:s
[%2:s %0:s, %1:s sent file]
%2:s %0:s, %1:s отправил(а) файл
[%2:s %0:s, %1:s started typing]
%2:s %0:s, %1:s начал(а) печатать
[%2:s %0:s, %1:s finished typing]
%2:s %0:s, %1:s закончил(а) печтатать
[%2:s %0:s, %1:s is online]
%2:s %0:s, %1:s онлайн
[%2:s %0:s, %1:s is offline]
%2:s %0:s, %1:s оффлайн
[%2:s %0:s, %1:s auto-message]
[%2:s %0:s, %1:s: auto-message]
%2:s %0:s, %1:s: автосообщение
[%2:s %0:s, %1:s requested your auto-message]
%2:s %0:s, %1:s запросил ваше автосообщение
[%2:s %0:s, %1:s Request authorization]
[%2:s %0:s, %1:s: auto-message request]
%2:s %0:s, %1:s: запрос автосообщения
[%2:s %0:s, %1:s: authorization request]
%2:s %0:s, %1:s: запрос авторизации
[%2:s %0:s, %1:s Authorized]
%2:s %0:s, %1:s авторизован
[%2:s %0:s, %1:s Denied authorization]
%2:s %0:s, %1:s отказано в авторизации
[%2:s %0:s, %1:s - status %3:s]
%2:s %0:s, %1:s: статус %3:s
[%2:s %0:s, %1:s - status %3:s]
%2:s %0:s, %1:s: статус %3:s
[%2:s %0:s, %1:s Greeting Card]
[%2:s %0:s, %1:s: authorized]
%2:s %0:s, %1:s: авторизован
[%2:s %0:s, %1:s: denied authorization]
%2:s %0:s, %1:s: отказ в авторизации
[%2:s %0:s, %1:s: status %0:s]
%2:s %0:s, %1:s: статус %0:s
[%2:s %0:s, %1:s: greeting card]
%2:s %0:s, %1:s: открытка
[%2:s %0:s, %1:s requested your XStatus]
%2:s %0:s, %1:s запросил ваш доп.статус
[%2:s %0:s, %1:s - status %3:s]
%2:s %0:s, %1:s: статус %3:s
%2:s %0:s, %1:s запросил ваш доп. статус
[Scrolls the message line by line\nCTRL+UP, CTRL+DOWN]
Прокручивать сообщение построчно\nCTRL+ВВЕРХ, CTRL+ВНИЗ
[Scrolls the message line by line]
@ -1006,6 +1008,8 @@ UIN-листы
[SPAM FILTERED FROM %s \n BY WORD %s]
Отфильтрован спам от %s\nпо слову "%s"
[Load the whole history before removing messages]
Загрузите историю полностью прежде чем удалять сообщения
[The contacts database is corrupted, some data is lost]
База данных контактов повреждена, некоторые данные утеряны
[Server says you're reconnecting too fastly, try later or change user.]
@ -1070,7 +1074,7 @@ URL от %s
открытка от %s
[auto-message for %s]
автосообщение от %s
[Begun typing]
[Started typing]
Начал(а) печатать
[Finished typing]
Закончил(а) печатать
@ -1535,7 +1539,7 @@ $[ICQ]
[Delete offline messages (from server) on start]
Удалять принятые офлайн сообщения с сервера
[Reopen previous chats on start]
Открывать чаты при запуске
Открывать прошлые чаты при запуске
[Auto start with UIN]
Запуск с UIN'ом
[current UIN]
@ -3145,10 +3149,12 @@ RTP аудио
Добавить список к отмеченным
[Save selected as a uin-list]
Сохранить отмеченные как список
[ -no info]
[- no info]
- нет информации
[ -newer info available on server]
[- newer info available on server]
- на сервере есть более новая информация
[- user not found on server]
- на сервере нет такого юзера
[Internal IP]
Внутренний IP-адрес
@ -3425,6 +3431,56 @@ _________
Прокси: Неправильный пароль или имя пользователя
[PROXY: Unknown reply\n[%d]\n%s]
Прокси: Неизвестная ошибка\n[%d]\n%s
[SSI message error\n%s]
Ошибка SSI сообщения\n%s
[Invalid SNAC header]
Неверный SNAC заголовок
[Server rate limit exceeded]
Превышен лимит сервера
[Client rate limit exceeded]
Превышен лимит клиента
[Recipient is not logged in]
Получатель не залогинен
[Requested service unavailable]
Запрошенный сервис недоступен
[Requested service not defined]
Запрошенный сервис не определён
[You sent obsolete SNAC]
Отправлен устаревший SNAC
[Not supported by server]
Не поддерживается сервером
[Not supported by client]
Не поддерживается клиентом
[Refused by client]
Отклонено клиентом
[Reply too big]
Ответ слишком большой
[Responses lost]
Ответы потеряны
[Request denied]
Запрос отклонён
[Incorrect SNAC format]
Неверный формат SNAC
[Insufficient rights]
Недостаточно прав
[In local permit/deny (recipient blocked)]
В локальном списке доступа (получатель заблокирован)
[Sender too evil]
Отправитель превысил лимит
[Receiver too evil]
Получатель превысил лимит
[User temporarily unavailable]
Пользователь временно недоступен
[No match]
Нет совпадений
[List overflow]
Переполнение списка
[Request ambiguous]
Неоднозначный запрос
[Server queue full]
Очередь запросов на сервере заполнена
[Not while on AOL]
Не на AOL
[SSL: libeay32.dll or ssleay32.dll not found\n%s]
SSL: Не найден файл libeay32.dll или ssleay32.dll\n%s
[R&Q error: Could't decrypt message. Bad CRC.\n[%s]]


+ 9
- 2
README.html View File

@ -1,8 +1,8 @@
<div style="line-height: 150%;">
<h1>R&Q 1125 Кастомная сборка</h1>
Номер сборки: 24<br>
Последнее обновление: 01.10.2015
Номер сборки: 25<br>
Последнее обновление: 23.10.2015
<br /><div style="width: 100%; height: 1px; border-top: #D3D3D3 solid 1px;"></div><br />
<u>Особенности сборки</u><br>
@ -45,6 +45,13 @@ smiles.selected.frame.color=969696</pre></blockquote>
<h2>История версий</h2>
1125 Сборка 25<br>
- Уменьшена высота превью во всплывающем окне на панели задач<br>
- Исправлена ошибка при использовании аватаров на кнопках в панели задач<br>
- Исправлено получение e-mail адресов контактов<br>
- Исправлена отправка списка контактов<br>
- Обновлён перевод<br><br>
1125 Сборка 24<br>
- Поддержка Windows 10, обновлены некоторые элементы интерфейса, убрана тень у всплывающих подсказок<br>
- Отображение 7 первых открытых чатов в виде кнопок во всплывающем окне на панели задач<br>


+ 4
- 38
RnQ/ICQ/ICQConsts.pas View File

@ -710,8 +710,8 @@ type
// at login-time, referred to my own uin
EC_missingLogin, EC_anotherLogin, EC_serverDisconnected, EC_badPwd, EC_cantChangePwd,
EC_loginDelay, EC_cantCreateUIN, EC_invalidFlap, EC_badContact, EC_cantConnect_dc,
EC_proxy_error, EC_proxy_badPwd, EC_proxy_unk // unknown reply
);
EC_proxy_error, EC_proxy_badPwd, EC_proxy_unk, // unknown reply
EC_SSI_error);
const
icqerror2str: array [TicqError] of string =
@ -733,7 +733,8 @@ const
'can''t directly connect\n[%d]\n%s', 'proxy: error', 'PROXY: Invalid user/password',
// 'proxy: wrong user/pwd',
// 'PROXY: Unknown reply\n[%d]\n%s' // 'proxy: unk'
ProxyUnkError);
ProxyUnkError,
'SSI message error\n%s');
ICQauthErrors: array [1 .. $2A] of string = (
@ -941,41 +942,6 @@ array [0 .. 4] of string = ('Message was invalid', 'Message was too large', 'Mes
'Sender too evil (sender warn level > your max_msgs_evil)',
'You are too evil (sender max_msg_revil < your warn level)');
var
AntiSpamMsgs: array [0 .. 6] of String = (
// (
(
'Your message has been blocked for antispam reason.'
),
(
'You entered invalid code. Try again.'
),
(
'Confirmation accepted. Your message recieved. Thank you.'
),
(
'You failed antispam verification. You have no attemts. Your UIN (%uin%) is ignored.'
),
(
'Please, type digital CODE which you can see below (3 digits).'
),
(
'You have attempts: %attempt%.'
), // %code%
(
'Please, type answer on question which you can see below.'
)
{ )
(
('Ваше сообщение заблокировано антиспам плагином.'),
('Вы ввели не правильный код. Попробуйте еще раз.'),
('Код принят. Ваше сообщение получено. Спасибо.'),
('Вы не прошли антиспам проверку. У вас не осталось попыток. Ваш UIN (%uin%) игнорируется.'),
('Пожалуйста, введите цифровой КОД который вы видите ниже (3 цифры). '),
('Осталось попыток: %attempt%.'#13#10'%code%')
) }
);
function CAPS_sm2big(i: byte): RawByteString; inline;
var
// ExtStsStrings : array[low(aXStatus)..High(aXStatus),0..1] of string;


+ 85
- 71
RnQ/ICQ/ICQv9.pas View File

@ -16,7 +16,7 @@ uses
WinSock,
ICQflap,
RnQProtocol,
ICQContacts, strutils,
ICQContacts, strutils, math,
RQThemes, RDGlobal, RQUtil,
RnQPrefsLib,
ICQConsts, OverbyteIcsUtils;
@ -642,7 +642,7 @@ type
procedure sendDeleteUIN;
procedure sendsaveMyInfoNew(c:TICQContact);
// procedure sendPermsNew;//(c:Tcontact);
procedure sendSticker(uin: TUID; const sticker: String);
procedure sendSticker(const uin: TUID; const sticker: String);
procedure sendInfoStatus(const s : String);
procedure sendPrivacy(em : Word; ShareWeb : Boolean; authReq : Boolean);
procedure sendReqOfflineMsgs;
@ -650,7 +650,7 @@ type
procedure sendContacts(cnt : TRnQContact;flags:dword; cl:TRnQCList);
procedure sendQueryInfo(uin: Integer);
procedure sendSimpleQueryInfo(const uin: TUID);
procedure sendAdvQueryInfo(const uin: TUID);
procedure sendAdvQueryInfo(const uin: TUID; token: RawByteString);
procedure sendFullQueryInfo(const uin: TUID);
procedure sendNewQueryInfo(const uin: TUID);
procedure sendAddedYou(const uin: TUID);
@ -807,6 +807,7 @@ type
function SSI_sendAddContact(cnt : TICQContact; needAuth : Boolean = false; pItem : TOSSIItem = NIL) : Word;
// procedure SSInewContactauth(gID,cID:integer; nUIN,cName:string);
// procedure SSIdeleteContact(gID,cID:integer; nUIN,cName:string);
procedure parse1301error(const snac: RawByteString; ref:integer; flags : word);
procedure parse131b(const pkt : RawByteString);
procedure parse131C(const pkt : RawByteString);
procedure parse1308090A(const snac:RawByteString; ref:integer; iType : Word);
@ -3649,27 +3650,25 @@ sendSNAC(ICQ_MSG_FAMILY, CLI_META_MSG, qword_LEasStr(msgID)+#0#2
end; // sendFileAck
{$ENDIF usesDC}
procedure TicqSession.sendAuthReq(const uin:TUID; const msg:string);
procedure TicqSession.sendAuthReq(const uin: TUID; const msg: string);
var
c:TICQcontact;
iam : TRnQContact;
c: TICQcontact;
iam: TRnQContact;
begin
c:=getICQContact(uin);
if not imVisibleTo(c) then
if addTempVisMsg then
addTemporaryVisible(c);
c := getICQContact(uin);
if not imVisibleTo(c) then
if addTempVisMsg then
addTemporaryVisible(c);
iam := getMyInfo;
sendSNAC(ICQ_MSG_FAMILY, CLI_META_MSG, qword_LEasStr(SNACref)+#0#4
+ Length_B(uin)
+TLV(5, myUINle+ AnsiChar(MTYPE_AUTHREQ)+ AnsiChar(#0)
sendSNAC(ICQ_MSG_FAMILY, CLI_META_MSG, qword_LEasStr(SNACref) + #00#04 + Length_B(uin)
+ TLV(5, myUINle + AnsiChar(MTYPE_AUTHREQ) + AnsiChar(#00)
// +WNTS(getMyInfo.nick+#$FE+getMyInfo.first+#$FE+getMyInfo.last+#$FE+ MyInfo0.email+#$FE#0#$FE+msg)
+WNTS(StrToUTF8(iam.nick)+AnsiChar(#$FE)+
StrToUTF8(iam.first)+AnsiChar(#$FE)+
StrToUTF8(iam.last)+AnsiChar(#$FE)+
''+AnsiString(#$FE#0#$FE)+
StrToUTF8(msg))
)
);
+ WNTS(StrToUTF8(iam.nick) + AnsiChar(#$FE) +
StrToUTF8(iam.first) + AnsiChar(#$FE) +
StrToUTF8(iam.last) + AnsiChar(#$FE) +
'' + AnsiString(#$FE#0#$FE) +
StrToUTF8(msg))
));
end; // sendAuthReq
procedure TicqSession.sendMSGsnac(const uin : TUID; const sn : RawByteString);
@ -4245,88 +4244,87 @@ begin
addRef(REF_wp, '');
end; // sendWPsearch
procedure TicqSession.sendWPsearch2(wp:TwpSearch; idx : Integer; IsWP : Boolean = True);
procedure TicqSession.sendWPsearch2(wp: TwpSearch; idx: Integer; IsWP: Boolean = True);
function TLVIfNotNull(t : word; const s : RawByteString) : RawByteString;
begin
if s > '' then
result := TLV(t, WNTS(s));
result := TLV(t, WNTS(s));
end;
function TLVIfbNotNull(t : word; b : byte) : RawByteString;
begin
if b > 0 then
result := TLV(t, AnsiChar(b));
result := TLV(t, AnsiChar(b));
end;
function TLVIfWNotNull(t : word; w : word) : RawByteString;
begin
if w > 0 then
result := TLV(t, word_BEasStr(w));
result := TLV(t, word_BEasStr(w));
end;
function TLVIfDWNotNull(t : word; d : dword) : RawByteString;
begin
if d > 0 then
result := TLV(t, dword_BEasStr(d));
result := TLV(t, dword_BEasStr(d));
end;
function TLVIfDWLENotNull(t : word; d : dword) : RawByteString;
begin
if d > 0 then
result := TLV(t, dword_LEasStr(d));
result := TLV(t, dword_LEasStr(d));
end;
function TLVIfINotNull(t : word; w : word; const s : RawByteString) : RawByteString;
begin
if (w > 0) or (s > '') then
result := TLV(t, word_LEasStr(w) + WNTS(s));
result := TLV(t, word_LEasStr(w) + WNTS(s));
end;
{ function TLVIfSNotNull(t : word; s : String) : String;
begin
if (s > '') then
result := TLV(t, Length_LE(s));
result := TLV(t, Length_LE(s));
end;}
function TLVIfSNotNull(t : word; const s : RawByteString) : RawByteString;
begin
if (s > '') then
result := TLV(t, s);
result := TLV(t, s);
end;
//const
// TAB:array [boolean] of AnsiChar=(#$B2,#$D0);
var
s : RawByteString;
s: RawByteString;
begin
if not isReady then exit;
if not isReady then
Exit;
wasUINwp := false;
if (not IsWP) and (wp.uin > '') then
s:= TLV($05B9, Word($8000)) + #$00#$00#$00#$00+
Length_BE(#00#01#00#02#00#02) +
#$00#$00#$04#$E3#$00#$00
+ #$00#$02#$00#$03#$00#$00
s:= TLV($05B9, Word($8000)) + #$00#$00#$00#$00 + Length_BE(#00#01#00#02#00#02) +
#$00#$00#$04#$E3#$00#$00 + #$00#$02#$00#$03#$00#$00
// + TLV(02, Word(idx))
+ TLV(01,
TLVIfSNotNull(META_COMPAD_UID, wp.uin)+
TLVIfSNotNull(META_COMPAD_INFO_HASH, wp.Token)
)
TLVIfSNotNull(META_COMPAD_UID, wp.uin)+
TLVIfSNotNull(META_COMPAD_INFO_HASH, wp.Token)
)
else
begin
s := #$05#$B9#$0F#$A0#$00#$00#$00#$00#$00#$00#$00#$00#$04#$E3#$00#$00
+ TLV(02, Word(idx))
+ TLV(01,
begin
s := #$05#$B9#$0F#$A0#$00#$00#$00#$00#$00#$00#$00#$00#$04#$E3#$00#$00
+ TLV(02, Word(idx))
+ TLV(01,
// + TLVIfNotNull(User_First, wp.first)
// + TLVIfNotNull(User_Last, wp.last)
// TLVIfNotNull(META_COMPAD_UID, wp.uin)
TLVIfSNotNull(CP_User_NICK, StrToUTF8(wp.nick))
// + TLVIfNotNull(User_email, wp.email)
+ TLVIfDWNotNull(CP_User_Cntry, wp.country)
+ TLVIfSNotNull(CP_User_City, StrToUTF8(wp.city))
+ TLVIfDWNotNull(CP_User_Cntry, wp.country)
+ TLVIfSNotNull(CP_User_City, StrToUTF8(wp.city))
// + TLVIfNotNull(User_State, wp.state)
// + TLVIfINotNull(User_Inter, wp.wInterest, wp.keyword)
+ TLVIfWNotNull(CP_User_Lang, wp.lang)
+ TLVIfbNotNull(CP_User_Gender, wp.gender)
+ TLVIfDWLENotNull(CP_User_Age, wp.age)
+ TLVIfWNotNull(CP_User_ONLINE, word(wp.onlineOnly))
// + TLVIfNotNull(User_, wp.)
// + TLVIfNotNull(User_, wp.)
);
end;
+ TLVIfWNotNull(CP_User_Lang, wp.lang)
+ TLVIfbNotNull(CP_User_Gender, wp.gender)
+ TLVIfDWLENotNull(CP_User_Age, wp.age)
+ TLVIfWNotNull(CP_User_ONLINE, word(wp.onlineOnly))
// + TLVIfNotNull(User_, wp.)
// + TLVIfNotNull(User_, wp.)
);
end;
sendSNAC(ICQ_EXTENSIONS_FAMILY, CLI_META_REQ, TLV(1, Length_LE(myUINle
+ word_LEasStr(CLI_META_INFO_REQ)
@ -4334,28 +4332,38 @@ begin
+ word_LEasStr(META_SEARCH_COMPAD)
+ Length_LE(s)))
);
// if wasUINwp then
// addRef(REF_wp,wp.uin)
// else
if IsWP then
addRef(REF_wp, '');
if IsWP then
addRef(REF_wp, '');
end; // sendWPsearch2
procedure TicqSession.sendAdvQueryInfo(const uin: TUID);
procedure TicqSession.sendAdvQueryInfo(const uin: TUID; token: RawByteString);
function TLVIfSNotNull(t: word; const s: RawByteString): RawByteString;
begin
if (s > '') then
result := TLV(t, s);
end;
begin
if not isReady then exit;
if not isReady then
Exit;
if not (uin = '') then
sendSnac(ICQ_EXTENSIONS_FAMILY, CLI_META_REQ,
TLV(1, Length_LE(myUINle
+ word_LEasStr(CLI_META_INFO_REQ)
+ word_LEasStr($03)
+ word_LEasStr($00)
+ word_LEasStr(META_SEARCH_COMPAD)
+ Length_LE(SNAC_shortver($05B9, $0fa0, $00, $00, $02)
+ word_BEasStr($00)
+ word_BEasStr(GetACP)
+ dword_BEasStr($02)
+ TLV(3, '')
+ TLV(1, #00#$32 + Length_BE(uin))
+ TLV(1,
TLVIfSNotNull(META_COMPAD_UID, uin)
+ TLVIfSNotNull(META_COMPAD_INFO_HASH, token))
))
)
);
@ -4754,7 +4762,7 @@ begin
);
end; // sendChangePwd
procedure TicqSession.sendSticker(uin: TUID; const sticker: String);
procedure TicqSession.sendSticker(const uin: TUID; const sticker: String);
begin
sendSnac(ICQ_MSG_FAMILY, CLI_META_MSG, #$AB#$AB#$AB#$AB#$AB#$AB#$AB#$AB
+ word_BEasStr(MTYPE_PLAIN) + Length_B(uin)
@ -5992,13 +6000,12 @@ case Byte(snac[10]) of // msg format
inc(ofs, 2 + word_BEat(snac, ofs));
t := Byte(snac[ofs]);
if t = $10 then // Caps are required
if (t = $10) or (t = $05) then // Caps are required
begin
isTzer := false;
inc(ofs, 2);
t := word_BEat(snac, ofs);
inc(ofs, 2);
sA := copy(snac, ofs, 16); // first cap only, enough?
t := readBEWORD(snac, ofs);
sA := copy(snac, ofs, min(16, t)); // first cap only, enough?
if sA = BigCapability[CAPS_big_tZers].v then
isTzer := True;
inc(ofs, t);
@ -6008,17 +6015,14 @@ case Byte(snac[10]) of // msg format
if (ofs <= l2) and (t = $01) then
begin
inc(ofs, 2);
l := word_BEat(snac, ofs) - 4;
inc(ofs, 2);
CharsetNumber := word_BEat(snac, ofs); //The encoding used for the message.
l := readBEWORD(snac, ofs) - 4;
CharsetNumber := readBEWORD(snac, ofs); //The encoding used for the message.
//0x0000: US-ASCII
//0x0002: UCS-2BE (or UTF-16?)
//0x0003: local 8bit encoding, eg iso-8859-1, cp-1257, cp-1251.
//Beware that UCS-2BE will contain zero-bytes for characters in the US-ASCII range.
// 0006 - Unicode
inc(ofs, 2);
CharsetSubset := word_BEat(snac, ofs); //Unknown; seen: 0x0000 = 0, 0xffff = -1.
inc(ofs, 2);
CharsetSubset := readBEWORD(snac, ofs); //Unknown; seen: 0x0000 = 0, 0xffff = -1.
msg := copy(snac, ofs, l);
if CharsetNumber = 6 then
eventFlags := eventFlags or IF_Unicode
@ -7756,6 +7760,7 @@ while Q.available do
$1007: parseIcon(pkt);
{$ENDIF RNQ_AVATARS}
$1301: parse1301Error(pkt, ref, flags);
$1306: parse1306(self, serverSSI, pkt, ref);{SRV_REPLYROSTER} // By Rapid D
$1308: Parse1308090A(pkt, ref, SSI_OPERATION_CODES_ADD);
$1309: Parse1308090A(pkt, ref, SSI_OPERATION_CODES_UPDATE);
@ -7806,7 +7811,7 @@ begin
i := i or EVENTS_ALLOWED;
// if ((chn = #1)or(chn = #2)) then
i := i or OFFLINE_MSGS_ALLOWED; // Или это убивает офлайн-сообщения :)
i := i or unk0_ALLOWED or unk2_ALLOWED or unk3_ALLOWED; //or HTML_ALLOWED
i := i or unk0_ALLOWED or unk1_ALLOWED or unk3_ALLOWED; //or HTML_ALLOWED
sendSNAC(ICQ_MSG_FAMILY, $02, #$00 + chn + dword_BEasStr(i) + #$1F#$40 + #$03#$E7 + #$03#$E7 + Z);
addRef(REF_login, '');
@ -11252,7 +11257,7 @@ begin
'</NOTIFY></N>'+CRLF)));
end;
procedure TicqSession.AuthRequest(cnt : TRnQContact; const reason : String);
procedure TicqSession.AuthRequest(cnt: TRnQContact; const reason: String);
begin
// sendSNAC(ICQ_LISTS_FAMILY, $14, BUIN(uin) + Length_BE('') + #$00#$00);
// AuthGrant(cnt);
@ -11666,6 +11671,15 @@ begin
until ofs >= l;
end;
procedure TicqSession.parse1301error(const snac: RawByteString; ref: integer; flags: word);
begin
eventTime := Now;
eventFlags := 0;
eventError := EC_SSI_error;
eventInt := word_BEat(@snac[1]);
notifyListeners(IE_error);
end;
procedure TicqSession.parse131b(const pkt : RawByteString);
var
ofs : Integer;


+ 53
- 44
RnQ/ICQ/Protocol_ICQ.pas View File

@ -33,8 +33,6 @@ interface
{$ENDIF usesDC}
function enterICQpwd(const thisICQ : TRnQProtocol):boolean;
//function addToRoster(c:Tcontact):boolean; overload;
function addToRoster(c:TRnQcontact; isLocal : Boolean = False):boolean; overload;
procedure sendICQcontacts(cnt : TRnQContact; flags:integer; cl:TRnQCList);
procedure sendICQaddedYou(cnt : TRnQContact);
procedure sendICQautomsgreq(cnt : TRnQContact);
@ -277,35 +275,6 @@ begin
end; // sendfile
{$ENDIF usesDC}
function addToRoster(c:TRnQContact; isLocal : Boolean = False):boolean;
begin
notInList.remove(c);
// c.CntIsLocal := isLocal;
if isLocal then
c.SSIID := 0;
result:= c.fProto.addContact(c, isLocal);
if not result then exit;
roasterlib.update(c);
roasterLib.focus(c);
saveListsDelayed:=TRUE;
autosizeDelayed:=TRUE;
plugins.castEvList( PE_LIST_ADD, PL_ROSTER, c);
{$IFDEF UseNotSSI}
if c is TICQcontact then
// if (not icq.useSSI)and icq.useLSI3 then
with TicqSession(c.iProto.ProtoElem) do
if not UseSSI and useLSI2 then
begin
if StrToIntDef(c.uid, 0) > 0 then
begin
if TICQcontact(c).infoUpdatedTo=0 then sendQueryInfo(StrToIntDef(c.UID2cmp, 0));
if sendTheAddedYou then
Account.outbox.add(OE_addedYou, c);
end;
end;
{$ENDIF UseNotSSI}
end; // addToRoster
procedure ChangeXStatus(pICQ : TICQSession; const st : Byte;
const StName : String = ''; const StText : String = '');
var
@ -393,6 +362,7 @@ case getSnacService(s) of
$0B02: result := 'min stats report interval';
$1006: result := 'avatar request';
$1007: result := 'avatar';
$1301: result := 'client or server error';
$1302: result := 'SSI limits request';
$1303: result := 'SSI limits response';
$1304: result := 'contact list request';
@ -405,8 +375,14 @@ case getSnacService(s) of
$130E: result := 'SSI edit server ack';
$130F: result := 'local SSI is up-to-date';
$1311: result := 'SSI edit: Start transaction';
$1312: result := 'SSI edit: End transaction';
$1314: result := 'grant future auth';
$1315: result := 'future auth granted';
$1316: result := 'delete yoursef from another CL';
$1318: result := 'request auth';
$1319: result := 'auth request';
$131a: result := 'replay to auth';
$131b: result := 'auth reply';
$131c: result := 'you were added';
$1502:
case getMPservice(s) of
$3C: result := 'offline msgs request';
@ -759,12 +735,12 @@ case ev of
if Account.acks.getAt(i).kind = OE_msg then
begin
TempCh := chatFrm.chats.byContact(c);
if TempCh <> NIL then
if TempCh <> nil then
begin
// TempCh.historyBox.history.
TempEv := TempCh.historyBox.history.getByID(thisICQ.eventMsgID);
if TempEv <> NIL then
TempEv.flags := TempEv.flags OR IF_SERVER_ACCEPT;// IF_MSG_SERVER;
if TempEv <> nil then
TempEv.flags := TempEv.flags OR IF_SERVER_ACCEPT;// IF_MSG_SERVER;
// TempEv := NIL;
TempCh.repaint();
end;
@ -928,11 +904,11 @@ case ev of
if ( info = 'MSG') then
begin
TempCh := chatFrm.chats.byContact(c);
if TempCh <> NIL then
if TempCh <> nil then
begin
// TempCh.historyBox.history.
TempEv := TempCh.historyBox.history.getByID(thisICQ.eventMsgID);
if TempEv <> NIL then
if TempEv <> nil then
begin
TempEv.flags := TempEv.flags OR IF_not_delivered;// IF_MSG_OK;
TempCh.repaint();
@ -947,11 +923,11 @@ case ev of
if ( info = 'MSG') then
begin
TempCh := chatFrm.chats.byContact(c);
if TempCh <> NIL then
if TempCh <> nil then
begin
// TempCh.historyBox.history.
TempEv := TempCh.historyBox.history.getByID(thisICQ.eventMsgID);
if TempEv <> NIL then
if TempEv <> nil then
begin
TempEv.flags := TempEv.flags OR IF_not_delivered;// IF_MSG_OK;
TempCh.repaint();
@ -1114,11 +1090,11 @@ case ev of
if Account.acks.getAt(i).kind = OE_msg then
begin
TempCh := chatFrm.chats.byContact(c);
if TempCh <> NIL then
if TempCh <> nil then
begin
// TempCh.historyBox.history.
TempEv := TempCh.historyBox.history.getByID(thisICQ.eventMsgID);
if TempEv <> NIL then
if TempEv <> nil then
TempEv.flags := TempEv.flags OR IF_delivered;// IF_MSG_OK;
// TempEv := NIL;
TempCh.repaint();
@ -1243,7 +1219,36 @@ case ev of
rosterRepaintDelayed:=TRUE;
end;
IE_error:
if thisICQ.eventError = EC_badContact then
if thisICQ.eventError = EC_SSI_error then
begin
case thisICQ.eventInt of
$01: thisICQ.eventMsgA := 'Invalid SNAC header.';
$02: thisICQ.eventMsgA := 'Server rate limit exceeded';
$03: thisICQ.eventMsgA := 'Client rate limit exceeded';
$04: thisICQ.eventMsgA := 'Recipient is not logged in';
$05: thisICQ.eventMsgA := 'Requested service unavailable';
$06: thisICQ.eventMsgA := 'Requested service not defined';
$07: thisICQ.eventMsgA := 'You sent obsolete SNAC';
$08: thisICQ.eventMsgA := 'Not supported by server';
$09: thisICQ.eventMsgA := 'Not supported by client';
$0A: thisICQ.eventMsgA := 'Refused by client';
$0B: thisICQ.eventMsgA := 'Reply too big';
$0C: thisICQ.eventMsgA := 'Responses lost';
$0D: thisICQ.eventMsgA := 'Request denied';
$0E: thisICQ.eventMsgA := 'Incorrect SNAC format';
$0F: thisICQ.eventMsgA := 'Insufficient rights';
$10: thisICQ.eventMsgA := 'In local permit/deny (recipient blocked)';
$11: thisICQ.eventMsgA := 'Sender too evil';
$12: thisICQ.eventMsgA := 'Receiver too evil';
$13: thisICQ.eventMsgA := 'User temporarily unavailable';
$14: thisICQ.eventMsgA := 'No match';
$15: thisICQ.eventMsgA := 'List overflow';
$16: thisICQ.eventMsgA := 'Request ambiguous';
$17: thisICQ.eventMsgA := 'Server queue full';
$18: thisICQ.eventMsgA := 'Not while on AOL';
end;
msgDlg(getTranslation(icqerror2str[thisICQ.eventError], [getTranslation(thisICQ.eventMsgA)]), False, mtError);
end else if thisICQ.eventError = EC_badContact then
loggaEvtS(format('ERROR: bad contact: %s',[cuid]))
else
begin
@ -1382,6 +1387,8 @@ case ev of
reqXStatusQ.Add(c);
end;
autosizeDelayed:=TRUE;
if Assigned(chatFrm) then
chatFrm.RefreshTaskbarButtons;
end;
{$IFDEF RNQ_AVATARS}
IE_avatar_changed:
@ -1392,7 +1399,7 @@ case ev of
reqAvatarsQ.add(c)
else
if c.icon.ToShow = IS_AVATAR then
ClearAvatar(c);
ClearAvatar(TRnQContact(c));
// if ShowAvt then
if TO_SHOW_ICON[CNT_ICON_AVT] then
redraw(c);
@ -1613,7 +1620,9 @@ case ev of
// chatFrm.userChanged(c);
redraw(c);
updateViewInfo(c);
// autosizeDelayed:=TRUE;
if Assigned(chatFrm) then
chatFrm.RefreshTaskbarButtons;
// autosizeDelayed := True;
end;
IE_contactSelfDeleted:
begin


+ 2
- 1
RnQ/ICQ/RQ_ICQ.pas View File

@ -66,13 +66,14 @@ var
CLPktNUM: Byte;
implementation
uses
DateUtils, UtilLib, roasterlib, RDGlobal, mainDlg, RnQGlobal,
math,
{$IFDEF RNQ_AVATARS}
RnQ_Avatars,
{$ENDIF}
Base64, RnQBinUtils, RDFileUtil, RnQNet,RDUtils,
Base64, RnQBinUtils, RDFileUtil, RnQNet, RDUtils,
RQUtil, GlobalLib, RnQLangs,
Protocol_ICQ,
menusUnit,


+ 6
- 2
RnQ/ICQ/Stickers.pas View File

@ -62,8 +62,12 @@ begin
pfs.Seek(0, 0);
SetLength(stickerForChat, pfs.size);
pfs.ReadBuffer(stickerForChat[1], pfs.size);
Result := AnsiString('<RnQImageEx>') + Base64EncodeString(stickerForChat) + AnsiString('</RnQImageEx>');
if pfs.size > 0 then
begin
pfs.ReadBuffer(stickerForChat[1], pfs.size);
Result := AnsiString('<RnQImageEx>') + Base64EncodeString(stickerForChat) + AnsiString('</RnQImageEx>');
end else
Result := '';
if fsPtr = nil then
pfs.Free


+ 22
- 0
RnQ/ICQ/icq_fr.dfm View File

@ -136,6 +136,8 @@ object icqFr: TicqFr
Width = 75
Height = 25
Caption = 'test it'
DoubleBuffered = True
ParentDoubleBuffered = False
TabOrder = 4
OnClick = SpeedButton1Click
end
@ -193,6 +195,10 @@ object icqFr: TicqFr
object SecTS: TTabSheet
Caption = 'Security'
ImageIndex = 4
ExplicitLeft = 0
ExplicitTop = 0
ExplicitWidth = 0
ExplicitHeight = 0
DesignSize = (
405
421)
@ -244,6 +250,10 @@ object icqFr: TicqFr
object AddTrafTB: TTabSheet
Caption = 'Add traffic'
ImageIndex = 1
ExplicitLeft = 0
ExplicitTop = 0
ExplicitWidth = 0
ExplicitHeight = 0
DesignSize = (
405
421)
@ -414,6 +424,8 @@ object icqFr: TicqFr
Width = 121
Height = 25
Caption = 'Select contacts'
DoubleBuffered = True
ParentDoubleBuffered = False
TabOrder = 2
OnClick = SBSelInvisClClick
end
@ -488,6 +500,8 @@ object icqFr: TicqFr
Width = 91
Height = 23
Caption = 'Add defined'
DoubleBuffered = True
ParentDoubleBuffered = False
TabOrder = 10
OnClick = AddCapsBtnClick
ImageName = 'add'
@ -522,6 +536,10 @@ object icqFr: TicqFr
object AvatarsTS: TTabSheet
Caption = 'Avatars'
ImageIndex = 2
ExplicitLeft = 0
ExplicitTop = 0
ExplicitWidth = 0
ExplicitHeight = 0
object AvatarGrp: TGroupBox
Left = 6
Top = 17
@ -588,6 +606,10 @@ object icqFr: TicqFr
Caption = 'File transfer'
ImageIndex = 3
TabVisible = False
ExplicitLeft = 0
ExplicitTop = 0
ExplicitWidth = 0
ExplicitHeight = 0
object FTPortsEdit: TLabeledEdit
Left = 64
Top = 16


+ 1
- 1
RnQ/ICQ/icq_fr.pas View File

@ -401,7 +401,7 @@ begin
begin
icq.sendPrivacy(PrivacyGrp.itemindex, webawareChk.Checked, authNeededChk.Checked);
// Reload UIN info to refresh this ICQ settings page
icq.sendAdvQueryInfo(Account.AccProto.MyAccNum);
icq.sendAdvQueryInfo(Account.AccProto.MyAccNum, '');
end;
if needSaveChkList then
saveListsDelayed := True;


+ 2
- 2
RnQ/ICQ/viewinfoDlg.dfm View File

@ -344,8 +344,8 @@ object viewinfoFrm: TviewinfoFrm
Top = 166
Width = 82
Height = 22
Date = 39050.677962962960000000
Time = 39050.677962962960000000
Date = 714.677962962960000000
Time = 714.677962962960000000
TabOrder = 14
OnChange = birthBoxChange
end


+ 13
- 13
RnQ/ICQ/viewinfoDlg.pas View File

@ -371,11 +371,11 @@ begin
begin
caption := getTranslation('%s', [displayed]);
if nodb then
caption := caption + getTranslation(' -user not found on server')
caption := caption + ' ' + getTranslation('- user not found on server')
else if infoUpdatedTo = 0 then
caption := caption + getTranslation(' -no info')
caption := caption + ' ' + getTranslation('- no info')
else if not isUpToDate then
caption := caption + getTranslation(' -newer info available on server');
caption := caption + ' ' + getTranslation('- newer info available on server');
displayBox.text := displayed;
firstBox.text := first;
lastBox.text := last;
@ -726,8 +726,8 @@ end;
// updateInfo
procedure TviewinfoFrm.updateBtnClick(Sender: TObject);
// var
// wpS : TwpSearch;
var
wpS : TwpSearch;
begin
if OnlFeature(contact.fProto) then
begin
@ -735,13 +735,13 @@ begin
// TICQSession(contact.fProto).sendFullQueryInfo(contact.UID2cmp);
// All data in one packet
TICQSession(contact.fProto).sendAdvQueryInfo(contact.uid2Cmp);
{
wpS.uin := contact.UID2cmp;
// TICQSession(contact.iProto.ProtoElem).sendQueryInfo(StrToIntDef(wpS.uin, 0));
wpS.token := TICQcontact(contact).InfoToken;
TICQSession(contact.fProto).sendWPsearch2(wpS, 0, False);
}
TICQSession(contact.fProto).sendAdvQueryInfo(contact.uid2Cmp, TICQcontact(contact).InfoToken);
{
wpS.uin := contact.UID2cmp;
//TICQSession(contact.iProto.ProtoElem).sendQueryInfo(StrToIntDef(wpS.uin, 0));
wpS.token := TICQcontact(contact).InfoToken;
TICQSession(contact.fProto).sendWPsearch2(wpS, 0, False);
}
end
end;
@ -1266,7 +1266,7 @@ var
i: integer;
begin
i := birthageBox.ItemIndex;
birthBox.enabled := i = 1;
birthBox.visible := i = 1;
updateAge;
// birthageLbl.Visible := i = 0;
end;


+ 53
- 1
RnQ/Protocols_all.pas View File

@ -11,7 +11,7 @@ uses
Classes, Forms,
RnQProtocol, langLib,
Protocol_icq, ICQcontacts,
automsgDlg, globalLib,
automsgDlg, globalLib, roasterlib,
RnQPrefsLib, RnQPics,
RDGlobal, outboxLib;
@ -28,6 +28,7 @@ procedure Protos_auth(cnt: TRnQContact);
procedure Protos_AuthDenied(cnt: TRnQContact; const msg: string = '');
procedure Protos_DelCntFromSrv(cnt: TRnQContact);
function addToRoster(c: TRnQcontact; isLocal: Boolean = False): boolean; overload;
function status2imgName(s: byte; inv: Boolean = false): TPicName; inline;
function status2imgNameExt(s: byte; inv: Boolean = false; extSts: byte = 0): TPicName; inline;
@ -49,6 +50,27 @@ function Proto_Outbox_add(kind: Integer; dest: TRnQContact; flags: Integer = 0;
function Proto_Outbox_add(kind: Integer; dest: TRnQContact; flags: Integer; cl: TRnQCList): Toevent; overload;
procedure getTrayIconTip(var vPic: TPicName; var vTip: String);
var
AntiSpamMsgs: array [0 .. 6] of String = (
// (
('Your message has been blocked for antispam reason.'),
('You entered invalid code. Try again.'),
('Confirmation accepted. Your message recieved. Thank you.'),
('You failed antispam verification. You have no attemts. Your UIN (%uin%) is ignored.'),
('Please, type digital CODE which you can see below (3 digits).'),
('You have attempts: %attempt%.'), // %code%
('Please, type answer on question which you can see below.')
{ )
(
('Âàøå ñîîáùåíèå çàáëîêèðîâàíî àíòèñïàì ïëàãèíîì.'),
('Âû ââåëè íå ïðàâèëüíûé êîä. Ïîïðîáóéòå åùå ðàç.'),
('Êîä ïðèíÿò. Âàøå ñîîáùåíèå ïîëó÷åíî. Ñïàñèáî.'),
('Âû íå ïðîøëè àíòèñïàì ïðîâåðêó. Ó âàñ íå îñòàëîñü ïîïûòîê. Âàø UIN (%uin%) èãíîðèðóåòñÿ.'),
('Ïîæàëóéñòà, ââåäèòå öèôðîâîé ÊÎÄ êîòîðûé âû âèäèòå íèæå (3 öèôðû). '),
('Îñòàëîñü ïîïûòîê: %attempt%.'#13#10'%code%')
) }
);
implementation
uses
@ -293,6 +315,36 @@ begin
{$ENDIF ICQ_ONLY}
end;
function addToRoster(c: TRnQContact; isLocal: Boolean = False): boolean;
begin
notInList.remove(c);
// c.CntIsLocal := isLocal;
if isLocal then
c.SSIID := 0;
result:= c.fProto.addContact(c, isLocal);
if not result then exit;
roasterlib.update(c);
roasterLib.focus(c);
saveListsDelayed:=TRUE;
autosizeDelayed:=TRUE;
plugins.castEvList( PE_LIST_ADD, PL_ROSTER, c);
{$IFDEF UseNotSSI}
if c is TICQcontact then
// if (not icq.useSSI)and icq.useLSI3 then
with TicqSession(c.iProto.ProtoElem) do
if not UseSSI and useLSI2 then
begin
if StrToIntDef(c.uid, 0) > 0 then
begin
if TICQcontact(c).infoUpdatedTo=0 then
sendQueryInfo(StrToIntDef(c.UID2cmp, 0));
if sendTheAddedYou then
Account.outbox.add(OE_addedYou, c);
end;
end;
{$ENDIF UseNotSSI}
end; // addToRoster
function status2imgName( // pr : TRnQProtocol;
s: byte; inv: Boolean = false): TPicName;
begin


+ 2
- 2
RnQ/RnQBuiltTime.inc View File

@ -1,2 +1,2 @@
{ 01.10.2015 18:50:10 }
BuiltTime = 42278.7848394329;
{ 23.10.2015 13:49:55 }
BuiltTime = 42300.5763349306;

+ 49
- 22
RnQ/RnQProtocol.pas View File

@ -598,11 +598,13 @@ type
function imVisibleTo : Boolean;
function isInRoster : Boolean;
function isInList(l : TLIST_TYPES) : Boolean;
procedure SetGroupName(const pName : String);
// public
// function GetProto : IRnQProtocol;
function buin: RawByteString;
property Display : string read fDisplay write SetDisplay;
property ProtoID : byte read _getProtoID;
property Status : byte read getStatus;
end;
TcontactProc=procedure(c:TRnQContact);
@ -682,6 +684,8 @@ const
IF_urgent = 1 shl 2; // send msg urgent
IF_noblink = 1 shl 3; // send to contact list
IF_no_matter = 1 shl 10; // If set, don't play sound
const // Avatar type
IS_AVATAR = 0;
IS_PHOTO = 1;
@ -1006,16 +1010,16 @@ begin
// end;
end;
function TRnQcontact.equals(const pUID: TUID):boolean;
function TRnQcontact.equals(const pUID: TUID): boolean;
var
// i, j : Byte;
vUID : TUID;
// i, j: Byte;
vUID: TUID;
begin
try
vUID := LowerCase(trimUID(pUID));
if (not assigned(self)) or (self.UID2cmp='') or (vUID='') then
result := false
else
vUID := LowerCase(trimUID(pUID));
if (not assigned(self)) or (self.UID2cmp = '') or (vUID = '') then
Result := False
else
{ begin
i := 1; j := 1;
repeat
@ -1034,9 +1038,9 @@ begin
result := false;
end;}
//
result:=(UID2cmp = vUID)
Result := (UID2cmp = vUID)
except
result := False;
Result := False;
end;
end;
@ -1115,6 +1119,27 @@ begin
end;
end;
procedure TRnQcontact.SetGroupName(const pName : String);
var
gId : Integer;
begin
gID := groups.name2id(pName);
if gID >= 0 then
begin
self.group := gID
end
else
begin
if pName > '' then
begin
gID := groups.add();
groups.rename(gID, pName);
end
else
gId := 2000;
end;
self.group := gID;
end;
/////////////// TRnQCList ///////////////////////////////////////////////
@ -1431,34 +1456,36 @@ begin
end;
end; // fromString
function TRnQCList.clone:TRnQCList;
function TRnQCList.clone: TRnQCList;
var
i:integer;
i: integer;
begin
result := TRnQCList.create;
for i:=0 to count-1 do
result.add(getAt(i))
result := TRnQCList.create;
for i := 0 to count - 1 do
result.add(getAt(i))
end; // clone
procedure TRnQCList.resetEnumeration;
begin enumIdx:=0 end;
begin
enumIdx := 0
end;
function TRnQCList.hasMore:boolean;
begin
result:=enumIdx<count
result := enumIdx < count
end;
function TRnQCList.getNext:TRnQContact;
function TRnQCList.getNext: TRnQContact;
begin
result:=getAt(enumIdx);
inc(enumIdx);
result := getAt(enumIdx);
inc(enumIdx);
end; // getNext
procedure TRnQCList.assign(cl:TRnQCList);
procedure TRnQCList.assign(cl: TRnQCList);
begin
if cl=NIL then
if cl = nil then
clear
else
else
inherited assign(cl, laCopy)
end;


+ 28
- 20
RnQ/RnQTips.pas View File

@ -42,21 +42,29 @@ procedure TipsDraw(Sender: TtipFrm; mode: Tmodes; info: Pointer; pMaxX, pMaxY: I
var
hb: HBRUSH;
begin
case mode of
TM_EVENT:
tipDrawEvent(Sender.Canvas.Handle, Thevent(info), NIL, pMaxX, pMaxY, calcOnly);
TM_PIC:
Sender.Canvas.Draw(0, 0, TBitmap(info));
TM_PIC_EX:
if Assigned(TRnQBitmap(info)) then
if Assigned(TRnQBitmap(info).fBmp) then
begin
hb := CreateSolidBrush(ColorToRGB(theme.GetColor('tip.bg', clInfoBk)));
FillRect(Sender.Canvas.Handle, Sender.Canvas.ClipRect, hb);
DrawRbmp(Sender.Canvas.Handle, TRnQBitmap(info));
end;
TM_BDay:
tipDrawEvent(Sender.Canvas.Handle, NIL, TRnQContact(info), pMaxX, pMaxY, calcOnly);
if not Sender.HandleAllocated then
Exit;
Sender.Canvas.Lock;
try
case mode of
TM_EVENT:
tipDrawEvent(Sender.Canvas.Handle, Thevent(info), nil, pMaxX, pMaxY, calcOnly);
TM_PIC:
Sender.Canvas.Draw(0, 0, TBitmap(info));
TM_PIC_EX:
if Assigned(TRnQBitmap(info)) then
if Assigned(TRnQBitmap(info).fBmp) then
begin
hb := CreateSolidBrush(ColorToRGB(theme.GetColor('tip.bg', clInfoBk)));
FillRect(Sender.Canvas.Handle, Sender.Canvas.ClipRect, hb);
DrawRbmp(Sender.Canvas.Handle, TRnQBitmap(info));
end;
TM_BDay:
tipDrawEvent(Sender.Canvas.Handle, NIL, TRnQContact(info), pMaxX, pMaxY, calcOnly);
end;
finally
Sender.Canvas.Unlock;
end;
end;
@ -274,7 +282,7 @@ begin
if AddTip(item, ti, needW, needH) then
begin
item.form.onPaintTip := TipsDraw;
item.form.OnPaintTip := TipsDraw;
item.form.OnTipDestroy := TipsDestroy;
item.form.AlphaBlend := True;
item.form.AlphaBlendValue := 0;
@ -500,8 +508,8 @@ begin
maxY := 0;
end;
if (pCnt = NIL) and ((ev = nil) or (ev.who = NIL)) then
exit;
if (pCnt = nil) and ((ev = nil) or (ev.who = nil)) then
Exit;
fullR.Left := 0;
fullR.Top := 0;
@ -524,7 +532,7 @@ begin
if (ABitmap = 0) and (Right - Left + Bottom - Top <> 0) then
raise EOutOfResources.create('Out of Resources');
HOldBmp := SelectObject(dc, ABitmap);
SetWindowOrgEx(dc, Left, Top, Nil);
SetWindowOrgEx(dc, Left, Top, nil);
end;
finally
end;
@ -532,7 +540,7 @@ begin
// DC := 0;
try
thisCnt := NIL;
thisCnt := nil;
if Assigned(ev) and Assigned(ev.who) then
thisCnt := ev.who
else if Assigned(pCnt) then


+ 2
- 2
RnQ/RnQ_Avatars.pas View File

@ -42,7 +42,7 @@ procedure avatars_save_and_load(cnt: TRnQContact; const hash: RawByteString; var
procedure loadAvatars(const proto: TRnQProtocol; path: String);
procedure updateAvatarFor(c: TRnQContact);
procedure Check_my_avatar(const proto: TRnQProtocol);
procedure ClearAvatar(var cnt: TICQContact);
procedure ClearAvatar(var cnt: TRnQContact);
function try_load_avatar(c: TICQContact; const hash: RawByteString): Boolean;
// function try_load_avatar2(bmp:TBitmap; hash : String) :Boolean ;
// function try_load_avatar3(var bmp:TRnQBitmap; const hash : AnsiString) :Boolean;
@ -1025,7 +1025,7 @@ begin
roasterLib.redraw(c);
end;
procedure ClearAvatar(var cnt: TICQContact);
procedure ClearAvatar(var cnt: TRnQContact);
var
frm: TRnQViewInfoForm;
ci: TchatInfo;


+ 4
- 0
RnQ/RnQdbDlg.dfm View File

@ -65,6 +65,8 @@ object RnQdbFrm: TRnQdbFrm
Width = 99
Height = 25
Caption = '&Purge'
DoubleBuffered = True
ParentDoubleBuffered = False
TabOrder = 2
OnClick = purgeBtnClick
end
@ -74,6 +76,8 @@ object RnQdbFrm: TRnQdbFrm
Width = 100
Height = 25
Caption = 'View report'
DoubleBuffered = True
ParentDoubleBuffered = False
TabOrder = 3
Visible = False
OnClick = reportBtnClick


+ 1
- 1
RnQ/RnQdbDlg.pas View File

@ -69,7 +69,7 @@ uses
RnQLangs, RnQStrings, RDUtils,
RnQSysUtils, RnQPics,
RQUtil, RDGlobal, RQThemes, RnQMenu, menusUnit,
RnQProtocol,
RnQProtocol, Protocols_all,
globalLib, chatDlg, utilLib, themesLib,
icqv9, ICQcontacts,
Protocol_ICQ, icqConsts;


+ 24
- 24
RnQ/RnQx64.dproj View File

@ -156,10 +156,10 @@ $(PreBuildEvent)]]></PreBuildEvent>
<DCC_GenerateStackFrames>true</DCC_GenerateStackFrames>
</PropertyGroup>
<PropertyGroup Condition="'$(Cfg_2_Win32)'!=''">
<DCC_Optimize>true</DCC_Optimize>
<BCC_SourceDebuggingOn>true</BCC_SourceDebuggingOn>
<ILINK_FullDebugInfo>true</ILINK_FullDebugInfo>
<BCC_DebugLineNumbers>true</BCC_DebugLineNumbers>
<DCC_Optimize>true</DCC_Optimize>
<DCC_DebugInfoInExe>true</DCC_DebugInfoInExe>
<DCC_IMPLICIT_STRING_CAST>false</DCC_IMPLICIT_STRING_CAST>
<DCC_UsePackage>EurekaLogCore;$(DCC_UsePackage)</DCC_UsePackage>
@ -479,18 +479,18 @@ $(PreBuildEvent)]]></PreBuildEvent>
<Overwrite>true</Overwrite>
</Platform>
</DeployFile>
<DeployFile LocalName="..\Distro\RnQx64.exe" Configuration="Release" Class="ProjectOutput">
<Platform Name="Win64">
<RemoteName>RnQx64.exe</RemoteName>
<Overwrite>true</Overwrite>
</Platform>
</DeployFile>
<DeployFile LocalName="RnQx64.todo" Configuration="Release" Class="ProjectFile">
<Platform Name="Win32">
<RemoteDir>.\</RemoteDir>
<Overwrite>true</Overwrite>
</Platform>
</DeployFile>
<DeployFile LocalName="..\Distro\RnQx64.exe" Configuration="Release" Class="ProjectOutput">
<Platform Name="Win64">
<RemoteName>RnQx64.exe</RemoteName>
<Overwrite>true</Overwrite>
</Platform>
</DeployFile>
<DeployFile LocalName="..\for.RnQ\ForRnQConfig.inc" Configuration="Release" Class="ProjectFile">
<Platform Name="Win32">
<RemoteDir>.\</RemoteDir>
@ -503,27 +503,12 @@ $(PreBuildEvent)]]></PreBuildEvent>
<Overwrite>true</Overwrite>
</Platform>
</DeployFile>
<DeployClass Name="DependencyModule">
<Platform Name="Win32">
<Operation>0</Operation>
<Extensions>.dll;.bpl</Extensions>
</Platform>
<DeployClass Name="ProjectiOSDeviceResourceRules">
<Platform Name="iOSDevice64">
<Operation>1</Operation>
<Extensions>.dylib</Extensions>
</Platform>
<Platform Name="OSX32">
<RemoteDir>Contents\MacOS</RemoteDir>
<Operation>1</Operation>
<Extensions>.dylib</Extensions>
</Platform>
<Platform Name="iOSDevice32">
<Operation>1</Operation>
<Extensions>.dylib</Extensions>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
<Extensions>.dylib</Extensions>
</Platform>
</DeployClass>
<DeployClass Name="ProjectOSXResource">
@ -887,12 +872,27 @@ $(PreBuildEvent)]]></PreBuildEvent>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectiOSDeviceResourceRules">
<DeployClass Name="DependencyModule">
<Platform Name="Win32">
<Operation>0</Operation>
<Extensions>.dll;.bpl</Extensions>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
<Extensions>.dylib</Extensions>
</Platform>
<Platform Name="OSX32">
<RemoteDir>Contents\MacOS</RemoteDir>
<Operation>1</Operation>
<Extensions>.dylib</Extensions>
</Platform>
<Platform Name="iOSDevice32">
<Operation>1</Operation>
<Extensions>.dylib</Extensions>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
<Extensions>.dylib</Extensions>
</Platform>
</DeployClass>
<ProjectRoot Platform="iOSDevice64" Name="$(PROJECTNAME).app"/>


+ 1
- 1
RnQ/ThemesLib.pas View File

@ -41,7 +41,7 @@ uses
{$IFNDEF RNQ_LITE}
themedit_fr,
{$ENDIF}
RnQProtocol,
RnQProtocol, Protocols_all,
{$IFDEF PROTOCOL_ICQ}
Protocol_ICQ, ICQClients, icqConsts,
{$ENDIF PROTOCOL_ICQ}


+ 426
- 0
RnQ/ViewPicDimmedDlg.pas View File

@ -0,0 +1,426 @@
{
This file is part of R&Q.
Under same license
}
unit ViewPicDimmedDlg;
{$I RnQConfig.inc}
{$I NoRTTI.inc}
interface
uses
Windows, SysUtils, Graphics, Classes, ExtCtrls, Themes,
Forms, StdCtrls, Controls, Menus, Generics.Collections,
ComCtrls, Messages, RnQGraphics32, AnsiClasses, Vcl.Imaging.GIFImg;
const
WM_FADEOUT = WM_USER + 1;
type
TOnTimerProc = reference to procedure;
TOneShotTimer = class
ID: UINT_PTR;
Proc: TOnTimerProc;
end;
TFormEx = class(TForm)
private
AnimTimer: TTimer;
AlphaValue: Integer;
Dimmed: Boolean;
LastImage: Integer;
ShownImage: Integer;
procedure onAnimTimer(Sender: TObject);
procedure OnCloseImg(Sender: TObject; var Action: TCloseAction);
procedure OnKeyDownImg(Sender: TObject; var Key: Word; Shift: TShiftState);
procedure OnMouseDownImg(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
procedure UpdateShownImage();
procedure ShowHideImages();
procedure UpdateFormSize();
procedure FadeOutMsg(var Msg: TMessage); message WM_FADEOUT;
procedure WMAppCommand(var msg: TMessage); message WM_APPCOMMAND;
public
otherForm: HWND;
procedure FadeOut;
procedure ShowWithFade();
procedure startTimer();
procedure stopTimer();
//procedure updateWindow();
procedure CreateParams(var Params: TCreateParams); override;
constructor CreateNew(AOwner: TComponent; DimmedParam: Boolean = False);
end;
function viewImageDimmed(evimage: RawByteString; evoffset: Integer): Tform;
procedure SetTimeout(AProc: TOnTimerProc; ATimeout: Cardinal);
implementation
uses
globalLib, utilLib, Base64, chatDlg, cgJpeg;
var
TimerList: TDictionary<UINT_PTR, TOnTimerProc>;
procedure TFormEx.onAnimTimer(Sender: TObject);
begin
if AnimTimer.Tag = 1 then
begin
if (AlphaValue > 0) and Assigned(self) and self.HandleAllocated then
try
if not Dimmed or (Dimmed and (AlphaValue <= 200)) then
SetLayeredWindowAttributes(handle, 0, AlphaValue, LWA_ALPHA);
Dec(AlphaValue, 33);
except
stopTimer()
end
else
stopTimer();
end
else
begin
if (((AlphaValue <= 255) and not Dimmed) or ((AlphaValue <= 200) and Dimmed)) and Assigned(self) and self.HandleAllocated then
try
SetLayeredWindowAttributes(handle, 0, AlphaValue, LWA_ALPHA);
Inc(AlphaValue, 25);
except
stopTimer()
end
else
stopTimer();
end;
end;
procedure TimerProc(hwnd: HWND; uMsg: UINT; idEvent: UINT_PTR; dwTime: DWORD); stdcall;
var
Proc: TOnTimerProc;
begin
if TimerList.TryGetValue(idEvent, Proc) then
try
KillTimer(0, idEvent);
Proc();
finally
TimerList.Remove(idEvent);
end;
end;
procedure SetTimeout(AProc: TOnTimerProc; ATimeout: Cardinal);
begin
TimerList.Add(SetTimer(0, 0, ATimeout, @TimerProc), AProc);
end;
procedure TFormEx.ShowWithFade();
begin
try
Show;
Invalidate;
if Dimmed then
startTimer()
else
SetTimeout(procedure begin startTimer(); end, 100);
except
end;
end;
procedure TFormEx.startTimer();
begin
if (Assigned(AnimTimer)) then
AnimTimer.Enabled := true;
end;
procedure TFormEx.stopTimer();
begin
if (Assigned(AnimTimer)) then
AnimTimer.Enabled := false;
if AnimTimer.Tag = 1 then
Close
else
AlphaValue := 255;
end;
{
procedure TFormEx.updateWindow();
var
Bitmap: TBitmap;
BitmapPos: TPoint;
BitmapSize: TSIZE;
BlendFunction: _BLENDFUNCTION;
begin
Bitmap := TBitmap.Create;
Bitmap.PixelFormat := pf32bit;
Bitmap.SetSize(1920, 1080);
Bitmap.Canvas.Brush.Color := clRed;
Bitmap.Canvas.FillRect(Rect(0, 0, Bitmap.Width, Bitmap.Height));
BitmapPos := Point(0, 0);
BitmapSize.cx := 1920;
BitmapSize.cy := 1080;
BlendFunction.BlendOp := AC_SRC_OVER;
BlendFunction.BlendFlags := 0;
BlendFunction.SourceConstantAlpha := 127;
BlendFunction.AlphaFormat := AC_SRC_ALPHA;
UpdateLayeredWindow(Handle, 0, nil, @BitmapSize, Bitmap.Canvas.Handle, @BitmapPos, 0, @BlendFunction, ULW_ALPHA);
Bitmap.Free;
end;
}
procedure TFormEx.CreateParams(var Params: TCreateParams);
begin
inherited;
Params.ExStyle := Params.ExStyle or WS_EX_NOACTIVATE;
end;
constructor TFormEx.CreateNew(AOwner: TComponent; DimmedParam: Boolean = False);
begin
inherited CreateNew(AOwner);
Dimmed := DimmedParam;
if StyleServices.Enabled and Assigned(self) then
begin
SetWindowLong(handle, GWL_EXSTYLE, GetWindowLong(handle, GWL_EXSTYLE) or WS_EX_LAYERED);
SetLayeredWindowAttributes(Handle, 0, 0, LWA_ALPHA);
end;
DoubleBuffered := True;
BorderStyle := bsNone;
KeyPreview := True;
OnClose := OnCloseImg;
OnKeyDown := OnKeyDownImg;
OnMouseDown := OnMouseDownImg;
if not Dimmed then
begin
FormStyle := fsStayOnTop;
SetWindowPos(Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE or SWP_NOMOVE or SWP_NOACTIVATE);
end;
alphaValue := 0;
animTimer := TTimer.Create(AOwner);
animTimer.Enabled := false;
animTimer.OnTimer := onAnimTimer;
animTimer.Interval := 10;
animTimer.Tag := 0;
end;
procedure TFormEx.FadeOut();
begin
animTimer.Tag := 1;
animTimer.Interval := 10;
animTimer.Enabled := true;
end;
procedure TFormEx.FadeOutMsg(var Msg: TMessage);
begin
FadeOut;
end;
procedure TFormEx.WMAppCommand(var msg: TMessage);
begin
if Dimmed then
PostMessage(otherForm, WM_APPCOMMAND, msg.WParam, msg.LParam)
else
case GET_APPCOMMAND_LPARAM(msg.LParam) of
APPCOMMAND_BROWSER_BACKWARD:
begin
dec(ShownImage);
if ShownImage < 0 then ShownImage := LastImage;
UpdateShownImage;
msg.Result := 1;
end;
APPCOMMAND_BROWSER_FORWARD:
begin
inc(ShownImage);