// ---------------------------------------------------------------------------80
// ICQ plugin for Miranda Instant Messenger
// ________________________________________
//
// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
// Copyright © 2001,2002 Jon Keating, Richard Hughes
// Copyright © 2002,2003,2004 Martin Öberg, Sam Kothari, Robert Rainwater
// Copyright © 2004,2005,2006,2007 Joe Kucera
// Copyright © 2006,2007 [sss], chaos.persei, [sin], Faith Healer, Theif, nullbie
//
// 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.
//
// -----------------------------------------------------------------------------
//
// File name : $Source$
// Revision : $Revision: 64 $
// Last change on : $Date: 2007-10-16 17:39:11 +0300 (Вт, 16 окт 2007) $
// Last change by : $Author: chaos.persei $
//
// DESCRIPTION:
//
// Support for Custom Statuses
//
// -----------------------------------------------------------------------------
#include "icqoscar.h"
#include "m_cluiframes.h"
extern void setUserInfo();
extern BOOL bXstatusIconShow;
extern HANDLE hxstatusiconchanged;
extern HANDLE hxstatuschanged;
int bHideXStatusUI = 0;
static int bStatusMenu = 0;
static HANDLE hHookExtraIconsRebuild = NULL;
static HANDLE hHookStatusBuild = NULL;
static HANDLE hHookExtraIconsApply = NULL;
static HANDLE hXStatusIcons[37];
static HANDLE hXStatusItems[38];
static HANDLE hXStatusIconsHandle[37];
static int hXStatusCListIcons[37]; //
static BOOL bXStatusCListIconsValid[37]; //need to be changed dinamicly
void CListShowMenuItem(HANDLE hMenuItem, BYTE bShow);
DWORD dwLastXUpdateTime;
BYTE fXstatusIcons()
{
if(ICQGetContactSettingByte(NULL, "NonStandartXstatus", 1))
return 37;
else
return 32;
}
BYTE fXstatusItems()
{
if(ICQGetContactSettingByte(NULL, "NonStandartXstatus", 1))
return 38;
else
return 33;
}
#define XstatusIcons fXstatusIcons()
#define XstatusItems fXstatusItems()
BYTE __stdcall ICQGetContactXStatus(HANDLE hContact)
{
BYTE bXStatus = ICQGetContactSettingByte(hContact, DBSETTING_XSTATUSID, 0);
if (!gbXStatusEnabled || bXStatus < 1 || bXStatus > XstatusIcons) return 0;
return bXStatus;
}
DWORD sendXStatusDetailsRequest(HANDLE hContact, int bForced)
{
if (invis_for(0,hContact))
{
return 0;
}
{
DWORD dwCookie = 0;
if (ICQGetContactSettingByte(hContact, DBSETTING_XSTATUSID, -1) != -1)
{ // only request custom status detail when the contact has one
char *szNotify;
int nNotifyLen;
nNotifyLen = 94 + UINMAXLEN;
szNotify = (char*)_alloca(nNotifyLen);
nNotifyLen = null_snprintf(szNotify, nNotifyLen, "cAwaySrvAwayStat1%d", dwLocalUIN);
dwCookie = SendXtrazNotifyRequest(hContact, "srvMng
", szNotify, bForced);
}
return dwCookie;
}
}
static DWORD requestXStatusDetails(HANDLE hContact, BOOL bAllowDelay)
{
rate_record rr = {0};
if (!validateStatusMessageRequest(hContact, MTYPE_SCRIPT_NOTIFY))
return 0; // apply privacy rules
// delay is disabled only if fired from dialog
if (!CheckContactCapabilities(hContact, CAPF_XTRAZ) && bAllowDelay)
return 0; // Contact does not support xtraz, do not request details
rr.hContact = hContact;
rr.bType = RIT_XSTATUS_REQUEST;
rr.nRequestType = 0x101; // request
rr.nMinDelay = 1000; // delay at least 1s
EnterCriticalSection(&ratesMutex);
rr.wGroup = ratesGroupFromSNAC(gRates, ICQ_MSG_FAMILY, ICQ_MSG_SRV_SEND);
LeaveCriticalSection(&ratesMutex);
if (!handleRateItem(&rr, bAllowDelay))
return sendXStatusDetailsRequest(hContact, !bAllowDelay);
return -1; // delayed
}
void UpdateXStatuses()
{
HANDLE hContact;
extern BOOL bXUpdaterPopUp;
if(!icqOnline)
return;
if(!gbXStatusEnabled)
return;
hContact = ICQFindFirstContact();
if(hContact){
do{
if (ICQGetContactStatus(hContact) != ID_STATUS_OFFLINE && (CheckContactCapabilities(hContact, CAPF_XTRAZ) && !invis_for(ICQGetContactSettingDword(hContact, "UIN",0),hContact) && ICQGetContactSettingByte(hContact, DBSETTING_XSTATUSID, 0) != 0))
requestXStatusDetails(hContact, 1);
}while(hContact = ICQFindNextContact(hContact));
}
if(bXUpdaterPopUp)
{
static char title[32];
strcpy(title, gpszICQProtoName);
strcat(title, " XStatus Updater");
ShowPopUpMsg(0,0,title, "Requests sent to all contacts", LOG_NOTE);
}
}
DWORD __stdcall icq_XStatusUpdaterThread(LPVOID lp)
{
dwLastXUpdateTime = 0;
while(1){
Sleep(60000);
if(time(NULL) - dwLastXUpdateTime < DBGetContactSettingDword(0, gpszICQProtoName, "XStatusUpdatePeriod", 5) * 60)
continue;
if(!DBGetContactSettingByte(NULL, gpszICQProtoName, "UpdateXStatus", 1))
continue;
UpdateXStatuses();
dwLastXUpdateTime = time(NULL);
}
return 0;
}
static HANDLE LoadXStatusIconLibrary(char* path, const char* sub)
{
char* p = strrchr(path, '\\');
HANDLE hLib;
strcpy(p, sub);
strcat(p, "\\xStatus_icons.dll");
if (hLib = LoadLibrary(path)) return hLib;
strcpy(p, sub);
strcat(p, "\\xStatus_ICQ.dll");
if (hLib = LoadLibrary(path)) return hLib;
strcpy(p, "\\");
return hLib;
}
static char* InitXStatusIconLibrary(char* buf)
{
char path[2*MAX_PATH];
HMODULE hXStatusIconsDLL;
// get miranda's exe path
GetModuleFileNameA(NULL, path, MAX_PATH);
hXStatusIconsDLL = LoadXStatusIconLibrary(path, "\\Icons");
if (!hXStatusIconsDLL) // TODO: add "Custom Folders" support
hXStatusIconsDLL = LoadXStatusIconLibrary(path, "\\Plugins");
if (hXStatusIconsDLL)
strcpy(buf, path);
/* {
strcpy(buf, path);
if (LoadStringA(hXStatusIconsDLL, IDS_IDENTIFY, path, sizeof(path)) == 0 || strcmpnull(path, "# Custom Status Icons #"))
{ // library is invalid
*buf = '\0';
}
FreeLibrary(hXStatusIconsDLL);
}
else
*buf = '\0';
*/
return buf;
}
HICON GetXStatusIcon(int bStatus, UINT flags)
{
char szTemp[64];
HICON icon;
null_snprintf(szTemp, sizeof(szTemp), "xstatus%d", bStatus - 1);
icon = IconLibGetIcon(szTemp);
if (flags & LR_SHARED)
return icon;
else
return CopyIcon(icon);
}
static void setContactExtraIcon(HANDLE hContact, HANDLE hIcon)
{
WORD icon_pos = ICQGetContactSettingWord(NULL, "xstatus_icon_pos", 9);
if(icon_pos<=0||icon_pos>9)
{
icon_pos=9;
}
if (bXstatusIconShow)
{
IconExtraColumn iec;
iec.cbSize = sizeof(iec);
iec.hImage = hIcon;
iec.ColumnType = icon_pos;
CallService(MS_CLIST_EXTRA_SET_ICON, (WPARAM)hContact, (LPARAM)&iec);
NotifyEventHooks(hxstatusiconchanged, (WPARAM)hContact, (LPARAM)hIcon);
}
}
static int CListMW_ExtraIconsRebuild(WPARAM wParam, LPARAM lParam)
{
BYTE i;
if (gbXStatusEnabled && ServiceExists(MS_CLIST_EXTRA_ADD_ICON))
{
for (i = 0; i < XstatusIcons; i++)
{
hXStatusIcons[i] = (HANDLE)CallService(MS_CLIST_EXTRA_ADD_ICON, (WPARAM)GetXStatusIcon(i + 1, LR_SHARED), 0);
}
}
return 0;
}
static int CListMW_ExtraIconsApply(WPARAM wParam, LPARAM lParam)
{
if (gbXStatusEnabled && ServiceExists(MS_CLIST_EXTRA_SET_ICON))
{
if (IsICQContact((HANDLE)wParam))
{ // only apply icons to our contacts, do not mess others
DWORD bXStatus = ICQGetContactXStatus((HANDLE)wParam);
if (bXStatus)
{
setContactExtraIcon((HANDLE)wParam, hXStatusIcons[bXStatus-1]);
}
else
{
setContactExtraIcon((HANDLE)wParam, (HANDLE)-1);
}
}
}
return 0;
}
static int CListMW_BuildStatusItems(WPARAM wParam, LPARAM lParam)
{
InitXStatusItems(TRUE);
return 0;
}
void InitXStatusEvents()
{
if (!hHookStatusBuild)
if (bStatusMenu = ServiceExists(MS_CLIST_ADDSTATUSMENUITEM))
hHookStatusBuild = HookEvent(ME_CLIST_PREBUILDSTATUSMENU, CListMW_BuildStatusItems);
if (!hHookExtraIconsRebuild)
hHookExtraIconsRebuild = HookEvent(ME_CLIST_EXTRA_LIST_REBUILD, CListMW_ExtraIconsRebuild);
if (!hHookExtraIconsApply)
hHookExtraIconsApply = HookEvent(ME_CLIST_EXTRA_IMAGE_APPLY, CListMW_ExtraIconsApply);
}
void UninitXStatusEvents()
{
if (hHookStatusBuild)
UnhookEvent(hHookStatusBuild);
if (hHookExtraIconsRebuild)
UnhookEvent(hHookExtraIconsRebuild);
if (hHookExtraIconsApply)
UnhookEvent(hHookExtraIconsApply);
}
const capstr capXStatus[37] = {
{0x01, 0xD8, 0xD7, 0xEE, 0xAC, 0x3B, 0x49, 0x2A, 0xA5, 0x8D, 0xD3, 0xD8, 0x77, 0xE6, 0x6B, 0x92},// XStatus(Angry)
{0x5A, 0x58, 0x1E, 0xA1, 0xE5, 0x80, 0x43, 0x0C, 0xA0, 0x6F, 0x61, 0x22, 0x98, 0xB7, 0xE4, 0xC7},// XStatus(Duck)
{0x83, 0xC9, 0xB7, 0x8E, 0x77, 0xE7, 0x43, 0x78, 0xB2, 0xC5, 0xFB, 0x6C, 0xFC, 0xC3, 0x5B, 0xEC},// XStatus(Tired)
{0xE6, 0x01, 0xE4, 0x1C, 0x33, 0x73, 0x4B, 0xD1, 0xBC, 0x06, 0x81, 0x1D, 0x6C, 0x32, 0x3D, 0x81},// XStatus(Party)
{0x8C, 0x50, 0xDB, 0xAE, 0x81, 0xED, 0x47, 0x86, 0xAC, 0xCA, 0x16, 0xCC, 0x32, 0x13, 0xC7, 0xB7},// XStatus(Beer)
{0x3F, 0xB0, 0xBD, 0x36, 0xAF, 0x3B, 0x4A, 0x60, 0x9E, 0xEF, 0xCF, 0x19, 0x0F, 0x6A, 0x5A, 0x7F},// XStatus(Thinking)
{0xF8, 0xE8, 0xD7, 0xB2, 0x82, 0xC4, 0x41, 0x42, 0x90, 0xF8, 0x10, 0xC6, 0xCE, 0x0A, 0x89, 0xA6},// XStatus(Eating)
{0x80, 0x53, 0x7D, 0xE2, 0xA4, 0x67, 0x4A, 0x76, 0xB3, 0x54, 0x6D, 0xFD, 0x07, 0x5F, 0x5E, 0xC6},// XStatus(TV)
{0xF1, 0x8A, 0xB5, 0x2E, 0xDC, 0x57, 0x49, 0x1D, 0x99, 0xDC, 0x64, 0x44, 0x50, 0x24, 0x57, 0xAF},// XStatus(Friends)
{0x1B, 0x78, 0xAE, 0x31, 0xFA, 0x0B, 0x4D, 0x38, 0x93, 0xD1, 0x99, 0x7E, 0xEE, 0xAF, 0xB2, 0x18},// XStatus(Coffee)
{0x61, 0xBE, 0xE0, 0xDD, 0x8B, 0xDD, 0x47, 0x5D, 0x8D, 0xEE, 0x5F, 0x4B, 0xAA, 0xCF, 0x19, 0xA7},// XStatus(Music)
{0x48, 0x8E, 0x14, 0x89, 0x8A, 0xCA, 0x4A, 0x08, 0x82, 0xAA, 0x77, 0xCE, 0x7A, 0x16, 0x52, 0x08},// XStatus(Business)
{0x10, 0x7A, 0x9A, 0x18, 0x12, 0x32, 0x4D, 0xA4, 0xB6, 0xCD, 0x08, 0x79, 0xDB, 0x78, 0x0F, 0x09},// XStatus(Camera)
{0x6F, 0x49, 0x30, 0x98, 0x4F, 0x7C, 0x4A, 0xFF, 0xA2, 0x76, 0x34, 0xA0, 0x3B, 0xCE, 0xAE, 0xA7},// XStatus(Funny)
{0x12, 0x92, 0xE5, 0x50, 0x1B, 0x64, 0x4F, 0x66, 0xB2, 0x06, 0xB2, 0x9A, 0xF3, 0x78, 0xE4, 0x8D},// XStatus(Phone)
{0xD4, 0xA6, 0x11, 0xD0, 0x8F, 0x01, 0x4E, 0xC0, 0x92, 0x23, 0xC5, 0xB6, 0xBE, 0xC6, 0xCC, 0xF0},// XStatus(Games)
{0x60, 0x9D, 0x52, 0xF8, 0xA2, 0x9A, 0x49, 0xA6, 0xB2, 0xA0, 0x25, 0x24, 0xC5, 0xE9, 0xD2, 0x60},// XStatus(College)
{0x63, 0x62, 0x73, 0x37, 0xA0, 0x3F, 0x49, 0xFF, 0x80, 0xE5, 0xF7, 0x09, 0xCD, 0xE0, 0xA4, 0xEE},// XStatus(Shopping)
{0x1F, 0x7A, 0x40, 0x71, 0xBF, 0x3B, 0x4E, 0x60, 0xBC, 0x32, 0x4C, 0x57, 0x87, 0xB0, 0x4C, 0xF1},// XStatus(Sick)
{0x78, 0x5E, 0x8C, 0x48, 0x40, 0xD3, 0x4C, 0x65, 0x88, 0x6F, 0x04, 0xCF, 0x3F, 0x3F, 0x43, 0xDF},// XStatus(Sleeping)
{0xA6, 0xED, 0x55, 0x7E, 0x6B, 0xF7, 0x44, 0xD4, 0xA5, 0xD4, 0xD2, 0xE7, 0xD9, 0x5C, 0xE8, 0x1F},// XStatus(Surfing)
{0x12, 0xD0, 0x7E, 0x3E, 0xF8, 0x85, 0x48, 0x9E, 0x8E, 0x97, 0xA7, 0x2A, 0x65, 0x51, 0xE5, 0x8D},// XStatus(@)
{0xBA, 0x74, 0xDB, 0x3E, 0x9E, 0x24, 0x43, 0x4B, 0x87, 0xB6, 0x2F, 0x6B, 0x8D, 0xFE, 0xE5, 0x0F},// XStatus(Engineering)
{0x63, 0x4F, 0x6B, 0xD8, 0xAD, 0xD2, 0x4A, 0xA1, 0xAA, 0xB9, 0x11, 0x5B, 0xC2, 0x6D, 0x05, 0xA1},// XStatus(Typing)
//Netvigator (China)
{0x2C, 0xE0, 0xE4, 0xE5, 0x7C, 0x64, 0x43, 0x70, 0x9C, 0x3A, 0x7A, 0x1C, 0xE8, 0x78, 0xA7, 0xDC},// XStatus(China1)
{0x10, 0x11, 0x17, 0xC9, 0xA3, 0xB0, 0x40, 0xF9, 0x81, 0xAC, 0x49, 0xE1, 0x59, 0xFB, 0xD5, 0xD4},// XStatus(China2)
{0x16, 0x0C, 0x60, 0xBB, 0xDD, 0x44, 0x43, 0xF3, 0x91, 0x40, 0x05, 0x0F, 0x00, 0xE6, 0xC0, 0x09},// XStatus(China3)
{0x64, 0x43, 0xC6, 0xAF, 0x22, 0x60, 0x45, 0x17, 0xB5, 0x8C, 0xD7, 0xDF, 0x8E, 0x29, 0x03, 0x52},// XStatus(China4)
{0x16, 0xF5, 0xB7, 0x6F, 0xA9, 0xD2, 0x40, 0x35, 0x8C, 0xC5, 0xC0, 0x84, 0x70, 0x3C, 0x98, 0xFA},// XStatus(China5)
//ProSieben (De)
{0x63, 0x14, 0x36, 0xff, 0x3f, 0x8a, 0x40, 0xd0, 0xa5, 0xcb, 0x7b, 0x66, 0xe0, 0x51, 0xb3, 0x64},// XStatus(De1)
{0xb7, 0x08, 0x67, 0xf5, 0x38, 0x25, 0x43, 0x27, 0xa1, 0xff, 0xcf, 0x4c, 0xc1, 0x93, 0x97, 0x97},// XStatus(De2)
{0xdd, 0xcf, 0x0e, 0xa9, 0x71, 0x95, 0x40, 0x48, 0xa9, 0xc6, 0x41, 0x32, 0x06, 0xd6, 0xf2, 0x80},// XStatus(De3)
//Rambler (Ru) // by BeteTest
{0xD4, 0xE2, 0xB0, 0xBA, 0x33, 0x4E, 0x4F, 0xA5, 0x98, 0xD0, 0x11, 0x7D, 0xBF, 0x4D, 0x3C, 0xC8},// XStatus(Ru1)
{0xCD, 0x56, 0x43, 0xA2, 0xC9, 0x4C, 0x47, 0x24, 0xB5, 0x2C, 0xDC, 0x01, 0x24, 0xA1, 0xD0, 0xCD},// XStatus(Ru2)
{0x00, 0x72, 0xD9, 0x08, 0x4A, 0xD1, 0x43, 0xDD, 0x91, 0x99, 0x6F, 0x02, 0x69, 0x66, 0x02, 0x6F},// XStatus(Ru3)
//RnQ
{0xe6, 0x01, 0xe4, 0x1c, 0x33, 0x73, 0x4b, 0xd1, 0xbc, 0x06, 0x81, 0x1d, 0x6c, 0x32, 0x3d, 0x82},// XStatus(Smoking)
{0xd6, 0x68, 0x7f, 0x4f, 0x3d, 0xc3, 0x4b, 0xdb, 0x8a, 0x8c, 0x4c, 0x1a, 0x57, 0x27, 0x63, 0xcd}};//XStatus(Sex)
const char* nameXStatus[37] = {
LPGEN("Angry"), // 23
LPGEN("Taking a bath"), // 1
LPGEN("Tired"), // 2
LPGEN("Party"), // 3
LPGEN("Drinking beer"), // 4
LPGEN("Thinking"), // 5
LPGEN("Eating"), // 6
LPGEN("Watching TV"), // 7
LPGEN("Meeting"), // 8
LPGEN("Coffee"), // 9
LPGEN("Listening to music"),// 10
LPGEN("Business"), // 11
LPGEN("Shooting"), // 12
LPGEN("Having fun"), // 13
LPGEN("On the phone"), // 14
LPGEN("Gaming"), // 15
LPGEN("Studying"), // 16
LPGEN("Shopping"), // 0
LPGEN("Feeling sick"), // 17
LPGEN("Sleeping"), // 18
LPGEN("Surfing"), // 19
LPGEN("Browsing"), // 20
LPGEN("Working"), // 21
LPGEN("Typing"), // 22
//Netvigator (China)
LPGEN("Picnic"),
LPGEN("Cooking"),
LPGEN("Mobile"),
LPGEN("I'm high"),
LPGEN("On WC"),
//ProSieben (De)
LPGEN("To be or not to be"),
LPGEN("Watching pro7 on TV"),
LPGEN("Love"),
//Rambler (Ru)
LPGEN("Searching"),
LPGEN("Love"),
LPGEN("Journal"),
//RnQ
LPGEN("Sex"),
LPGEN("Smoking")};
const int moodXStatus[37] = {
23,
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
0,
17,
18,
19,
20,
21,
22,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1};
void handleXStatusCaps(HANDLE hContact, char* caps, int capsize, char* moods, int moodsize)
{
int bChanged = FALSE;
HANDLE hIcon = (HANDLE)-1;
if (!gbXStatusEnabled)
return;
if (caps)
{ // detect custom status capabilities
BYTE i;
for (i = 0; itype != ICQACKTYPE_XSTATUS_RESPONSE) break;
if (ack->hContact != dat->hContact) break;
if ((DWORD)ack->hProcess != dat->iEvent) break;
ShowWindow(GetDlgItem(hwndDlg, IDC_RETRXSTATUS), SW_HIDE);
ShowWindow(GetDlgItem(hwndDlg, IDC_XMSG), SW_SHOW);
ShowWindow(GetDlgItem(hwndDlg, IDC_XTITLE), SW_SHOW);
SetDlgItemTextUtf(hwndDlg,IDOK,ICQTranslateUtfStatic("Close", str, MAX_PATH));
UnhookEvent(dat->hEvent); dat->hEvent = NULL;
szText = ICQGetContactSettingUtf(dat->hContact, DBSETTING_XSTATUSNAME, "");
SetDlgItemTextUtf(hwndDlg, IDC_XTITLE, szText);
SAFE_FREE(&szText);
szText = ICQGetContactSettingUtf(dat->hContact, DBSETTING_XSTATUSMSG, "");
SetDlgItemTextUtf(hwndDlg, IDC_XMSG, szText);
SAFE_FREE(&szText);
break;
}
case WM_INITDIALOG:
{
InitXStatusData *init = (InitXStatusData*)lParam;
ICQTranslateDialog(hwndDlg);
dat = (SetXStatusData*)SAFE_MALLOC(sizeof(SetXStatusData));
SetWindowLong(hwndDlg,GWL_USERDATA,(LONG)dat);
dat->bAction = init->bAction;
if (!init->bAction)
{ // set our xStatus
dat->bXStatus = init->bXStatus;
SendDlgItemMessage(hwndDlg, IDC_XTITLE, EM_LIMITTEXT, 256, 0);
SendDlgItemMessage(hwndDlg, IDC_XMSG, EM_LIMITTEXT, 1024, 0);
OldMessageEditProc = (WNDPROC)SetWindowLongUtf(GetDlgItem(hwndDlg,IDC_XTITLE),GWL_WNDPROC,(LONG)MessageEditSubclassProc);
OldMessageEditProc = (WNDPROC)SetWindowLongUtf(GetDlgItem(hwndDlg,IDC_XMSG),GWL_WNDPROC,(LONG)MessageEditSubclassProc);
dat->okButtonFormat = GetDlgItemTextUtf(hwndDlg,IDOK);
SetDlgItemTextUtf(hwndDlg, IDC_XTITLE, init->szXStatusName);
SetDlgItemTextUtf(hwndDlg, IDC_XMSG, init->szXStatusMsg);
dat->countdown=5;
SendMessage(hwndDlg, WM_TIMER, 0, 0);
SetTimer(hwndDlg,1,1000,0);
}
else
{ // retrieve contact's xStatus
dat->hContact = init->hContact;
dat->bXStatus = ICQGetContactXStatus(dat->hContact);
dat->okButtonFormat = NULL;
SendMessage(GetDlgItem(hwndDlg, IDC_XTITLE), EM_SETREADONLY, 1, 0);
SendMessage(GetDlgItem(hwndDlg, IDC_XMSG), EM_SETREADONLY, 1, 0);
if (!ICQGetContactSettingByte(NULL, "XStatusAuto", DEFAULT_XSTATUS_AUTO))
{
SetDlgItemTextUtf(hwndDlg,IDOK,ICQTranslateUtfStatic("Cancel", str, MAX_PATH));
dat->hEvent = HookEventMessage(ME_PROTO_ACK, hwndDlg, HM_PROTOACK);
ShowWindow(GetDlgItem(hwndDlg, IDC_RETRXSTATUS), SW_SHOW);
ShowWindow(GetDlgItem(hwndDlg, IDC_XMSG), SW_HIDE);
ShowWindow(GetDlgItem(hwndDlg, IDC_XTITLE), SW_HIDE);
dat->iEvent = requestXStatusDetails(dat->hContact, FALSE);
}
else
{
char *szText;
SetDlgItemTextUtf(hwndDlg,IDOK,ICQTranslateUtfStatic("Close", str, MAX_PATH));
dat->hEvent = NULL;
szText = ICQGetContactSettingUtf(dat->hContact, DBSETTING_XSTATUSNAME, "");
SetDlgItemTextUtf(hwndDlg, IDC_XTITLE, szText);
SAFE_FREE(&szText);
szText = ICQGetContactSettingUtf(dat->hContact, DBSETTING_XSTATUSMSG, "");
SetDlgItemTextUtf(hwndDlg, IDC_XMSG, szText);
SAFE_FREE(&szText);
}
}
if (dat->bXStatus)
{
SendMessage(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM)GetXStatusIcon(dat->bXStatus, LR_SHARED));
}
{
char *format;
char buf[MAX_PATH];
format = GetWindowTextUtf(hwndDlg);
null_snprintf(str, sizeof(str), format, dat->bXStatus?ICQTranslateUtfStatic(nameXStatus[dat->bXStatus-1], buf, MAX_PATH):"");
SetWindowTextUtf(hwndDlg, str);
SAFE_FREE(&format);
}
return TRUE;
}
case WM_TIMER:
if(dat->countdown==-1)
{
DestroyWindow(hwndDlg);
break;
}
{
null_snprintf(str,sizeof(str),dat->okButtonFormat,dat->countdown);
SetDlgItemTextUtf(hwndDlg,IDOK,str);
}
dat->countdown--;
break;
case WM_COMMAND:
switch(LOWORD(wParam))
{
case IDOK:
DestroyWindow(hwndDlg);
break;
case IDC_XTITLE:
case IDC_XMSG:
if (!dat->bAction)
{ // set our xStatus
KillTimer(hwndDlg,1);
SetDlgItemTextUtf(hwndDlg,IDOK,ICQTranslateUtfStatic("OK", str, MAX_PATH));
}
break;
}
break;
case WM_DESTROY:
if (!dat->bAction)
{ // set our xStatus
char szSetting[64];
char* szValue;
char *ansi = NULL;
CLISTMENUITEM mi = {0};
ICQWriteContactSettingByte(NULL, DBSETTING_XSTATUSID, dat->bXStatus);
szValue = GetDlgItemTextUtf(hwndDlg,IDC_XMSG);
sprintf(szSetting, "XStatus%dMsg", dat->bXStatus);
ICQWriteContactSettingUtf(NULL, szSetting, szValue);
ICQWriteContactSettingUtf(NULL, DBSETTING_XSTATUSMSG, szValue);
SAFE_FREE(&szValue);
szValue = GetDlgItemTextUtf(hwndDlg,IDC_XTITLE);
sprintf(szSetting, "XStatus%dName", dat->bXStatus);
ICQWriteContactSettingUtf(NULL, szSetting, szValue);
ICQWriteContactSettingUtf(NULL, DBSETTING_XSTATUSNAME, szValue);
mi.cbSize = sizeof(mi);
utf8_decode(szValue, &ansi);
mi.pszName = ((strlen(ansi) > 0) && DBGetContactSettingByte(NULL, gpszICQProtoName, "ShowMyXText", 1)) ? ansi : ICQTranslate(nameXStatus[dat->bXStatus-1]);
mi.flags = CMIM_NAME;
CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hXStatusItems[dat->bXStatus], (LPARAM)&mi);
SAFE_FREE(&szValue);
SAFE_FREE(&ansi);
updateServerCustomStatus();
SetWindowLongUtf(GetDlgItem(hwndDlg,IDC_XMSG),GWL_WNDPROC,(LONG)OldMessageEditProc);
SetWindowLongUtf(GetDlgItem(hwndDlg,IDC_XTITLE),GWL_WNDPROC,(LONG)OldMessageEditProc);
}
if (dat->hEvent) UnhookEvent(dat->hEvent);
SAFE_FREE(&dat->okButtonFormat);
SAFE_FREE(&dat);
break;
case WM_CLOSE:
DestroyWindow(hwndDlg);
break;
}
return FALSE;
}
static void setXStatusEx(BYTE bXStatus, BYTE bQuiet)
{
CLISTMENUITEM mi = {0};
BYTE bOldXStatus = ICQGetContactSettingByte(NULL, DBSETTING_XSTATUSID, 0);
mi.cbSize = sizeof(mi);
if (bOldXStatus <= XstatusIcons)
{
mi.flags = CMIM_FLAGS;
CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hXStatusItems[bOldXStatus], (LPARAM)&mi);
}
mi.flags = CMIM_FLAGS | CMIF_CHECKED;
CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hXStatusItems[bXStatus], (LPARAM)&mi);
if (bXStatus)
{
char szSetting[64];
char str[MAX_PATH];
char *szName, *szMsg;
sprintf(szSetting, "XStatus%dName", bXStatus);
szName = ICQGetContactSettingUtf(NULL, szSetting, ICQTranslateUtfStatic(nameXStatus[bXStatus-1], str, MAX_PATH));
sprintf(szSetting, "XStatus%dMsg", bXStatus);
szMsg = ICQGetContactSettingUtf(NULL, szSetting, "");
sprintf(szSetting, "XStatus%dStat", bXStatus);
if (!bQuiet && !ICQGetContactSettingByte(NULL, szSetting, 0))
{
InitXStatusData init;
//set xstatus to null, wenn dialog box opened
setXStatusEx(0, 1);
init.bAction = 0; // set
init.bXStatus = bXStatus;
init.szXStatusName = szName;
init.szXStatusMsg = szMsg;
DialogBoxUtf(FALSE, hInst, MAKEINTRESOURCEA(IDD_SETXSTATUS),NULL,SetXStatusDlgProc,(LPARAM)&init);
}
else
{
//by [sin]
if(ICQGetContactSettingByte(NULL, "ForceXstatus", 0))
{
if(bXStatus != 0 && icqOnline){
setXStatusEx(0, 1);
SleepEx(500, TRUE);//should be 500, less makes icq sometimes not reread
}
}
ICQWriteContactSettingByte(NULL, DBSETTING_XSTATUSID, bXStatus);
ICQWriteContactSettingUtf(NULL, DBSETTING_XSTATUSNAME, szName);
ICQWriteContactSettingUtf(NULL, DBSETTING_XSTATUSMSG, szMsg);
updateServerCustomStatus();
}
SAFE_FREE(&szName);
SAFE_FREE(&szMsg);
}
else
{
ICQWriteContactSettingByte(NULL, DBSETTING_XSTATUSID, bXStatus);
ICQDeleteContactSetting(NULL, DBSETTING_XSTATUSNAME);
ICQDeleteContactSetting(NULL, DBSETTING_XSTATUSMSG);
updateServerCustomStatus();
}
}
static int menuXStatus(WPARAM wParam,LPARAM lParam,LPARAM fParam)
{
setXStatusEx((BYTE)fParam, 0);
return 0;
}
void InitXStatusItems(BOOL bAllowStatus)
{
CLISTMENUITEM mi;
BYTE i = 0;
BYTE j = 0;
char srvFce[MAX_PATH + 64];
char szItem[MAX_PATH + 64];
HANDLE hXStatusRoot;
int bXStatusMenuBuilt = 0;
BYTE bXStatus = ICQGetContactXStatus(NULL);
if (!gbXStatusEnabled) return;
if (bStatusMenu && !bAllowStatus) return;
null_snprintf(szItem, sizeof(szItem), ICQTranslate("%s Custom Status"), gpszICQProtoName);
mi.cbSize = sizeof(mi);
mi.pszPopupName = szItem;
mi.popupPosition= 500084000;
mi.position = 2000040000;
while (i < XstatusItems)
{
char szTemp[64];
char* szValue;
char* ansi = NULL;
//if(i == 34) j--;//by BeteTest
null_snprintf(srvFce, sizeof(srvFce), "%s/menuXStatus%d", gpszICQProtoName, j);
mi.position++;
if (!i)
bXStatusMenuBuilt = ServiceExists(srvFce);
if (!bXStatusMenuBuilt)
CreateServiceFunctionParam(srvFce, menuXStatus, j);
mi.flags = (j ? CMIF_ICONFROMICOLIB : 0) | (bXStatus == j?CMIF_CHECKED:0);
mi.icolibItem = j ? hXStatusIconsHandle[j-1] : NULL;
mi.pszName = j ? (char*)nameXStatus[j-1] : LPGEN("None");
sprintf(szTemp, "XStatus%dName", j);
szValue = ICQGetContactSettingUtf(NULL, szTemp, "");
utf8_decode(szValue, &ansi);
mi.pszName = (strlen(ansi) == 0 || !DBGetContactSettingByte(NULL, gpszICQProtoName, "ShowMyXText", 1)) ? ICQTranslate(j?nameXStatus[j-1]:"None") : ansi;
/*if(i==33)
{
mi.pszName = LPGEN("Other clients");
mi.pszName = ICQTranslate("Other clients");
}*/
mi.pszService = srvFce;
mi.pszContactOwner = gpszICQProtoName;
//Create menu icons
if (bStatusMenu)
hXStatusItems[j] = (HANDLE)CallService(MS_CLIST_ADDSTATUSMENUITEM, (WPARAM)&hXStatusRoot, (LPARAM)&mi);
else
hXStatusItems[j] = (HANDLE)CallService(MS_CLIST_ADDMAINMENUITEM, 0, (LPARAM)&mi);
SAFE_FREE(&szValue);
SAFE_FREE(&ansi);
i++;
j++;
}
}
void InitXStatusIcons()
{
char szSection[MAX_PATH + 64];
char str[MAX_PATH], prt[MAX_PATH];
char lib[2*MAX_PATH] = {0};
char* icon_lib;
BYTE i;
if (!gbXStatusEnabled) return;
icon_lib = InitXStatusIconLibrary(lib);
null_snprintf(szSection, sizeof(szSection), ICQTranslateUtfStatic("%s/Custom Status", str, MAX_PATH), ICQTranslateUtfStatic(gpszICQProtoName, prt, MAX_PATH));
for (i = 0; i < XstatusIcons; i++)
{
char szTemp[64];
null_snprintf(szTemp, sizeof(szTemp), "xstatus%d", i);
hXStatusIconsHandle[i] = IconLibDefine(nameXStatus[i], szSection, szTemp, 0, icon_lib, -(IDI_XSTATUS1+i));
}
// initialize arrays for CList custom status icons
memset(bXStatusCListIconsValid,0,sizeof(bXStatusCListIconsValid));
memset(hXStatusCListIcons,-1,sizeof(hXStatusCListIcons));
}
void ChangedIconsXStatus()
{
memset(bXStatusCListIconsValid,0,sizeof(bXStatusCListIconsValid));
}
int IcqShowXStatusDetails(WPARAM wParam, LPARAM lParam)
{
InitXStatusData init;
sendXStatusDetailsRequest((HANDLE)wParam, 1);
init.bAction = 1; // retrieve
init.hContact = (HANDLE)wParam;
DialogBoxUtf(FALSE, hInst, MAKEINTRESOURCEA(IDD_SETXSTATUS), NULL, SetXStatusDlgProc, (LPARAM)&init);
return 0;
}
int IcqSetXStatus(WPARAM wParam, LPARAM lParam)
{ // obsolete (TODO: remove in next version)
if (!gbXStatusEnabled) return 0;
if (wParam >= 0 && wParam <= XstatusIcons)
{
setXStatusEx((BYTE)wParam, 1);
return wParam;
}
return 0;
}
int IcqGetXStatus(WPARAM wParam, LPARAM lParam)
{ // obsolete (TODO: remove in next version)
BYTE status = ICQGetContactXStatus(NULL);
if (!gbXStatusEnabled) return 0;
if (!icqOnline) return 0;
if (status < 1 || status > XstatusIcons) status = 0;
if (wParam) *((char**)wParam) = DBSETTING_XSTATUSNAME;
if (lParam) *((char**)lParam) = DBSETTING_XSTATUSMSG;
return status;
}
int IcqSetXStatusEx(WPARAM wParam, LPARAM lParam)
{
ICQ_CUSTOM_STATUS *pData = (ICQ_CUSTOM_STATUS*)lParam;
if (!gbXStatusEnabled) return 1;
if (pData->cbSize < sizeof(ICQ_CUSTOM_STATUS)) return 1; // Failure
if (pData->flags & CSSF_MASK_STATUS)
{ // set custom status
BYTE status = *pData->status;
if (status >= 0 && status <= XstatusIcons)
{
setXStatusEx((BYTE)status, 1);
}
else
return 1; // Failure
}
if (pData->flags & (CSSF_MASK_NAME | CSSF_MASK_MESSAGE))
{
BYTE status = ICQGetContactXStatus(NULL);
if (!status) return 1; // Failure
if (pData->flags & CSSF_MASK_NAME)
{ // set custom status name
if (pData->flags & CSSF_UNICODE)
{
char* utf = make_utf8_string(pData->pwszName);
ICQWriteContactSettingUtf(NULL, DBSETTING_XSTATUSNAME, utf);
SAFE_FREE(&utf);
}
else
ICQWriteContactSettingString(NULL, DBSETTING_XSTATUSNAME, pData->pszName);
}
if (pData->flags & CSSF_MASK_MESSAGE)
{ // set custom status message
if (pData->flags & CSSF_UNICODE)
{
char* utf = make_utf8_string(pData->pwszMessage);
ICQWriteContactSettingUtf(NULL, DBSETTING_XSTATUSMSG, utf);
SAFE_FREE(&utf);
}
else
ICQWriteContactSettingString(NULL, DBSETTING_XSTATUSMSG, pData->pszMessage);
}
}
if (pData->flags & CSSF_DISABLE_UI)
{ // hide menu items
BYTE n;
bHideXStatusUI = (*pData->wParam) ? 0 : 1;
for (n = 0; n<=XstatusIcons; n++)
CListShowMenuItem(hXStatusItems[n], (BYTE)!bHideXStatusUI);
}
return 0; // Success
}
int IcqGetXStatusEx(WPARAM wParam, LPARAM lParam)
{
ICQ_CUSTOM_STATUS *pData = (ICQ_CUSTOM_STATUS*)lParam;
HANDLE hContact = (HANDLE)wParam;
if (!gbXStatusEnabled)
return 1;
if (pData->cbSize < sizeof(ICQ_CUSTOM_STATUS)) return 1; // Failure
if (pData->flags & CSSF_MASK_STATUS)
{ // fill status member
*pData->status = ICQGetContactXStatus(hContact);
}
if (pData->flags & CSSF_MASK_NAME)
{ // fill status name member
if (pData->flags & CSSF_DEFAULT_NAME)
{
BYTE status = *pData->wParam;
if (status < 1 || status > XstatusIcons) return 1; // Failure
if (pData->flags & CSSF_UNICODE)
{
char *text = (char*)nameXStatus[status -1];
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, text, -1, pData->pwszName, MAX_PATH);
}
else
strcpy(pData->pszName, nameXStatus[status - 1]);
}
else
{
if (pData->flags & CSSF_UNICODE)
{
char* str = ICQGetContactSettingUtf(hContact, DBSETTING_XSTATUSNAME, "");
wchar_t* wstr = make_unicode_string(str);
wcscpy(pData->pwszName, wstr);
SAFE_FREE(&str);
SAFE_FREE(&wstr);
}
else
{
DBVARIANT dbv = {0};
if (!ICQGetContactSettingString(hContact, DBSETTING_XSTATUSNAME, &dbv) && dbv.pszVal)
strcpy(pData->pszName, dbv.pszVal);
else
strcpy(pData->pszName, "");
ICQFreeVariant(&dbv);
}
}
}
if (pData->flags & CSSF_MASK_MESSAGE)
{ // fill status message member
if (pData->flags & CSSF_UNICODE)
{
char* str = ICQGetContactSettingUtf(hContact, DBSETTING_XSTATUSMSG, "");
wchar_t* wstr = make_unicode_string(str);
wcscpy(pData->pwszMessage, wstr);
SAFE_FREE(&str);
SAFE_FREE(&wstr);
}
else
{
DBVARIANT dbv = {0};
if (!ICQGetContactSettingString(hContact, DBSETTING_XSTATUSMSG, &dbv) && dbv.pszVal)
strcpy(pData->pszMessage, dbv.pszVal);
else
strcpy(pData->pszMessage, "");
ICQFreeVariant(&dbv);
}
}
if (pData->flags & CSSF_DISABLE_UI)
{
if (pData->wParam) *pData->wParam = !bHideXStatusUI;
}
if (pData->flags & CSSF_STATUSES_COUNT)
{
if (pData->wParam) *pData->wParam = XstatusIcons;
}
if (pData->flags & CSSF_STR_SIZES)
{
DBVARIANT dbv = {0};
if (pData->wParam)
{
if (!ICQGetContactSettingString(hContact, DBSETTING_XSTATUSNAME, &dbv))
{
*pData->wParam = strlennull(dbv.pszVal);
ICQFreeVariant(&dbv);
}
else
*pData->wParam = 0;
}
if (pData->lParam)
{
if (!ICQGetContactSettingString(hContact, DBSETTING_XSTATUSMSG, &dbv))
{
*pData->lParam = strlennull(dbv.pszVal);
ICQFreeVariant(&dbv);
}
else
*pData->lParam = 0;
}
}
return 0; // Success
}
int IcqGetXStatusIcon(WPARAM wParam, LPARAM lParam)
{
if (!gbXStatusEnabled) return 0;
if (!wParam)
wParam = ICQGetContactXStatus(NULL);
if (wParam >= 1 && wParam <= XstatusIcons)
{
if (lParam == LR_SHARED)
return (int)GetXStatusIcon((BYTE)wParam, lParam);
else
return (int)GetXStatusIcon((BYTE)wParam, 0);
}
return 0;
}
int IcqRequestXStatusDetails(WPARAM wParam, LPARAM lParam)
{
HANDLE hContact = (HANDLE)wParam;
if (!gbXStatusEnabled)
return 0;
if (hContact && !ICQGetContactSettingByte(NULL, "XStatusAuto", DEFAULT_XSTATUS_AUTO) &&
ICQGetContactXStatus(hContact))
{ // user has xstatus, no auto-retrieve details, valid contact, request details
return requestXStatusDetails(hContact, TRUE);
}
return 0;
}
int IcqRequestAdvStatusIconIdx(WPARAM wParam, LPARAM lParam)
{
BYTE bXStatus;
if (!gbXStatusEnabled) return -1;
bXStatus = ICQGetContactXStatus((HANDLE)wParam);
if (bXStatus)
{
int idx=-1;
if (!bXStatusCListIconsValid[bXStatus-1])
{ // adding icon
int idx = hXStatusCListIcons[bXStatus-1];
HIMAGELIST hCListImageList = (HIMAGELIST)CallService(MS_CLIST_GETICONSIMAGELIST,0,0);
if (hCListImageList)
{
HICON hXStatusIcon = GetXStatusIcon(bXStatus, LR_SHARED);
if (idx > 0)
ImageList_ReplaceIcon(hCListImageList, idx, hXStatusIcon);
else
hXStatusCListIcons[bXStatus-1] = ImageList_AddIcon(hCListImageList, hXStatusIcon);
// mark icon index in the array as valid
bXStatusCListIconsValid[bXStatus-1] = TRUE;
}
}
idx = bXStatusCListIconsValid[bXStatus-1] ? hXStatusCListIcons[bXStatus-1] : -1;
if (idx > 0)
return (idx & 0xFFFF) << 16;
}
return -1;
}