summaryrefslogtreecommitdiff
path: root/plugins/CSList/src
diff options
context:
space:
mode:
authorVadim Dashevskiy <watcherhd@gmail.com>2012-07-17 08:44:50 +0000
committerVadim Dashevskiy <watcherhd@gmail.com>2012-07-17 08:44:50 +0000
commite736ab21213b66669dde5d9a9003596706eee8bd (patch)
treeb891b19763dd047c3b34c9df8c3b32b941ce4983 /plugins/CSList/src
parentee2e419778605a5445474a33a29f2cfbb7eed245 (diff)
CSList, CyrTranslit: changed folder structure
git-svn-id: http://svn.miranda-ng.org/main/trunk@1002 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'plugins/CSList/src')
-rw-r--r--plugins/CSList/src/Version.h22
-rw-r--r--plugins/CSList/src/cslist.cpp1349
-rw-r--r--plugins/CSList/src/cslist.h665
-rw-r--r--plugins/CSList/src/legacy.h87
-rw-r--r--plugins/CSList/src/resource.h49
-rw-r--r--plugins/CSList/src/strpos.h70
6 files changed, 2242 insertions, 0 deletions
diff --git a/plugins/CSList/src/Version.h b/plugins/CSList/src/Version.h
new file mode 100644
index 0000000000..8206c5c61f
--- /dev/null
+++ b/plugins/CSList/src/Version.h
@@ -0,0 +1,22 @@
+#define __MAJOR_VERSION 0
+#define __MINOR_VERSION 1
+#define __RELEASE_NUM 0
+#define __BUILD_NUM 5
+
+#define __FILEVERSION_STRING __MAJOR_VERSION,__MINOR_VERSION,__RELEASE_NUM,__BUILD_NUM
+#define __FILEVERSION_DOTS __MAJOR_VERSION.__MINOR_VERSION.__RELEASE_NUM.__BUILD_NUM
+
+#define __STRINGIFY_IMPL(x) #x
+#define __STRINGIFY(x) __STRINGIFY_IMPL(x)
+#define __VERSION_STRING __STRINGIFY(__FILEVERSION_DOTS)
+
+
+
+#define __PLUGIN_NAME "Custom Status List mod"
+#define __INTERNAL_NAME "CSList"
+#define __FILENAME "CSList.dll"
+#define __DESCRIPTION "This plugin offers simple management functions to keep your extra statuses on one place."
+#define __AUTHOR "Mataes, jarvis"
+#define __AUTHOREMAIL "mataes2007@gmail.com"
+#define __AUTHORWEB "http://mataes.googlecode.com/svn/Miranda/Plugins/Cslist/"
+#define __COPYRIGHT "© 2011-10 Mataes, 2009-2007 jarvis"
diff --git a/plugins/CSList/src/cslist.cpp b/plugins/CSList/src/cslist.cpp
new file mode 100644
index 0000000000..b8078ae1be
--- /dev/null
+++ b/plugins/CSList/src/cslist.cpp
@@ -0,0 +1,1349 @@
+/* ========================================================================
+
+ Custom Status List
+ __________________
+
+ Custom Status List plugin for Miranda-IM (www.miranda-im.org)
+ Follower of Custom Status History List by HANAX
+ Copyright © 2006-2008 HANAX
+ Copyright © 2007-2009 jarvis
+
+ 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 : $URL$
+ Revision : $Rev$
+ Last change on : $Date$
+ Last change by : $Author$
+
+ ============================================================================
+
+
+ DESCRIPTION:
+
+ Offers List of your Custom Statuses.
+
+// ======================================================================== */
+
+#include "cslist.h"
+#include "strpos.h"
+#include "legacy.h"
+
+SortedList *servicesList;
+int hLangpack;
+
+extern "C" __declspec(dllexport) const MUUID MirandaInterfaces[] = { PLUGIN_GUUID, MIID_LAST };
+
+PLUGININFOEX pluginInfoEx =
+{
+ sizeof(PLUGININFOEX),
+ __PLUGIN_NAME,
+ PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
+ __DESCRIPTION,
+ __AUTHOR,
+ __AUTHOREMAIL,
+ __COPYRIGHT,
+ __AUTHORWEB,
+ UNICODE_AWARE,
+ PLUGIN_GUUID
+};
+
+// ====[ MAIN ]===============================================================
+
+BOOL WINAPI DllMain( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved )
+{
+ CSList::handle = hinstDLL;
+ return TRUE;
+}
+
+
+// ====[ PLUGIN INFO ]========================================================
+
+extern "C" __declspec( dllexport ) PLUGININFOEX* MirandaPluginInfoEx( DWORD mirandaVersion )
+{
+ CSList::dwMirandaVersion = mirandaVersion;
+ return &pluginInfoEx;
+}
+
+// ====[ LOADER ]=============================================================
+
+extern "C" __declspec( dllexport ) int Load( )
+{
+ mir_getLP(&pluginInfoEx);
+ servicesList = List_Create(0, 10);
+
+ // support for ComboBoxEx
+ {
+ INITCOMMONCONTROLSEX icc;
+ icc.dwSize = sizeof(icc);
+ icc.dwICC = ICC_USEREX_CLASSES;
+ InitCommonControlsEx( &icc );
+ }
+
+ // set global variables
+ // we need 0.8.0.9 core which introduced accounts support for protocols
+ CSList::bAccountsSupported = ( CSList::dwMirandaVersion >= PLUGIN_MAKE_VERSION( 0, 8, 0, 9 ));
+
+ // are we running under Unicode core?
+ {
+ char szVer[MAX_PATH];
+
+ CallService( MS_SYSTEM_GETVERSIONTEXT, MAX_PATH, ( LPARAM )szVer );
+ _strlwr( szVer ); // make sure it is lowercase
+
+ CSList::bUnicodeCore = ( strstr( szVer, "unicode" ) != NULL );
+ }
+
+ // TODO: Alerts with wrong combination of ANSI/Unicode Windows/core/plugin
+
+ // create handler
+ cslist = new CSList( );
+
+ return FALSE;
+}
+
+
+// ====[ UNLOADER ]===========================================================
+
+extern "C" __declspec( dllexport ) int Unload( void )
+{
+ for (int i = servicesList->realCount-1; i >= 0; i--)
+ {
+ HANDLE *hService = (HANDLE *)servicesList->items[i];
+ DestroyServiceFunction(hService);
+ }
+ List_Destroy(servicesList);
+ mir_free(servicesList);
+ delete cslist;
+
+ return FALSE;
+}
+
+
+// ====[ FUN ]================================================================
+
+
+CSList::CSList( )
+{
+ this->mainWindow = NULL;
+ this->initIcoLib( );
+ this->hHookOnOptionsInit = HookEvent( ME_OPT_INITIALISE, this->initOptions );
+ //this->hHookOnPluginsLoaded = HookEvent( ME_SYSTEM_MODULESLOADED, this->postLoading );
+ this->hHookOnDBSettingChanged = HookEvent( ME_DB_CONTACT_SETTINGCHANGED, this->respondDBChange );
+ this->hHookOnStatusMenuBuild = HookEvent( ME_CLIST_PREBUILDSTATUSMENU, this->createMenuItems );
+}
+
+
+CSList::~CSList( )
+{
+ // unhook events, destroy functions
+ UnhookEvent( this->hHookOnStatusMenuBuild );
+ UnhookEvent( this->hHookOnPluginsLoaded );
+ UnhookEvent( this->hHookOnOptionsInit );
+ UnhookEvent( this->hHookOnDBSettingChanged );
+ DestroyServiceFunction( this->hServiceShowList );
+
+ // clear IcoLib
+ for ( int i = 0; i < SIZEOF(forms); i++ )
+ {
+ char iconName[64];
+ mir_snprintf(iconName, SIZEOF(iconName), "%s_%s", __INTERNAL_NAME, forms[i].pszIconIcoLib);
+ CallService( MS_SKIN2_REMOVEICON, 0, ( LPARAM )iconName );
+ }
+}
+
+
+int CSList::postLoading( WPARAM wparam, LPARAM lparam )
+{
+ //cslist->registerHotkeys( );
+ cslist->initIcoLib( ); // for < 0.7, but probably useless though :/
+ return FALSE;
+}
+
+
+void CSList::registerHotkeys(char buf[200], TCHAR* accName, int Number)
+{
+ HOTKEYDESC hotkey = { 0 };
+ hotkey.cbSize = sizeof(hotkey);
+ hotkey.dwFlags = HKD_TCHAR;
+ hotkey.pszName = buf;
+ hotkey.ptszDescription = accName;
+ hotkey.ptszSection = LPGENT("Custom Status List");
+ hotkey.pszService = buf;
+ hotkey.DefHotKey = HOTKEYCODE( HOTKEYF_CONTROL | HOTKEYF_SHIFT, '0'+Number );
+ Hotkey_Register(&hotkey);
+}
+
+int CSList::initOptions( WPARAM wparam, LPARAM lparam )
+{
+ OPTIONSDIALOGPAGE odp = { 0 };
+ odp.cbSize = sizeof(odp);
+ odp.position = 955000000;
+ odp.hInstance = CSList::handle;
+ odp.pszTemplate = MAKEINTRESOURCEA( IDD_OPTIONS );
+ odp.pszTitle = MODULENAME;
+ odp.pfnDlgProc = CSOptionsProc;
+ odp.pszGroup = LPGEN("Status");
+ odp.flags = ODPF_BOLDGROUPS;
+ Options_AddPage(wparam, &odp);
+ return FALSE;
+}
+
+
+int CSList::respondDBChange( WPARAM wparam, LPARAM lparam )
+{
+ HANDLE hContact = ( HANDLE )wparam;
+ DBCONTACTWRITESETTING *cws = ( DBCONTACTWRITESETTING* )lparam;
+
+ // if user changes his UIN or JID on any account
+ if (hContact == NULL && (!lstrcmpA(cws->szSetting, "UIN") || !lstrcmpA(cws->szSetting, "jid")))
+ {
+ cslist->rebuildMenuItems();
+ return 0;
+ }
+
+ // own setting or not a status-related setting
+ else if ( hContact == NULL || lstrcmpA( cws->szSetting, "Status" ))
+ return 0;
+
+ DWORD dwEasteredUin = getDword( "EasterEggedUIN", 0x0 );
+ if ( dwEasteredUin == 0x0 ) // no spyed UIN found
+ return 0;
+
+ DBVARIANT dbv = { 0 };
+ DBGetContactSettingString( hContact, "Protocol", "p", &dbv );
+
+ DWORD dwUin = DBGetContactSettingDword( hContact, dbv.pszVal, "UIN", 0x0 );
+
+ if ( dwUin != 0x0 ) // if this is an ICQ user
+ if ( dwUin == dwEasteredUin ) // if spyed UIN is equivalent to this contact
+ if ( DBGetContactSettingWord( hContact, "UserOnline", "OldStatus", 0 ) == ID_STATUS_OFFLINE )
+ if ( cws->value.wVal > ID_STATUS_OFFLINE )
+ cslist->setStatus( IDC_CANCEL, NULL, "");
+
+ return FALSE;
+}
+
+
+int CSList::createMenuItems( WPARAM wparam, LPARAM lparam )
+{
+ int ProtoCount = 0;
+
+ ForAllProtocols(countProtos, &ProtoCount);
+
+ if (ProtoCount == 0)
+ return FALSE;
+
+ ForAllProtocols(addProtoStatusMenuItem, 0);
+
+ return FALSE;
+}
+
+
+void CSList::rebuildMenuItems( )
+{
+ CLIST_INTERFACE* pcli;
+ pcli = ( CLIST_INTERFACE* )CallService( MS_CLIST_RETRIEVE_INTERFACE, 0, 0 );
+ if ( pcli && pcli->version > 4 )
+ pcli->pfnReloadProtoMenus( );
+}
+
+
+void CSList::setStatus( WORD code, StatusItem* item, char* protoName)
+{
+ if ( code == IDCLOSE )
+ return;
+
+ PROTOACCOUNT* pdescr = (PROTOACCOUNT*)CallService(MS_PROTO_GETACCOUNT, 0, (LPARAM)protoName);
+ if (pdescr == NULL)
+ return;
+ int statusToSet = -1;
+ if (lstrcmpA(pdescr->szProtoName, "ICQ") == 0)
+ {
+ ICQ_CUSTOM_STATUS ics = {0};
+ ics.cbSize = sizeof(ICQ_CUSTOM_STATUS);
+ ics.flags = CSSF_MASK_STATUS | CSSF_MASK_NAME | CSSF_MASK_MESSAGE | CSSF_TCHAR;
+
+ if (code == IDC_CANCEL)
+ {
+ statusToSet = 0;
+ ics.ptszName = _T("");
+ ics.ptszMessage = _T("");
+ }
+ else if (code == IDOK && item != NULL)
+ {
+ statusToSet = item->iIcon + 1;
+ ics.ptszName = variables_parsedup(item->tszTitle, NULL, NULL);
+ ics.ptszMessage = variables_parsedup(item->tszMessage, NULL, NULL);
+ }
+ else return;
+
+ ics.status = &statusToSet;
+
+ char protoService[64];
+ mir_snprintf(protoService, SIZEOF(protoService), "%s%s", protoName, PS_ICQ_SETCUSTOMSTATUSEX);
+ CallService(protoService, 0, (LPARAM)&ics);
+ }
+ if (lstrcmpA(pdescr->szProtoName, "JABBER") == 0)
+ {
+ JABBER_CUSTOM_STATUS ics = {0};
+ ics.cbSize = sizeof(ICQ_CUSTOM_STATUS);
+ ics.flags = CSSF_MASK_STATUS | CSSF_MASK_NAME | CSSF_MASK_MESSAGE | CSSF_TCHAR;
+
+ if (code == IDC_CANCEL)
+ {
+ statusToSet = 0;
+ ics.ptszMessage = _T("");
+ }
+ else if (code == IDOK && item != NULL)
+ {
+ statusToSet = item->iIcon + 1;
+ ics.ptszMessage = variables_parsedup(item->tszMessage, NULL, NULL);
+ }
+ else return;
+
+ ics.status = &statusToSet;
+
+ char protoService[64];
+ mir_snprintf(protoService, SIZEOF(protoService), "%s%s", protoName, JS_SETXSTATUSEX);
+ CallService(protoService, 0, (LPARAM)&ics);
+ }
+}
+
+void CSList::initIcoLib( )
+{
+ // init icons of buttons
+ TCHAR tszFile[MAX_PATH];
+ GetModuleFileName( CSList::handle, tszFile, MAX_PATH );
+
+ SKINICONDESC sid = { 0 };
+ sid.cbSize = sizeof(SKINICONDESC);
+ sid.ptszDefaultFile = tszFile;
+ sid.flags = SIDF_ALL_TCHAR;
+ sid.cx = sid.cy = 16;
+ sid.ptszSection = _T(MODULENAME);
+
+ for (int i=0; i < SIZEOF(forms); i++ ) {
+ char szSettingName[64];
+ mir_snprintf( szSettingName, SIZEOF(szSettingName), "%s_%s", __INTERNAL_NAME, forms[i].pszIconIcoLib );
+
+ sid.pszName = szSettingName;
+ sid.ptszDescription = forms[i].ptszDescr;
+ sid.iDefaultIndex = -forms[i].iconNoIcoLib;
+ forms[i].hIcoLibItem = Skin_AddIcon(&sid);
+ }
+}
+
+
+INT_PTR CSList::showList(WPARAM wparam, LPARAM lparam, LPARAM param)
+{
+ cslist->mainWindow = new CSWindow((char*)param);
+ ForkThread(&cslist->mainWindow->showWindow, cslist->mainWindow);
+ return 0;
+}
+
+
+void CSList::closeList( HWND hwnd )
+{
+ ForkThread( &cslist->mainWindow->closeWindow, hwnd );
+ delete cslist->mainWindow;
+ cslist->mainWindow = NULL;
+}
+
+
+void CSList::ForAllProtocols( pForAllProtosFunc pFunc, void* arg )
+{
+ int protoCount;
+ PROTOACCOUNT** pdesc;
+ CallService( MS_PSEUDO_PROTO_PROTOACCSENUM, ( WPARAM )&protoCount, ( LPARAM )&pdesc );
+
+ for ( int i = 0; i < protoCount; i++ )
+ {
+ if (lstrcmpA(pdesc[i]->szProtoName, "ICQ") == 0)
+ {
+ DWORD uin = 0;
+ uin = DBGetContactSettingDword(NULL, pdesc[i]->szModuleName, "UIN", 0);
+ if (uin == 0)
+ continue;
+ }
+ else if (lstrcmpA(pdesc[i]->szProtoName, "JABBER") == 0)
+ {
+ DBVARIANT dbv = {0};
+ DBGetContactSettingTString(NULL, pdesc[i]->szModuleName, "jid", &dbv);
+ if (dbv.ptszVal == _T(""))
+ continue;
+ }
+ else
+ continue;
+ pFunc(pdesc[i]->szModuleName , arg);
+ }
+}
+
+
+void CSList::addProtoStatusMenuItem( char* protoName, void* arg )
+{
+ char buf[200];
+ PROTOACCOUNT* pdescr;
+ pdescr = (PROTOACCOUNT*)CallService(MS_PROTO_GETACCOUNT, 0, (LPARAM)protoName);
+ if (pdescr == NULL)
+ return;
+
+ HANDLE hService;
+ mir_snprintf(buf, SIZEOF(buf), "CSList/ShowList/%s", protoName);
+ if (!ServiceExists(buf))
+ hService = CreateServiceFunctionParam(buf, CSList::showList, (LPARAM)protoName);
+ List_Insert(servicesList, hService, servicesList->realCount);
+
+ CLISTMENUITEM mi = {0};
+ mi.cbSize = sizeof(mi);
+ mi.flags = CMIF_TCHAR;
+ if (ServiceExists(MS_SKIN2_GETICON))
+ mi.icolibItem = (HANDLE)LoadIconExEx("icon", IDI_CSLIST);
+ else
+ mi.hIcon = LoadIconExEx("icon", IDI_CSLIST);
+ mi.ptszName = _T(MODULENAME);
+ mi.position = 2000040000;
+ mi.pszService = buf;
+ mi.ptszPopupName = pdescr->tszAccountName;
+ Menu_AddStatusMenuItem(&mi);
+
+ cslist->registerHotkeys(buf, pdescr->tszAccountName, pdescr->iOrder);
+}
+
+
+void CSList::countProtos( char* protoName, void* arg )
+{
+ int* protosEnabled = (int*)arg;
+ *protosEnabled = ( *protosEnabled )++;
+}
+
+
+void CSList::countPlusModProtos( char* protoName, void* arg )
+{
+ int* protosExtraEnabled = ( int* )arg;
+ if ( DBGetContactSettingDword( NULL, protoName, "NonStandartXstatus", 0 ) ||
+ DBGetContactSettingDword( NULL, protoName, "NonStandardXstatus", 0 ))
+ *protosExtraEnabled = ( *protosExtraEnabled )++;
+}
+
+void CSList::importCustomStatusUIStatusesFromAllProtos( char* protoName, void* arg )
+{
+ int* result = ( int* )arg;
+
+ for ( int i = 1; i <= 37; i++ )
+ {
+ DBVARIANT dbv = { 0 };
+ char bufTitle[32], bufMessage[32];
+ StatusItem* si = new StatusItem( );
+
+ si->iIcon = i - 1;
+
+ mir_snprintf( bufTitle, 32, "XStatus%luName", i );
+ DBGetContactSettingTString( NULL, protoName, bufTitle, &dbv );
+ lstrcpy( si->tszTitle, dbv.ptszVal );
+
+ mir_snprintf( bufMessage, 32, "XStatus%luMsg", i );
+ DBGetContactSettingTString( NULL, protoName, bufMessage, &dbv );
+ lstrcpy( si->tszMessage, dbv.ptszVal );
+
+ if ( lstrlen( si->tszTitle ) || lstrlen( si->tszMessage ))
+ {
+ cslist->mainWindow->itemslist->list->add( si );
+ cslist->mainWindow->bSomethingChanged = TRUE;
+ }
+ else
+ delete si;
+
+ if ( *result == IDYES )
+ {
+ DBDeleteContactSetting( NULL, protoName, bufTitle );
+ DBDeleteContactSetting( NULL, protoName, bufMessage );
+ }
+ }
+ cslist->mainWindow->listview->reinitItems( cslist->mainWindow->itemslist->list->getListHead( ));
+}
+
+
+CSWindow::CSWindow(char* protoName)
+{
+ this->protoName = protoName;
+ this->handle = NULL;
+ this->bExtraIcons = getByte( "AllowExtraIcons", DEFAULT_ALLOW_EXTRA_ICONS );
+ this->itemslist = new CSItemsList(this->protoName);
+ this->listview = NULL;
+ this->addModifyDlg = NULL;
+ this->bSomethingChanged = FALSE;
+ this->filterString = NULL;
+}
+
+
+CSWindow::~CSWindow( )
+{
+ delete this->itemslist;
+ SAFE_FREE( ( void** )&this->filterString );
+}
+
+
+void CSWindow::showWindow( void* arg )
+{
+ CSWindow* csw = ( CSWindow* )arg;
+
+ while ( csw == NULL )
+ SleepEx( 10, FALSE );
+
+ DialogBoxParam( CSList::handle, MAKEINTRESOURCE( IDD_CSLIST ), NULL, ( DLGPROC )CSWindowProc, ( LPARAM )csw );
+}
+
+
+void CSWindow::closeWindow( void* arg )
+{
+ HWND hwnd = ( HWND )arg;
+ EndDialog( hwnd, FALSE );
+}
+
+
+void CSWindow::initIcons()
+{
+ PROTOACCOUNT* pdescr = (PROTOACCOUNT*)CallService(MS_PROTO_GETACCOUNT, 0, (LPARAM)protoName);
+ if (pdescr == NULL)
+ return;
+
+ if (lstrcmpA(pdescr->szProtoName, "ICQ") == 0)
+ {
+ DWORD uin = 0;
+ uin = DBGetContactSettingDword(NULL, pdescr->szModuleName, "UIN", 0);
+ if (uin != 0)
+ {
+ this->icons = ImageList_Create( 16, 16, IsWinVerXPPlus( ) ? ILC_COLOR32 | ILC_MASK : ILC_COLOR16 | ILC_MASK, XSTATUS_COUNT_EXTENDED, 0 );
+ if ( this->icons )
+ {
+ for ( int i = 0; i < ( ( this->bExtraIcons ) ? XSTATUS_COUNT_EXTENDED : XSTATUS_COUNT ); i++ )
+ {
+ char szTemp[MAX_PATH];
+ mir_snprintf(szTemp, SIZEOF(szTemp), "%s_xstatus%d", protoName, i);
+ ImageList_AddIcon( this->icons, ( HICON )CallService( MS_SKIN2_GETICON, 0, ( LPARAM )szTemp ));
+ }
+ }
+ }
+ }
+ else if (lstrcmpA(pdescr->szProtoName, "JABBER") == 0)
+ {
+ DBVARIANT dbv = {0};
+ DBGetContactSettingTString(NULL, pdescr->szModuleName, "jid", &dbv);
+ if (dbv.ptszVal != _T(""))
+ {
+ this->icons = ImageList_Create( 16, 16, IsWinVerXPPlus( ) ? ILC_COLOR32 | ILC_MASK : ILC_COLOR16 | ILC_MASK, MOODS_COUNT, 0 );
+ if ( this->icons )
+ {
+ for ( int i = 0; i < MOODS_COUNT; i++ )
+ {
+ char szTemp[MAX_PATH];
+ mir_snprintf(szTemp, SIZEOF(szTemp), "%s_%s", protoName, moods_names[i].szTag);
+ ImageList_AddIcon( this->icons, ( HICON )CallService( MS_SKIN2_GETICON, 0, ( LPARAM )szTemp ));
+ }
+ }
+ }
+ }
+}
+
+
+void CSWindow::deinitIcons( )
+{
+ ImageList_Destroy( this->icons );
+}
+
+
+void CSWindow::initButtons( )
+{
+ for (int i = 0; i < SIZEOF(forms); i++)
+ {
+ if ( forms[i].idc < 0 )
+ continue;
+
+ SendDlgItemMessage( this->handle, forms[i].idc, BM_SETIMAGE, IMAGE_ICON, ( LPARAM )LoadIconExEx( forms[i].pszIconIcoLib, forms[i].iconNoIcoLib ));
+ SendDlgItemMessage( this->handle, forms[i].idc, BUTTONSETASFLATBTN, TRUE, 0 ); //maybe set as BUTTONSETDEFAULT?
+ SendDlgItemMessage( this->handle, forms[i].idc, BUTTONADDTOOLTIP, ( WPARAM )TranslateTS(forms[i].ptszTitle), BATF_TCHAR );
+ }
+}
+
+void CSWindow::loadWindowPosition( )
+{
+ RECT rect = { 0 };
+ int width = GetSystemMetrics( SM_CXSCREEN );
+ int height = GetSystemMetrics( SM_CYSCREEN );
+ GetWindowRect( this->handle, &rect );
+ int x, y, defX, defY;
+ defX = x = ( width + 1 - ( rect.right - rect.left )) >> 1;
+ defY = y = ( height + 1 - ( rect.bottom - rect.top )) >> 1;
+ if ( getByte( "RememberWindowPosition", DEFAULT_REMEMBER_WINDOW_POSITION ))
+ {
+ x = getWord( "PositionX", defX );
+ y = getWord( "PositionY", defY );
+ }
+ if ( x > width || y > height || x < 0 || y < 0 )
+ {
+ x = defX;
+ y = defY;
+ }
+
+ MoveWindow( this->handle,
+ x, y,
+ ( rect.right - rect.left ),
+ ( rect.bottom - rect.top ),
+ TRUE );
+}
+
+
+void CSWindow::toggleEmptyListMessage( )
+{
+ HWND hwnd = GetDlgItem( this->handle, IDC_NO_ITEMS );
+ ShowWindow( hwnd, ( ListView_GetItemCount( this->listview->handle ) > 0 ) ? FALSE : TRUE );
+ SetForegroundWindow( hwnd );
+ hwnd = GetDlgItem( this->handle, IDC_ADD_SAMPLE );
+ ShowWindow( hwnd, ( ListView_GetItemCount( this->listview->handle ) > 0 ) ? FALSE : TRUE );
+ SetForegroundWindow( hwnd );
+}
+
+
+BOOL CSWindow::itemPassedFilter( ListItem< StatusItem >* li )
+{
+ TCHAR filter[MAX_PATH];
+ GetDlgItemText( this->handle, IDC_FILTER_FIELD, filter, MAX_PATH );
+
+ if ( lstrlen( filter ))
+ {
+ TCHAR title[EXTRASTATUS_TITLE_LIMIT], message[EXTRASTATUS_MESSAGE_LIMIT];
+ lstrcpy( title, li->item->tszTitle ); lstrcpy( message, li->item->tszMessage );
+ if ( strpos( _tcslwr( title ), _tcslwr( filter )) == -1 )
+ if ( strpos( _tcslwr( message ), _tcslwr( filter )) == -1 )
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+void CSWindow::toggleFilter( )
+{
+ HWND hFilter = GetDlgItem( this->handle, IDC_FILTER_FIELD );
+ BOOL isEnabled = !IsWindowEnabled( hFilter ) ? TRUE : FALSE; // ! = + isEnabled = !isEnabled in one
+ EnableWindow( hFilter, isEnabled );
+ ShowWindow( hFilter, isEnabled );
+ CheckDlgButton( this->handle, IDC_FILTER, isEnabled );
+ SetForegroundWindow( hFilter );
+ if ( isEnabled )
+ SetFocus( hFilter );
+ else
+ {
+ TCHAR filterText[255];
+ GetDlgItemText(this->handle, IDC_FILTER_FIELD, filterText, SIZEOF(filterText));
+ if ( lstrlen( filterText ) > 0 )
+ SetDlgItemText( this->handle, IDC_FILTER_FIELD, TEXT( "" ));
+ }
+}
+
+
+BOOL CSWindow::toggleButtons( )
+{
+ int selection = ListView_GetSelectedItemMacro( this->listview->handle );
+ BOOL validSelection = ( selection >= 0 && ( unsigned int )selection < this->itemslist->list->getCount( )) ? TRUE : FALSE;
+ BOOL filterEnabled = IsWindowVisible( GetDlgItem( this->handle, IDC_FILTER_FIELD ));
+ BOOL somethingChanged = this->bSomethingChanged;
+
+ EnableWindow( GetDlgItem( this->handle, IDC_ADD ), !filterEnabled );
+ EnableWindow( GetDlgItem( this->handle, IDC_MODIFY ), validSelection && !filterEnabled );
+ EnableWindow( GetDlgItem( this->handle, IDC_REMOVE ), validSelection && !filterEnabled );
+ EnableWindow( GetDlgItem( this->handle, IDC_FAVOURITE ), validSelection && !filterEnabled );
+ EnableWindow( GetDlgItem( this->handle, IDC_UNDO ), somethingChanged && !filterEnabled );
+ EnableWindow( GetDlgItem( this->handle, IDC_IMPORT ), !filterEnabled );
+// EnableWindow( GetDlgItem( this->handle, IDC_GLOBAL ), !filterEnabled );
+ EnableWindow( GetDlgItem( this->handle, IDOK ), validSelection );
+
+ return validSelection;
+}
+
+
+CSAMWindow::CSAMWindow( WORD action, CSWindow* parent )
+{
+ this->action = action;
+ this->parent = parent;
+ this->bChanged = FALSE;
+ this->hCombo = this->hMessage = NULL;
+
+ if ( this->action == IDC_ADD )
+ this->item = new StatusItem( );
+ else
+ this->item = new StatusItem( *this->parent->itemslist->list->get( this->parent->listview->getPositionInList( )) );
+
+}
+
+
+CSAMWindow::~CSAMWindow( )
+{
+ if ( ! this->bChanged )
+ delete this->item;
+}
+
+
+void CSAMWindow::exec( )
+{
+ DialogBoxParam( CSList::handle, MAKEINTRESOURCE( IDD_ADDMODIFY ), NULL, ( DLGPROC )CSAMWindowProc, ( LPARAM )this );
+}
+
+
+void CSAMWindow::setCombo()
+{
+ PROTOACCOUNT* pdescr = (PROTOACCOUNT*)CallService(MS_PROTO_GETACCOUNT, 0, (LPARAM)this->parent->protoName);
+ if (pdescr == NULL)
+ return;
+
+ if (lstrcmpA(pdescr->szProtoName, "ICQ") == 0)
+ {
+ DWORD uin = 0;
+ uin = DBGetContactSettingDword(NULL, pdescr->szModuleName, "UIN", 0);
+ if (uin != 0)
+ {
+ SendMessage( this->hCombo, CBEM_SETIMAGELIST, 0, ( LPARAM )this->parent->icons );
+ for ( int i = 0; i < ( ( this->parent->bExtraIcons ) ? XSTATUS_COUNT_EXTENDED : XSTATUS_COUNT ); i++ )
+ {
+ COMBOBOXEXITEM cbi = { 0 };
+ cbi.mask = CBEIF_IMAGE | CBEIF_TEXT | CBEIF_SELECTEDIMAGE;
+ cbi.pszText = TranslateTS(xstatus_names[i].ptszTitle);
+ cbi.iImage = xstatus_names[i].iId - 1;
+ cbi.iItem = i;
+ cbi.iSelectedImage = i;
+ SendMessage( this->hCombo, CBEM_INSERTITEM, 0, ( LPARAM )&cbi );
+ }
+ SendMessage( this->hCombo, CB_SETCURSEL, 0, 0 ); // first 0 sets selection to top
+ }
+ }
+ else if (lstrcmpA(pdescr->szProtoName, "JABBER") == 0)
+ {
+ DBVARIANT dbv = {0};
+ DBGetContactSettingTString(NULL, pdescr->szModuleName, "jid", &dbv);
+ if (dbv.ptszVal != _T(""))
+ {
+ SendMessage( this->hCombo, CBEM_SETIMAGELIST, 0, ( LPARAM )this->parent->icons );
+ for ( int i = 0; i < MOODS_COUNT; i++ )
+ {
+ COMBOBOXEXITEM cbi = { 0 };
+ cbi.mask = CBEIF_IMAGE | CBEIF_TEXT | CBEIF_SELECTEDIMAGE;
+ cbi.pszText = TranslateTS(moods_names[i].ptszTitle);
+ cbi.iImage = moods_names[i].iId - 1;
+ cbi.iItem = i;
+ cbi.iSelectedImage = i;
+ SendMessage( this->hCombo, CBEM_INSERTITEM, 0, ( LPARAM )&cbi );
+ }
+ SendMessage( this->hCombo, CB_SETCURSEL, 0, 0 ); // first 0 sets selection to top
+ }
+ }
+}
+
+void CSAMWindow::fillDialog( )
+{
+ if ( this->action == IDC_ADD )
+ {
+ SetWindowText( this->handle, TranslateT("Add new item"));
+ SetDlgItemText( this->handle, IDOK, TranslateT("Add"));
+ }
+ else
+ {
+ SetWindowText( this->handle, TranslateT("Modify item"));
+ SetDlgItemText( this->handle, IDOK, TranslateT("Modify"));
+ }
+
+ SendMessage( this->hCombo, CB_SETCURSEL, this->item->iIcon, 0 );
+ SetDlgItemText( this->handle, IDC_MESSAGE, this->item->tszMessage );
+}
+
+
+void CSAMWindow::checkFieldLimit( WORD action, WORD item )
+{
+ BOOL type = ( item == IDC_MESSAGE ) ? TRUE : FALSE;
+ unsigned int limit = type ? EXTRASTATUS_MESSAGE_LIMIT : EXTRASTATUS_TITLE_LIMIT;
+
+ if ( action == EN_CHANGE )
+ {
+ TCHAR* ptszInputText = (TCHAR*)mir_alloc((limit + 8) * sizeof(TCHAR));
+
+ GetDlgItemText( this->handle, item, ptszInputText, limit + 8 );
+
+ if ( _tcslen( ptszInputText ) > limit )
+ {
+#if ( WINVER >= 0x501 )
+ TCHAR tszPopupTip[MAX_PATH];
+ EDITBALLOONTIP ebt = { 0 };
+ ebt.cbStruct = sizeof(ebt);
+ ebt.pszTitle = TranslateT("Warning");
+ mir_sntprintf(tszPopupTip, SIZEOF(tszPopupTip), TranslateT("This field doesn't accept string longer than %d characters. The string will be truncated."), limit);
+ ebt.pszText = tszPopupTip;
+ ebt.ttiIcon = TTI_WARNING;
+ SendMessage( GetDlgItem( this->handle, item ), EM_SHOWBALLOONTIP, 0, ( LPARAM )&ebt );
+#endif
+ TCHAR* ptszOutputText = (TCHAR*)mir_alloc((limit + 1) * sizeof(TCHAR));
+ GetDlgItemText( this->handle, item, ptszOutputText, limit + 1 );
+ SetDlgItemText( this->handle, item, ptszOutputText );
+ mir_free( ptszOutputText );
+ }
+ mir_free( ptszInputText );
+ }
+}
+
+
+void CSAMWindow::checkItemValidity()
+{
+ COMBOBOXEXITEM cbi = { 0 };
+ cbi.mask = CBEIF_IMAGE;
+ cbi.iItem = SendDlgItemMessage( this->handle, IDC_COMBO, CB_GETCURSEL, 0, 0 );
+ SendDlgItemMessage( this->handle, IDC_COMBO, CBEM_GETITEM, 0, ( LPARAM )&cbi );
+
+ if ( this->item->iIcon != cbi.iImage )
+ ( this->item->iIcon = cbi.iImage ) && ( this->bChanged = TRUE );
+
+ TCHAR tszInputMessage[EXTRASTATUS_MESSAGE_LIMIT];
+
+ GetDlgItemText( this->handle, IDC_MESSAGE, tszInputMessage, EXTRASTATUS_MESSAGE_LIMIT );
+
+ PROTOACCOUNT* pdescr = (PROTOACCOUNT*)CallService(MS_PROTO_GETACCOUNT, 0, (LPARAM)this->parent->protoName);
+ if (pdescr == NULL)
+ return;
+
+ if (lstrcmpA(pdescr->szProtoName, "ICQ") == 0)
+ {
+ int i = SendMessage(this->hCombo, CB_GETCURSEL, 0, 0);
+ lstrcpy(this->item->tszTitle, TranslateTS(xstatus_names[i].ptszTitle));
+ }
+ if (lstrcmpA(pdescr->szProtoName, "JABBER") == 0)
+ {
+ int i = SendMessage(this->hCombo, CB_GETCURSEL, 0, 0);
+ lstrcpy(this->item->tszTitle, TranslateTS(moods_names[i].ptszTitle));
+ }
+ if ( lstrcmp( this->item->tszMessage, tszInputMessage ))
+ ( lstrcpy( this->item->tszMessage, tszInputMessage )) && ( this->bChanged = TRUE );
+}
+
+
+CSListView::CSListView( HWND hwnd, CSWindow* parent )
+{
+ this->handle = hwnd;
+ this->parent = parent;
+
+#if (_WIN32_WINNT >= 0x501)
+ LVGROUP lg = { 0 };
+ lg.cbSize = sizeof(LVGROUP);
+ lg.mask = LVGF_HEADER | LVGF_GROUPID;
+
+ lg.pszHeader = TranslateT("Favourites");
+ lg.iGroupId = 0;
+ ListView_InsertGroup( this->handle, -1, &lg );
+
+ lg.pszHeader = TranslateT("Regular statuses");
+ lg.iGroupId = 1;
+ ListView_InsertGroup( this->handle, -1, &lg );
+ ListView_EnableGroupView( this->handle, TRUE );
+#endif
+
+ LVCOLUMN lvc = { 0 };
+ lvc.mask = LVCF_TEXT | LVCF_FMT | LVCF_WIDTH | LVCF_SUBITEM;
+ lvc.fmt = LVCFMT_LEFT;
+ lvc.cx = 0x00;
+ lvc.pszText = TEXT( "" );
+ lvc.cx = 0x16;
+ SendMessage( this->handle, LVM_INSERTCOLUMN, 0, ( LPARAM )&lvc );
+ lvc.pszText = TranslateT("Title");
+ lvc.cx = 0x64;
+ SendMessage( this->handle, LVM_INSERTCOLUMN, 1, ( LPARAM )&lvc );
+ lvc.pszText = TranslateT("Message");
+ lvc.cx = 0xa8;
+ SendMessage( this->handle, LVM_INSERTCOLUMN, 2, ( LPARAM )&lvc );
+
+// ListView_SetExtendedListViewStyle( this->handle, LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_HEADERDRAGDROP );
+#if (_WIN32_IE >= 0x0400)
+ ListView_SetExtendedListViewStyleEx( this->handle, 0, LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_HEADERDRAGDROP | LVS_EX_INFOTIP );
+#endif
+ ListView_SetImageList( this->handle, this->parent->icons, LVSIL_SMALL );
+}
+
+
+void CSListView::addItem( StatusItem* item, int itemNumber )
+{
+ LVITEM lvi = { 0 };
+ lvi.mask = LVIF_IMAGE | LVIF_GROUPID | LVIF_PARAM;
+ lvi.cchTextMax = 256;
+ lvi.iItem = ListView_GetItemCount( this->handle );
+ lvi.lParam = itemNumber;
+#if ( WINVER >= 0x501 )
+ lvi.iGroupId = ( item->bFavourite == TRUE ) ? 0 : 1;
+#endif
+
+ // first column
+ lvi.iSubItem = 0;
+ lvi.iImage = item->iIcon; // use selected xicon
+ SendMessage( this->handle, LVM_INSERTITEM, 0, ( LPARAM )&lvi );
+
+ // second column
+ lvi.mask = LVIF_TEXT;
+ lvi.iSubItem = 1;
+ lvi.pszText = item->tszTitle;
+ SendMessage( this->handle, LVM_SETITEM, 0, ( LPARAM )&lvi );
+
+ // third column
+ lvi.iSubItem = 2;
+ lvi.pszText = item->tszMessage;
+ SendMessage( this->handle, LVM_SETITEM, 0, ( LPARAM )&lvi );
+}
+
+
+void CSListView::initItems( ListItem< StatusItem >* items )
+{
+ ListItem< StatusItem >* help = items;
+ for ( int i = 0; help != NULL; help = help->next, i++ )
+ if ( parent->itemPassedFilter( help ))
+ addItem( help->item, i );
+}
+
+
+void CSListView::reinitItems( ListItem< StatusItem >* items )
+{
+ EnableWindow( this->handle, FALSE );
+ this->removeItems( );
+ this->initItems( items );
+ EnableWindow( this->handle, TRUE );
+}
+
+
+void CSListView::removeItems( )
+{
+ ListView_DeleteAllItems( this->handle );
+}
+
+
+int CSListView::getPositionInList( )
+{
+ LVITEM lvi = { 0 };
+ lvi.iItem = ListView_GetSelectedItemMacro( this->parent->listview->handle );
+ lvi.iSubItem = 0;
+ lvi.mask = LVIF_PARAM;
+ ListView_GetItem( this->parent->listview->handle, &lvi );
+ return lvi.lParam;
+}
+
+
+void CSListView::setFullFocusedSelection( int selection )
+{
+ ListView_SetItemState( this->handle, -1, 0, LVIS_SELECTED );
+ ListView_EnsureVisible( this->handle, selection, FALSE );
+ ListView_SetItemState( this->handle, selection, LVIS_SELECTED, LVIS_SELECTED );
+ ListView_SetItemState( this->handle, selection, LVIS_FOCUSED , LVIS_FOCUSED );
+ SetFocus( this->handle );
+}
+
+
+// ====[ THREAD FORK ]========================================================
+
+void ForkThread( pThreadFunc pFunc, void* arg )
+{
+ mir_forkthread( pFunc, arg );
+}
+
+
+// ====[ LIST MANAGEMENT ]====================================================
+
+CSItemsList::CSItemsList(char* protoName)
+{
+ this->list = new List< StatusItem >( this->compareItems );
+ this->loadItems(protoName);
+}
+
+
+CSItemsList::~CSItemsList( )
+{
+ delete this->list;
+}
+
+
+int CSItemsList::compareItems( const StatusItem* p1, const StatusItem* p2 )
+{
+ int favRes = 0, icoRes = 0, ttlRes = 0, msgRes = 0;
+
+ if ( p1->bFavourite < p2->bFavourite )
+ favRes = 1;
+ else if ( p1->bFavourite > p2->bFavourite )
+ favRes = -1;
+
+ int result;
+ if ( p1->iIcon > p2->iIcon )
+ icoRes = 1;
+ else if ( p1->iIcon < p2->iIcon )
+ icoRes = -1;
+
+ result = lstrcmp( p1->tszTitle, p2->tszTitle );
+ ttlRes = result;
+
+ result = lstrcmp( p1->tszMessage, p2->tszMessage );
+ msgRes = result;
+
+ if ( !icoRes && !ttlRes && !msgRes )
+ return 0;
+
+ if ( favRes != 0 )
+ return favRes;
+ if ( icoRes != 0 )
+ return icoRes;
+ if ( ttlRes != 0 )
+ return ttlRes;
+ if ( msgRes != 0 )
+ return msgRes;
+
+ return 0;
+}
+
+
+void CSItemsList::loadItems(char* protoName)
+{
+ char dbSetting[32];
+ mir_snprintf(dbSetting, SIZEOF(dbSetting), "%s_ItemsCount", protoName);
+ unsigned int itemsCount = getWord(dbSetting, DEFAULT_ITEMS_COUNT);
+
+ for (unsigned int i = 1; i <= itemsCount; i++)
+ {
+ StatusItem* item = new StatusItem();
+ DBVARIANT dbv = {DBVT_TCHAR};
+ mir_snprintf(dbSetting, SIZEOF(dbSetting), "%s_Item%dIcon", protoName, i);
+ item->iIcon = getByte(dbSetting, DEFAULT_ITEM_ICON);
+ mir_snprintf(dbSetting, SIZEOF(dbSetting), "%s_Item%dTitle", protoName, i);
+ getTString(dbSetting, &dbv);
+ lstrcpy(item->tszTitle, dbv.ptszVal);
+ mir_snprintf(dbSetting, SIZEOF(dbSetting), "%s_Item%dMessage", protoName, i);
+ getTString(dbSetting, &dbv);
+ lstrcpy(item->tszMessage, dbv.ptszVal);
+ mir_snprintf(dbSetting, SIZEOF(dbSetting), "%s_Item%dFavourite", protoName, i);
+ item->bFavourite = (BOOL)getByte(dbSetting, DEFAULT_ITEM_IS_FAVOURITE);
+ this->list->add(item);
+ }
+}
+
+
+void CSItemsList::saveItems(char* protoName)
+{
+ unsigned int i;
+ char dbSetting[32];
+ mir_snprintf(dbSetting, SIZEOF(dbSetting), "%s_ItemsCount", protoName);
+ unsigned int oldItemsCount = getWord(dbSetting, DEFAULT_ITEMS_COUNT);
+
+ for (i = 1; i <= this->list->getCount(); i++)
+ {
+ StatusItem* item = this->list->get( i - 1 );
+ mir_snprintf(dbSetting, SIZEOF(dbSetting), "%s_Item%dIcon", protoName, i);
+ setByte(dbSetting, item->iIcon);
+ mir_snprintf(dbSetting, SIZEOF(dbSetting), "%s_Item%dTitle", protoName, i);
+ setTString(dbSetting, item->tszTitle);
+ mir_snprintf(dbSetting, SIZEOF(dbSetting), "%s_Item%dMessage", protoName, i);
+ setTString(dbSetting, item->tszMessage);
+ mir_snprintf(dbSetting, SIZEOF(dbSetting), "%s_Item%dFavourite", protoName, i);
+ setByte(dbSetting, item->bFavourite);
+ }
+
+ mir_snprintf(dbSetting, SIZEOF(dbSetting), "%s_ItemsCount", protoName);
+ setWord(dbSetting, this->list->getCount());
+
+ for ( ; i <= oldItemsCount; i++)
+ {
+ mir_snprintf(dbSetting, SIZEOF(dbSetting), "%s_Item%dIcon", protoName, i);
+ deleteSetting(dbSetting);
+ mir_snprintf(dbSetting, SIZEOF(dbSetting), "%s_Item%dTitle", protoName, i);
+ deleteSetting(dbSetting);
+ mir_snprintf(dbSetting, SIZEOF(dbSetting), "%s_Item%dMessage", protoName, i);
+ deleteSetting(dbSetting);
+ mir_snprintf(dbSetting, SIZEOF(dbSetting), "%s_Item%dFavourite", protoName, i);
+ deleteSetting(dbSetting);
+ }
+}
+
+
+// ====[ PROCEDURES ]=========================================================
+
+INT_PTR CALLBACK CSWindowProc( HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam )
+{
+ CSWindow* csw = ( CSWindow* )GetWindowLongPtr( hwnd, GWLP_USERDATA );
+
+ switch ( message )
+ {
+
+ case WM_INITDIALOG:
+ csw = ( CSWindow* )lparam;
+ SetWindowLongPtr( hwnd, GWLP_USERDATA, lparam );
+ csw->handle = hwnd;
+ csw->initIcons();
+ csw->initButtons( );
+ csw->listview = new CSListView( GetDlgItem( hwnd, IDC_CSLIST ), csw );
+ csw->listview->initItems( csw->itemslist->list->getListHead( ));
+ csw->toggleButtons( );
+ csw->toggleEmptyListMessage( );
+ csw->loadWindowPosition( );
+ SetWindowText(hwnd, TranslateT(MODULENAME));
+ TranslateDialogDefault(hwnd);
+ return TRUE;
+
+ case WM_COMMAND:
+ switch ( LOWORD( wparam ))
+ {
+ case IDC_MODIFY:
+ case IDC_ADD:
+ csw->addModifyDlg = new CSAMWindow( LOWORD( wparam ), csw );
+ csw->addModifyDlg->exec( );
+ if ( csw->addModifyDlg->bChanged )
+ {
+ if ( LOWORD( wparam ) == IDC_MODIFY )
+ csw->itemslist->list->remove( csw->listview->getPositionInList( ));
+
+ int selection = csw->itemslist->list->add( csw->addModifyDlg->item );
+ csw->bSomethingChanged = TRUE;
+ csw->listview->reinitItems( csw->itemslist->list->getListHead( ));
+ csw->listview->setFullFocusedSelection( selection );
+ csw->toggleButtons( );
+ csw->toggleEmptyListMessage( );
+ }
+ delete csw->addModifyDlg;
+ break;
+
+ case IDC_REMOVE:
+ if ( getByte( "ConfirmDeletion", DEFAULT_PLUGIN_CONFIRM_ITEMS_DELETION ))
+ if ( MessageBox( hwnd, TranslateT("Do you really want to delete selected item?"), TranslateT(MODULENAME), MB_YESNO | MB_DEFBUTTON2 | MB_ICONQUESTION ) == IDNO )
+ break;
+ csw->itemslist->list->remove( csw->listview->getPositionInList( ));
+ csw->bSomethingChanged = TRUE;
+ csw->listview->reinitItems( csw->itemslist->list->getListHead( ));
+ csw->toggleButtons( );
+ csw->toggleEmptyListMessage( );
+ break;
+
+ case IDC_FAVOURITE:
+ {
+ int selection = csw->listview->getPositionInList( );
+ StatusItem* f = new StatusItem( *csw->itemslist->list->get( selection ));
+ f->bFavourite = ! f->bFavourite;
+ csw->itemslist->list->remove( selection );
+ selection = csw->itemslist->list->add( f );
+ csw->bSomethingChanged = TRUE;
+ csw->listview->reinitItems( csw->itemslist->list->getListHead( ));
+ csw->listview->setFullFocusedSelection( selection );
+ csw->toggleButtons( );
+ }
+ break;
+
+ case IDC_UNDO:
+ {
+ csw->itemslist->list->destroy( );
+ csw->itemslist->loadItems(csw->protoName);
+ csw->bSomethingChanged = FALSE;
+ csw->listview->reinitItems( csw->itemslist->list->getListHead( ));
+ csw->toggleButtons( );
+ csw->toggleEmptyListMessage( );
+ break;
+ }
+
+ case IDC_IMPORT:
+ {
+ int result = getByte( "DeleteAfterImport", DEFAULT_PLUGIN_DELETE_AFTER_IMPORT );
+ if ( result == TRUE )
+ result = IDYES;
+ else
+ {
+ result = MessageBox( hwnd, TranslateT("Do you want old database entries to be deleted after Import?"),
+ TranslateT(MODULENAME), MB_YESNOCANCEL | MB_DEFBUTTON2 | MB_ICONQUESTION );
+ if ( result == IDCANCEL ) break;
+ }
+
+ CSList::ForAllProtocols( CSList::importCustomStatusUIStatusesFromAllProtos, ( void* )&result );
+ csw->bSomethingChanged = TRUE;
+ csw->toggleButtons( );
+ csw->toggleEmptyListMessage( );
+ }
+ break;
+
+ case IDC_FILTER:
+ csw->toggleFilter( );
+ csw->toggleButtons( );
+ break;
+
+ case IDC_FILTER_FIELD:
+ if ( HIWORD( wparam ) == EN_CHANGE )
+ csw->listview->reinitItems( csw->itemslist->list->getListHead( ));
+ break;
+
+ case IDCLOSE: // close and save, no custom status
+ case IDCANCEL: // close and save, no custom status
+ case IDC_CANCEL: // close and save, cancel custom status
+ case IDOK: // close and save, set selected custom status
+ if ( LOWORD( wparam ) == IDOK && csw->toggleButtons( ))
+ cslist->setStatus(IDOK, csw->itemslist->list->get(csw->listview->getPositionInList()), csw->protoName);
+ if ( LOWORD( wparam ) == IDC_CANCEL )
+ cslist->setStatus(IDC_CANCEL, NULL, csw->protoName);
+ if ( csw->bSomethingChanged )
+ if (csw->itemslist!=NULL)
+ csw->itemslist->saveItems(csw->protoName);
+ csw->saveWindowPosition( csw->handle );
+ delete csw->listview;
+ csw->deinitIcons( );
+ cslist->closeList( hwnd );
+ break;
+
+ }
+ return FALSE;
+
+ case WM_NOTIFY:
+ if ( wparam == IDC_CSLIST )
+ {
+ NMHDR* pnmh = ( NMHDR* )lparam;
+ switch ( pnmh->code )
+ {
+
+ case NM_DBLCLK:
+ PostMessage( hwnd, WM_COMMAND, IDOK, 0L );
+ break;
+
+ case LVN_ITEMCHANGED:
+ case NM_CLICK:
+ csw->toggleButtons( );
+ break;
+
+ }
+ }
+ return FALSE;
+
+ case WM_CTLCOLORSTATIC:
+ SetTextColor( ( HDC )wparam, RGB( 174, 174, 174 ));
+ if ( ( ( HWND )lparam == GetDlgItem( hwnd, IDC_NO_ITEMS )) ||
+ ( ( HWND )lparam == GetDlgItem( hwnd, IDC_ADD_SAMPLE )) )
+ return ( BOOL )GetStockObject( WHITE_BRUSH );
+ return FALSE;
+ }
+ return FALSE;
+}
+
+
+INT_PTR CALLBACK CSAMWindowProc( HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam )
+{
+ CSAMWindow* csamw = ( CSAMWindow* )GetWindowLongPtr( hwnd, GWLP_USERDATA );
+
+ switch ( message )
+ {
+
+ case WM_INITDIALOG:
+ {
+ csamw = ( CSAMWindow* )lparam;
+ SetWindowLongPtr( hwnd, GWLP_USERDATA, lparam );
+ csamw->handle = hwnd;
+ EnableWindow( csamw->parent->handle, FALSE );
+ csamw->hCombo = GetDlgItem( hwnd, IDC_COMBO );
+ csamw->hMessage = GetDlgItem( hwnd, IDC_MESSAGE );
+ csamw->setCombo();
+ csamw->fillDialog();
+ TranslateDialogDefault(hwnd);
+ }
+ break;
+
+ case WM_COMMAND:
+ switch ( LOWORD( wparam ))
+ {
+ case IDC_MESSAGE:
+ csamw->checkFieldLimit( HIWORD( wparam ), LOWORD( wparam ));
+ break;
+ case IDOK:
+ csamw->checkItemValidity( );
+ case IDCANCEL:
+ EnableWindow( csamw->parent->handle, TRUE );
+ EndDialog( hwnd, LOWORD( wparam ));
+ break;
+
+ }
+ break;
+
+ }
+ return FALSE;
+}
+
+
+INT_PTR CALLBACK CSOptionsProc( HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam )
+{
+ switch ( message )
+ {
+
+ case WM_INITDIALOG:
+ {
+ CheckDlgButton( hwnd, IDC_CONFIRM_DELETION,
+ getByte( "ConfirmDeletion", DEFAULT_PLUGIN_CONFIRM_ITEMS_DELETION ) ?
+ BST_CHECKED : BST_UNCHECKED );
+
+ CheckDlgButton( hwnd, IDC_DELETE_AFTER_IMPORT,
+ getByte( "DeleteAfterImport", DEFAULT_PLUGIN_DELETE_AFTER_IMPORT ) ?
+ BST_CHECKED : BST_UNCHECKED );
+
+ CheckDlgButton( hwnd, IDC_REMEMBER_POSITION,
+ getByte( "RememberWindowPosition", DEFAULT_REMEMBER_WINDOW_POSITION ) ?
+ BST_CHECKED : BST_UNCHECKED );
+
+ unsigned int protosExtraEnabled = 1;
+
+ CSList::ForAllProtocols( CSList::countPlusModProtos, ( void* )&protosExtraEnabled );
+
+ if ( protosExtraEnabled ) // some protocol(s) allow(s) use of extra icons
+ {
+ EnableWindow( GetDlgItem( hwnd, IDC_ALLOW_EXTRA_ICONS ), TRUE );
+ CheckDlgButton( hwnd, IDC_ALLOW_EXTRA_ICONS, getByte( "AllowExtraIcons",
+ DEFAULT_ALLOW_EXTRA_ICONS ));
+ }
+
+ TranslateDialogDefault(hwnd);
+ }
+ return TRUE;
+
+ case WM_NOTIFY:
+ switch ( ( ( LPNMHDR )lparam )->code )
+ {
+
+ case PSN_APPLY:
+ {
+ setByte( "ConfirmDeletion", IsDlgButtonChecked( hwnd, IDC_CONFIRM_DELETION ) ? 1 : 0 );
+ setByte( "DeleteAfterImport", IsDlgButtonChecked( hwnd, IDC_DELETE_AFTER_IMPORT ) ? 1 : 0 );
+ setByte( "AllowExtraIcons", IsDlgButtonChecked( hwnd, IDC_ALLOW_EXTRA_ICONS ) ? 1 : 0 );
+ setByte( "RememberWindowPosition", IsDlgButtonChecked( hwnd, IDC_REMEMBER_POSITION ) ? 1 : 0 );
+
+ cslist->rebuildMenuItems( );
+ }
+ break;
+
+ }
+ return TRUE;
+
+ }
+ return FALSE;
+}
+
+
+// ====[ HELPERS ]============================================================
+
+HICON LoadIconExEx( const char* IcoLibName, int NonIcoLibIcon )
+{
+ if ( ServiceExists( MS_SKIN2_GETICON )) {
+ char szSettingName[64];
+ mir_snprintf(szSettingName, SIZEOF(szSettingName), "%s_%s", __INTERNAL_NAME, IcoLibName);
+ return ( HICON )CallService( MS_SKIN2_GETICON, 0, ( LPARAM )szSettingName );
+ }
+ else
+ return ( HICON )LoadImage( cslist->handle, MAKEINTRESOURCE( NonIcoLibIcon ), IMAGE_ICON, 0, 0, 0 );
+}
diff --git a/plugins/CSList/src/cslist.h b/plugins/CSList/src/cslist.h
new file mode 100644
index 0000000000..7a4f0f8e75
--- /dev/null
+++ b/plugins/CSList/src/cslist.h
@@ -0,0 +1,665 @@
+/* ========================================================================
+
+ Custom Status List
+ __________________
+
+ Custom Status List plugin for Miranda-IM (www.miranda-im.org)
+ Follower of Custom Status History List by HANAX
+ Copyright © 2006-2008 HANAX
+ Copyright © 2007-2009 jarvis
+
+ 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 : $URL$
+ Revision : $Rev$
+ Last change on : $Date$
+ Last change by : $Author$
+
+ ============================================================================
+
+
+ DESCRIPTION:
+
+ Offers List of your Custom Statuses.
+
+ ============================================================================
+
+// ====[ INCLUDES AND DEFINITIONS ]======================================== */
+
+#ifndef __CSLIST_H
+#define __CSLIST_H 1
+
+
+#define WINVER 0x501
+#define _WIN32_WINNT 0x501
+#define _WIN32_IE 0x600
+
+#define MIRANDA_VER 0x0A00
+
+#pragma warning( disable: 4996 )
+#pragma comment( lib, "comctl32.lib" )
+
+#include <windows.h>
+#include <commctrl.h>
+#include <tchar.h>
+
+#include <win2k.h>
+#include <newpluginapi.h>
+#include <m_database.h>
+#include <m_utils.h>
+#include <m_langpack.h>
+#include <m_clist.h>
+#include <m_clistint.h>
+#include <m_genmenu.h>
+#include <m_skin.h>
+#include <m_icolib.h>
+#include <m_protocols.h>
+#include <m_protosvc.h>
+#include <m_icq.h>
+#include <m_jabber.h>
+#include <m_options.h>
+#include <m_hotkeys.h>
+#include <m_variables.h>
+
+// ====[ BASIC DEFINITIONS ]==================================================
+
+#include "resource.h"
+#include "version.h"
+
+#define MODULENAME "Custom Status List"
+
+// {C8CC7414-6507-4AF6-925A-83C1D2F7BE8C}
+#define PLUGIN_GUUID { 0xc8cc7414, 0x6507, 0x4af6, { 0x92, 0x5a, 0x83, 0xc1, 0xd2, 0xf7, 0xbe, 0x8c } }
+
+// ====[ LIMITS ]=============================================================
+
+#define EXTRASTATUS_TITLE_LIMIT 64 // limit of chars for extra status title
+#define EXTRASTATUS_MESSAGE_LIMIT 2048 // limit of chars for extra status message
+#define XSTATUS_COUNT 32
+#define XSTATUS_COUNT_EXTENDED 37
+#define MOODS_COUNT 84
+
+// ====[ SERVICES ]===========================================================
+
+#define MS_PSEUDO_PROTO_PROTOACCSENUM ( CSList::bAccountsSupported ? MS_PROTO_ENUMACCOUNTS : MS_PROTO_ENUMPROTOCOLS )
+
+// ====[ DEFAULT DB VALUES ]==================================================
+
+#define DEFAULT_ICQ_XSTATUS_ENABLED 1
+#define DEFAULT_PLUGIN_SHOW_RELNOTES 0
+#define DEFAULT_PLUGIN_SHOW_NONSTANDARD_XSTATUSES 1
+#define DEFAULT_PLUGIN_CONFIRM_ITEMS_DELETION 1
+#define DEFAULT_PLUGIN_DELETE_AFTER_IMPORT 0
+#define DEFAULT_ITEMS_COUNT 0
+#define DEFAULT_ITEM_ICON 0
+#define DEFAULT_ITEM_IS_FAVOURITE 0
+#define DEFAULT_ALLOW_EXTRA_ICONS 1
+#define DEFAULT_REMEMBER_WINDOW_POSITION 1
+
+
+// ====[ FUNCTION MACROS ]====================================================
+
+// set which row is selected (cannot be only focused, but fully selected - second param ;))
+#define ListView_GetSelectedItemMacro( hwnd ) ListView_GetNextItem( hwnd, -1, LVNI_FOCUSED | LVNI_SELECTED );
+#ifndef ListView_SetSelectionMark
+ #define ListView_SetSelectionMark( x, y ) 0
+#endif
+
+#define getByte( setting, error ) DBGetContactSettingByte( NULL, __INTERNAL_NAME, setting, error )
+#define setByte( setting, value ) DBWriteContactSettingByte( NULL, __INTERNAL_NAME, setting, value )
+#define getWord( setting, error ) DBGetContactSettingWord( NULL, __INTERNAL_NAME, setting, error )
+#define setWord( setting, value ) DBWriteContactSettingWord( NULL, __INTERNAL_NAME, setting, value )
+#define getDword( setting, error ) DBGetContactSettingDword( NULL, __INTERNAL_NAME, setting, error )
+#define setDword( setting, value ) DBWriteContactSettingDword( NULL, __INTERNAL_NAME, setting, value )
+#define getTString( setting, dest ) DBGetContactSettingTString( NULL, __INTERNAL_NAME, setting, dest )
+#define setTString( setting, value ) DBWriteContactSettingTString( NULL, __INTERNAL_NAME, setting, value )
+#define deleteSetting( setting ) DBDeleteContactSetting( NULL, __INTERNAL_NAME, setting )
+
+// --
+typedef void (__cdecl *pForAllProtosFunc)( char*, void* );
+
+
+// ====[ STRUCTURES ]=========================================================
+
+struct StatusItem { // list item structure
+ int iIcon;
+ TCHAR tszTitle[EXTRASTATUS_TITLE_LIMIT];
+ TCHAR tszMessage[EXTRASTATUS_MESSAGE_LIMIT];
+ BOOL bFavourite;
+
+ StatusItem()
+ {
+ this->iIcon = 0;
+ lstrcpy(this->tszTitle, _T(""));
+ lstrcpy(this->tszMessage, _T(""));
+ this->bFavourite = FALSE;
+ }
+
+ StatusItem( const StatusItem& p )
+ {
+ this->iIcon = p.iIcon;
+ lstrcpy( this->tszTitle, p.tszTitle );
+ lstrcpy( this->tszMessage, p.tszMessage );
+ this->bFavourite = p.bFavourite;
+ }
+
+ ~StatusItem( )
+ {
+ }
+};
+
+static struct CSForm { // icons + buttons
+ int idc;
+ TCHAR* ptszTitle;
+ TCHAR* ptszDescr;
+ char* pszIconIcoLib;
+ int iconNoIcoLib;
+ HANDLE hIcoLibItem;
+
+} forms[] = {
+
+ { -1, LPGENT( "Main Menu" ), LPGENT( "Main Icon" ), "icon", IDI_CSLIST, NULL },
+ { IDC_ADD, LPGENT( "Add new item" ), LPGENT( "Add" ), "add", IDI_ADD, NULL },
+ { IDC_MODIFY, LPGENT( "Modify selected item" ), LPGENT( "Modify" ), "modify", IDI_MODIFY, NULL },
+ { IDC_REMOVE, LPGENT( "Delete selected item" ), LPGENT( "Remove" ), "remove", IDI_REMOVE, NULL },
+ { IDC_FAVOURITE, LPGENT( "Set/unset current item as favorite" ), LPGENT( "Favourite" ), "favourite", IDI_FAVOURITE, NULL },
+ { IDC_UNDO, LPGENT( "Undo changes" ), LPGENT( "Undo changes" ), "undo", IDI_UNDO, NULL },
+ { IDC_IMPORT, LPGENT( "Import statuses from database" ), LPGENT( "Import" ), "import", IDI_IMPORT, NULL },
+ { IDC_FILTER, LPGENT( "Filter list" ), LPGENT( "Filter" ), "filter", IDI_FILTER, NULL },
+ { IDCLOSE, LPGENT( "Close without changing custom status" ), LPGENT( "No change" ), "nochng", IDI_CLOSE, NULL },
+ { IDC_CANCEL, LPGENT( "Clear custom status (reset to None) and close" ), LPGENT( "Clear" ), "clear", IDI_UNSET, NULL },
+ { IDOK, LPGENT( "Set custom status to selected one and close" ), LPGENT( "Set" ), "apply", IDI_APPLY, NULL },
+};
+
+static struct CSXstatus { // combobox xstatus icons
+ int iId;
+ TCHAR* ptszTitle;
+
+} xstatus_names[] = {
+
+ { 1, LPGENT( "Angry" ) },
+ { 2, LPGENT( "Taking a bath" ) },
+ { 3, LPGENT( "Tired" ) },
+ { 4, LPGENT( "Party" ) },
+ { 5, LPGENT( "Drinking beer" ) },
+ { 6, LPGENT( "Thinking" ) },
+ { 7, LPGENT( "Eating" ) },
+ { 8, LPGENT( "Watching TV" ) },
+ { 9, LPGENT( "Meeting" ) },
+ { 10, LPGENT( "Coffee" ) },
+ { 11, LPGENT( "Listening to music" ) },
+ { 12, LPGENT( "Business" ) },
+ { 13, LPGENT( "Shooting" ) },
+ { 14, LPGENT( "Having fun" ) },
+ { 15, LPGENT( "On the phone" ) },
+ { 16, LPGENT( "Gaming" ) },
+ { 17, LPGENT( "Studying" ) },
+ { 18, LPGENT( "Shopping" ) },
+ { 19, LPGENT( "Feeling sick" ) },
+ { 20, LPGENT( "Sleeping" ) },
+ { 21, LPGENT( "Surfing" ) },
+ { 22, LPGENT( "Browsing" ) },
+ { 23, LPGENT( "Working" ) },
+ { 24, LPGENT( "Typing" ) },
+ { 25, LPGENT( "Picnic" ) },
+ { 26, LPGENT( "PDA" ) },
+ { 27, LPGENT( "On the phone" ) },
+ { 28, LPGENT( "I'm high" ) },
+ { 29, LPGENT( "On WC" ) },
+ { 30, LPGENT( "To be or not to be" ) },
+ { 31, LPGENT( "Watching pro7 on TV" ) },
+ { 32, LPGENT( "Love" ) },
+ { 33, LPGENT( "Searching" ) },
+ { 34, LPGENT( "Amorous" ) }, // I don't understand why this falls when 2 same named items appear O_o
+ { 35, LPGENT( "Journal" ) }, // edit: ..and now I REALLY don't understand why it's working now x))
+ { 36, LPGENT( "Sex" ) },
+ { 37, LPGENT( "Smoking" ) }, // -||-
+};
+
+static struct CSMoods { // combobox moods icons
+ int iId;
+ TCHAR* ptszTitle;
+ char* szTag;
+} moods_names[] = {
+ { 1, LPGENT("Afraid"), "afraid" },
+ { 2, LPGENT("Amazed"), "amazed" },
+ { 3, LPGENT("Amorous"), "amorous" },
+ { 4, LPGENT("Angry"), "angry" },
+ { 5, LPGENT("Annoyed"), "annoyed" },
+ { 6, LPGENT("Anxious"), "anxious" },
+ { 7, LPGENT("Aroused"), "aroused" },
+ { 8, LPGENT("Ashamed"), "ashamed" },
+ { 9, LPGENT("Bored"), "bored" },
+ { 10, LPGENT("Brave"), "brave" },
+ { 11, LPGENT("Calm"), "calm" },
+ { 12, LPGENT("Cautious"), "cautious" },
+ { 13, LPGENT("Cold"), "cold" },
+ { 14, LPGENT("Confident"), "confident" },
+ { 15, LPGENT("Confused"), "confused" },
+ { 16, LPGENT("Contemplative"),"contemplative" },
+ { 17, LPGENT("Contented"), "contented" },
+ { 18, LPGENT("Cranky"), "cranky" },
+ { 19, LPGENT("Crazy"), "crazy" },
+ { 20, LPGENT("Creative"), "creative" },
+ { 21, LPGENT("Curious"), "curious" },
+ { 22, LPGENT("Dejected"), "dejected" },
+ { 23, LPGENT("Depressed"), "depressed" },
+ { 24, LPGENT("Disappointed"), "disappointed" },
+ { 25, LPGENT("Disgusted"), "disgusted" },
+ { 26, LPGENT("Dismayed"), "dismayed" },
+ { 27, LPGENT("Distracted"), "distracted" },
+ { 28, LPGENT("Embarrassed"), "embarrassed" },
+ { 29, LPGENT("Envious"), "envious" },
+ { 30, LPGENT("Excited"), "excited" },
+ { 31, LPGENT("Flirtatious"), "flirtatious" },
+ { 32, LPGENT("Frustrated"), "frustrated" },
+ { 33, LPGENT("Grateful"), "grateful" },
+ { 34, LPGENT("Grieving"), "grieving" },
+ { 35, LPGENT("Grumpy"), "grumpy" },
+ { 36, LPGENT("Guilty"), "guilty" },
+ { 37, LPGENT("Happy"), "happy" },
+ { 38, LPGENT("Hopeful"), "hopeful" },
+ { 39, LPGENT("Hot"), "hot" },
+ { 40, LPGENT("Humbled"), "humbled" },
+ { 41, LPGENT("Humiliated"), "humiliated" },
+ { 42, LPGENT("Hungry"), "hungry" },
+ { 43, LPGENT("Hurt"), "hurt" },
+ { 44, LPGENT("Impressed"), "impressed" },
+ { 45, LPGENT("In awe"), "in_awe" },
+ { 46, LPGENT("In love"), "in_love" },
+ { 47, LPGENT("Indignant"), "indignant" },
+ { 48, LPGENT("Interested"), "interested" },
+ { 49, LPGENT("Intoxicated"), "intoxicated" },
+ { 50, LPGENT("Invincible"), "invincible" },
+ { 51, LPGENT("Jealous"), "jealous" },
+ { 52, LPGENT("Lonely"), "lonely" },
+ { 53, LPGENT("Lost"), "lost" },
+ { 54, LPGENT("Lucky"), "lucky" },
+ { 55, LPGENT("Mean"), "mean" },
+ { 56, LPGENT("Moody"), "moody" },
+ { 57, LPGENT("Nervous"), "nervous" },
+ { 58, LPGENT("Neutral"), "neutral" },
+ { 59, LPGENT("Offended"), "offended" },
+ { 60, LPGENT("Outraged"), "outraged" },
+ { 61, LPGENT("Playful"), "playful" },
+ { 62, LPGENT("Proud"), "proud" },
+ { 63, LPGENT("Relaxed"), "relaxed" },
+ { 64, LPGENT("Relieved"), "relieved" },
+ { 65, LPGENT("Remorseful"), "remorseful" },
+ { 66, LPGENT("Restless"), "restless" },
+ { 67, LPGENT("Sad"), "sad" },
+ { 68, LPGENT("Sarcastic"), "sarcastic" },
+ { 69, LPGENT("Satisfied"), "satisfied" },
+ { 70, LPGENT("Serious"), "serious" },
+ { 71, LPGENT("Shocked"), "shocked" },
+ { 72, LPGENT("Shy"), "shy" },
+ { 73, LPGENT("Sick"), "sick" },
+ { 74, LPGENT("Sleepy"), "sleepy" },
+ { 75, LPGENT("Spontaneous"), "spontaneous" },
+ { 76, LPGENT("Stressed"), "stressed" },
+ { 77, LPGENT("Strong"), "strong" },
+ { 78, LPGENT("Surprised"), "surprised" },
+ { 79, LPGENT("Thankful"), "thankful" },
+ { 80, LPGENT("Thirsty"), "thirsty" },
+ { 81, LPGENT("Tired"), "tired" },
+ { 82, LPGENT("Undefined"), "undefined" },
+ { 83, LPGENT("Weak"), "weak" },
+ { 84, LPGENT("Worried"), "worried" },
+};
+// ====[ MY BITCHY LIST IMPLEMENTATION x)) ]==================================
+// TODO: Optimize it all x))
+
+template< class T > struct ListItem
+{
+ T* item;
+ ListItem* next;
+
+ ListItem( )
+ {
+ this->item = NULL;
+ this->next = NULL;
+ }
+
+ ~ListItem( )
+ {
+ delete this->item;
+ }
+
+ ListItem( StatusItem* si )
+ {
+ this->item = si;
+ this->next = NULL;
+ }
+
+ ListItem( const ListItem& p )
+ {
+ this->item = p.item;
+ this->next = NULL;
+ }
+};
+
+
+template< class T > struct List
+{
+private:
+ ListItem< T >* items;
+ unsigned int count;
+
+public:
+ typedef int ( *compareFunc )( const T* p1, const T* p2 );
+ compareFunc compare;
+
+ List( compareFunc compFnc )
+ {
+ this->items = NULL;
+ this->count = 0;
+ this->compare = compFnc;
+ }
+
+ ~List( )
+ {
+ this->destroy( );
+ }
+
+ ListItem< T >* getListHead( )
+ {
+ return items;
+ }
+
+ unsigned int getCount( )
+ {
+ return count;
+ }
+
+ int add( T* csi )
+ {
+ int position = 0;
+ ListItem< T >* item = new ListItem< T >( csi );
+ if ( this->items == NULL )
+ this->items = item;
+ else
+ {
+ ListItem< T >* help = item;
+ item->next = items;
+ while ( help->next != NULL )
+ {
+ int cmp = compare( item->item, help->next->item );
+ if ( cmp == 1 )
+ help = help->next;
+ else if ( cmp == 0 )
+ {
+ delete item;
+ return -1;
+ }
+ else
+ break;
+ position++;
+ }
+ if ( help != item )
+ {
+ item->next = help->next;
+ help->next = item;
+ }
+ else
+ items = item;
+ }
+ this->count++;
+ return position;
+ }
+
+ int remove( const unsigned int item )
+ {
+ int position = 0;
+ if ( item < 0 || item >= this->count )
+ return -1;
+
+ ListItem< T >* help = items;
+ ListItem< T >* removed;
+ if ( item == 0 )
+ {
+ items = items->next;
+ removed = help;
+ }
+ else
+ {
+ for ( unsigned int i = 0; i < item - 1; i++ )
+ {
+ help = help->next;
+ position++;
+ }
+ removed = help->next;
+ help->next = help->next->next;
+ }
+ delete removed;
+ this->count--;
+ return position;
+ }
+
+ T* get( const unsigned int item )
+ {
+ ListItem< T >* help = items;
+ for ( unsigned int i = 0; i < item; i++ )
+ help = help->next;
+ return help->item;
+ }
+
+ T* operator[]( const unsigned int item )
+ {
+ return get( item );
+ }
+
+ void destroy( )
+ {
+ while ( this->count > 0 )
+ this->remove( 0 );
+ }
+};
+
+
+// ====[ CLASSING -- FUNNY STUFF :) ]=========================================
+
+struct CSList;
+struct CSWindow;
+struct CSAMWindow;
+struct CSItemsList;
+struct CSListView;
+
+// --------
+
+struct CSListView
+{
+ HWND handle;
+ CSWindow* parent;
+
+ CSListView( HWND, CSWindow* );
+
+ void addItem( StatusItem* item, int itemNumber );
+ void initItems( ListItem< StatusItem >* items );
+ void reinitItems( ListItem< StatusItem >* items );
+ void removeItems( );
+ int getPositionInList( );
+ void setFullFocusedSelection( int selection );
+};
+
+
+struct CSItemsList
+{
+ List< StatusItem >* list;
+
+ static int compareItems( const StatusItem* p1, const StatusItem* p2 );
+ void loadItems(char* protoName);
+ void saveItems(char* protoName);
+
+ CSItemsList(char* protoName);
+ ~CSItemsList();
+};
+
+
+struct CSAMWindow
+{
+ WORD action;
+ StatusItem* item;
+ CSWindow* parent;
+ BOOL bChanged;
+
+ HWND handle;
+ HWND hCombo;
+ HWND hMessage;
+
+ CSAMWindow( WORD action, CSWindow* parent );
+ ~CSAMWindow( );
+
+ void exec( );
+ void setCombo( );
+ void fillDialog( );
+ void checkFieldLimit( WORD action, WORD item );
+ void checkItemValidity();
+};
+
+
+struct CSWindow
+{
+ HWND handle;
+ BOOL bExtraIcons;
+ CSItemsList* itemslist;
+ CSListView* listview;
+ CSAMWindow* addModifyDlg;
+ HIMAGELIST icons;
+ BOOL bSomethingChanged;
+ TCHAR* filterString;
+ char* protoName;
+ CSWindow(char* protoName);
+ ~CSWindow();
+
+ void initIcons( );
+ void deinitIcons( );
+ void initButtons( );
+ static void __cdecl showWindow( void* arg );
+ static void __cdecl closeWindow( void* arg );
+ void loadWindowPosition( );
+ BOOL toggleButtons( );
+ void toggleEmptyListMessage( );
+ void toggleFilter( );
+ BOOL itemPassedFilter( ListItem< StatusItem >* li );
+
+ void __inline saveWindowPosition( HWND hwnd )
+ {
+ if ( getByte( "RememberWindowPosition", DEFAULT_REMEMBER_WINDOW_POSITION ) == TRUE )
+ {
+ RECT rect = { 0 };
+ GetWindowRect( hwnd, &rect );
+ setWord( "PositionX", rect.left );
+ setWord( "PositionY", rect.top );
+ }
+ }
+};
+
+
+struct CSList
+{
+ // global variables
+ static HINSTANCE handle;
+ static DWORD dwMirandaVersion;
+ static BOOL bUnicodeCore;
+ static BOOL bAccountsSupported;
+
+ // class components
+ CSWindow* mainWindow;
+
+ // events
+ HANDLE hHookOnPluginsLoaded;
+ HANDLE hHookOnOptionsInit;
+ HANDLE hHookOnDBSettingChanged;
+ HANDLE hHookOnStatusMenuBuild;
+
+ // services
+ HANDLE hServiceShowList;
+
+ CSList( );
+ ~CSList( );
+
+ // event functions
+ static int postLoading( WPARAM, LPARAM );
+ static int initOptions( WPARAM, LPARAM );
+ static int respondDBChange( WPARAM, LPARAM );
+ static int createMenuItems( WPARAM, LPARAM );
+
+ // service functions
+ static INT_PTR __cdecl showList(WPARAM, LPARAM, LPARAM);
+ void closeList( HWND );
+
+ // protocols enumeration related functions
+ static void ForAllProtocols( pForAllProtosFunc pFunc, void* arg );
+ static void __cdecl addProtoStatusMenuItem( char* protoName, void* arg );
+ static void __cdecl countProtos( char* protoName, void* arg );
+ static void __cdecl countPlusModProtos( char* protoName, void* arg );
+ static void __cdecl importCustomStatusUIStatusesFromAllProtos( char* protoName, void* arg );
+
+ // other functions
+ void initIcoLib( );
+ void registerHotkeys(char buf[200], TCHAR* accName, int Number);
+ void rebuildMenuItems( );
+ void setStatus(WORD code, StatusItem* item, char* protoName);
+};
+
+HINSTANCE CSList::handle = NULL;
+DWORD CSList::dwMirandaVersion = 0x00000000;
+BOOL CSList::bUnicodeCore = FALSE;
+BOOL CSList::bAccountsSupported = FALSE;
+
+// ====[ GLOBALS ]============================================================
+
+CSList* cslist = NULL;
+
+// ====[ INIT STUFF ]=========================================================
+
+BOOL WINAPI DllMain( HINSTANCE, DWORD, LPVOID );
+
+extern "C" __declspec( dllexport ) PLUGININFOEX* MirandaPluginInfoEx( DWORD );
+
+extern "C" __declspec( dllexport ) int Load(void);
+extern "C" __declspec( dllexport ) int Unload( void );
+
+
+// ====[ THREAD FORK ]========================================================
+
+void ForkThread( pThreadFunc pFunc, void* arg );
+
+
+// ====[ PROCEDURES ]=========================================================
+
+INT_PTR CALLBACK CSWindowProc( HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam );
+INT_PTR CALLBACK CSAMWindowProc( HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam );
+INT_PTR CALLBACK CSRNWindowProc( HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam );
+INT_PTR CALLBACK CSOptionsProc( HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam );
+
+
+// ====[ HELPERS ]============================================================
+
+HICON LoadIconExEx( const char*, int );
+
+void __fastcall SAFE_FREE(void** p)
+{
+ if (*p)
+ {
+ free(*p);
+ *p = NULL;
+ }
+}
+
+
+#endif /* __CSLIST_H */
diff --git a/plugins/CSList/src/legacy.h b/plugins/CSList/src/legacy.h
new file mode 100644
index 0000000000..8ef63089d7
--- /dev/null
+++ b/plugins/CSList/src/legacy.h
@@ -0,0 +1,87 @@
+/*
+
+ FILE INFO: Legacy functions of older Custom Status List versions
+
+*/
+
+int cslist_import_v2_status_items( );
+int cslist_parse_row( TCHAR *row, int ord );
+
+int cslist_import_v2_status_items( )
+{
+ // get DB string, parse to statuses, add by helpItem
+ DBVARIANT dbv = { DBVT_TCHAR };
+ int parseResult;
+ int dbLoadResult;
+ const TCHAR* rowDelim = _T( "" ); // new line
+ TCHAR *row = NULL;
+
+ dbLoadResult = getTString( "listhistory", &dbv );
+ if ( dbv.ptszVal )
+ {
+ int i = getByte( "ItemsCount", DEFAULT_ITEMS_COUNT );
+ row = _tcstok( dbv.ptszVal, rowDelim );
+ while( row != NULL ) {
+ i++;
+ // process current row..
+ parseResult = cslist_parse_row( row, i );
+ // ..and go to the other, while some remains
+ row = _tcstok( NULL, rowDelim );
+ }
+ setByte( "ItemsCount", i );
+ }
+ //free( rowDelim );
+ //free( row );
+ return 0;
+}
+
+int cslist_parse_row( TCHAR *row, int ord ) // parse + helpItem
+{
+ int pIconInt;
+ TCHAR pIcon[4], pTitle[EXTRASTATUS_TITLE_LIMIT+2], pMsg[EXTRASTATUS_MESSAGE_LIMIT+2], pFav[4];
+ TCHAR scanfFormat[64];
+
+ lstrcpy( pTitle, _T( "" ));
+ lstrcpy( pMsg, _T( "" ));
+
+ // database row format: "%2[^]%64[^]%2048[^]%2[^]"
+
+ mir_sntprintf(
+ scanfFormat,
+ sizeof( scanfFormat ),
+ _T( "%%%d[^]%%%d[^]%%%d[^]%%%d[^]" ), // %% makes %, %d makes number :)
+ 2,
+ EXTRASTATUS_TITLE_LIMIT,
+ EXTRASTATUS_MESSAGE_LIMIT,
+ 2
+ );
+
+ _tcscanf( row, scanfFormat, pIcon, pTitle, pMsg, pFav );
+
+ if ( lstrlen( pTitle ) + lstrlen( pMsg ) > 0 )
+ {
+ char dbSetting[32];
+ pIconInt = _ttoi( pIcon );
+ mir_snprintf( dbSetting, sizeof( dbSetting ), "Item%dIcon", ord );
+ setByte( dbSetting, pIconInt );
+ mir_snprintf( dbSetting, sizeof( dbSetting ), "Item%dTitle", ord );
+ setTString( dbSetting, pTitle );
+ mir_snprintf( dbSetting, sizeof( dbSetting ), "Item%dMessage", ord );
+ setTString( dbSetting, pMsg );
+ mir_snprintf( dbSetting, sizeof( dbSetting ), "Item%dFavourite", ord );
+ setByte( dbSetting, 0 );
+ }
+ else {
+ return FALSE;
+ }
+ return TRUE;
+}
+
+
+void MessageBoxInt( int value1, int value2 )
+{
+ TCHAR buf1[64], buf2[64];
+ mir_sntprintf( buf1, SIZEOF( buf1 ), TEXT( "%d" ), value1 );
+ mir_sntprintf( buf2, SIZEOF( buf2 ), TEXT( "%d" ), value2 );
+ MessageBox( NULL, buf2, buf1, MB_OK );
+}
diff --git a/plugins/CSList/src/resource.h b/plugins/CSList/src/resource.h
new file mode 100644
index 0000000000..cec164739d
--- /dev/null
+++ b/plugins/CSList/src/resource.h
@@ -0,0 +1,49 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by cslist.rc
+//
+#define IDCLOSE 8
+#define IDC_CANCEL 9
+#define IDD_CSLIST 101
+#define IDD_ADDMODIFY 102
+#define IDD_OPTIONS 103
+#define IDI_CSLIST 121
+#define IDI_ADD 122
+#define IDI_MODIFY 123
+#define IDI_REMOVE 124
+#define IDI_FAVOURITE 125
+#define IDI_UNDO 126
+#define IDI_GLOBAL 127
+#define IDI_FILTER 128
+#define IDI_CLOSE 129
+#define IDI_UNSET 130
+#define IDI_APPLY 131
+#define IDI_IMPORT 132
+#define IDC_CSLIST 1001
+#define IDC_FILTER_FIELD 1011
+#define IDC_ADD_SAMPLE 1012
+#define IDC_NO_ITEMS 1013
+#define IDC_ADD 1021
+#define IDC_MODIFY 1022
+#define IDC_REMOVE 1023
+#define IDC_FAVOURITE 1024
+#define IDC_UNDO 1025
+#define IDC_FILTER 1027
+#define IDC_COMBO 1041
+#define IDC_MESSAGE 1042
+#define IDC_CONFIRM_DELETION 1051
+#define IDC_DELETE_AFTER_IMPORT 1052
+#define IDC_IMPORT 1071
+#define IDC_ALLOW_EXTRA_ICONS 1204
+#define IDC_REMEMBER_POSITION 1207
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 104
+#define _APS_NEXT_COMMAND_VALUE 40003
+#define _APS_NEXT_CONTROL_VALUE 1209
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/plugins/CSList/src/strpos.h b/plugins/CSList/src/strpos.h
new file mode 100644
index 0000000000..210bfddf0a
--- /dev/null
+++ b/plugins/CSList/src/strpos.h
@@ -0,0 +1,70 @@
+/*
+ * strpos.c - Returns the offset of a string in a substring.
+ *
+ * Copyright (c) 2001, 2002 Andre Guibert de Bruet. <andre@siliconlandmark.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification, immediately at the beginning of the file.
+ * 2. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+/*
+ * You might want to place this next block in a header file somewhere:
+ */
+
+
+# ifndef TCHAR
+# define TCHAR wchar_t
+# endif /* TCHAR */
+# define STRING wchar_t *
+
+
+
+
+int strpos( STRING haystack, STRING needle )
+{
+ STRING pDest;
+ int position;
+
+#ifdef DEBUG_VERBOSE
+ TCHAR lpBuf[1024];
+#endif /* def DEBUG_VERBOSE */
+
+ pDest = (STRING) wcsstr( haystack, needle );
+
+
+ if ( pDest )
+ position = pDest - haystack;
+ else
+ {
+#ifdef DEBUG_VERBOSE
+ printf( L"strpos(): Could not find '%s' in '%s'.\tFAIL.", needle, haystack );
+#endif /* def DEBUG_VERBOSE */
+ return -1;
+ }
+
+#ifdef DEBUG_VERBOSE
+ printf( L"strpos(): Found '%s' at position: %d.\t\tOK.", needle, position );
+#endif /* def DEBUG_VERBOSE */
+
+ return position;
+}