summaryrefslogtreecommitdiff
path: root/plugins/UserInfoEx/Flags
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/UserInfoEx/Flags')
-rw-r--r--plugins/UserInfoEx/Flags/svc_countrylistext.cpp326
-rw-r--r--plugins/UserInfoEx/Flags/svc_countrylistext.h39
-rw-r--r--plugins/UserInfoEx/Flags/svc_flags.cpp765
-rw-r--r--plugins/UserInfoEx/Flags/svc_flags.h102
-rw-r--r--plugins/UserInfoEx/Flags/svc_flagsicons.cpp457
-rw-r--r--plugins/UserInfoEx/Flags/svc_flagsicons.h43
6 files changed, 1732 insertions, 0 deletions
diff --git a/plugins/UserInfoEx/Flags/svc_countrylistext.cpp b/plugins/UserInfoEx/Flags/svc_countrylistext.cpp
new file mode 100644
index 0000000000..54fcb86675
--- /dev/null
+++ b/plugins/UserInfoEx/Flags/svc_countrylistext.cpp
@@ -0,0 +1,326 @@
+/*
+UserinfoEx plugin for Miranda IM
+
+Copyright:
+ 2006-2010 DeathAxe, Yasnovidyashii, Merlin, K. Romanov, Kreol
+
+part of this code based on:
+Miranda IM Country Flags Plugin Copyright 2006-2007 H. Herkenrath
+
+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 : $HeadURL: https://userinfoex.googlecode.com/svn/trunk/Flags/svc_countrylistext.cpp $
+Revision : $Revision: 199 $
+Last change on : $Date: 2010-09-22 17:21:44 +0400 (Ср, 22 сен 2010) $
+Last change by : $Author: ing.u.horn $
+
+===============================================================================
+*/
+
+#include "..\commonheaders.h"
+#include "svc_countrylistext.h"
+
+/************************* Services *******************************/
+
+static struct CountryListEntry countries[]={
+ {0 ,"Unspecified"},
+ {9999,"Other"},
+ {0xFFFF,"Unknown"},
+ {93 ,"Afghanistan"},
+ {355 ,"Albania"},
+ {213 ,"Algeria"},
+ {376 ,"Andorra"},
+ {244 ,"Angola"},
+ {1264,"Anguilla"}, /* change county code to NANP (from 101) */
+ {1268,"Antigua and Barbuda"}, /* change county code to NANP (from 1021) */
+// {5902,"Antilles"}, /* removed: it is not a country, it's a group of islands from diffrent countries (all are included in the list)*/
+ {54 ,"Argentina"},
+ {374 ,"Armenia"},
+ {297 ,"Aruba"},
+ {61 ,"Australia"},
+ {6720 ,"Australia, Antarctic Territory"}, /* added country code 672(0)*/
+ {614 ,"Australia, Christmas Island"}, /* rename (from Christmas Island) and change to official county code 61(4) (from 672) */
+ {61891,"Australia, Cocos (Keeling) Islands"}, /* rename and change to official county code 61(891) (from 6102) */
+ {6723 ,"Australia, Norfolk Island"}, /* rename (from Norfolk Island) and change to official county code 672(3) (from 6722) */
+ {43 ,"Austria"},
+ {994 ,"Azerbaijan"},
+ {1242,"Bahamas"}, /* change county code to NANP (from 103) */
+ {973 ,"Bahrain"},
+ {880 ,"Bangladesh"},
+ {1246,"Barbados"}, /* change county code to NANP (from 103) */
+// {120 ,"Barbuda"}, /* removed: it is not a country and no special island, see Antigua and Barbuda*/
+ {375 ,"Belarus"},
+ {32 ,"Belgium"},
+ {501 ,"Belize"},
+ {229 ,"Benin"},
+ {1441,"Bermuda"}, /* change county code to NANP (from 105) */
+ {975 ,"Bhutan"},
+ {591 ,"Bolivia"},
+ {387 ,"Bosnia and Herzegovina"},
+ {267 ,"Botswana"},
+ {55 ,"Brazil"},
+ {673 ,"Brunei"},
+ {359 ,"Bulgaria"},
+ {226 ,"Burkina Faso"},
+ {257 ,"Burundi"},
+ {855 ,"Cambodia"},
+ {237 ,"Cameroon"},
+ {1002,"Canada"}, /* change county code to NANP (from 107 to virtual 1(002) -> reflect NANP*/
+ {238 ,"Cape Verde Islands"},
+ {1345,"Cayman Islands"}, /* change county code to NANP (from 108) */
+ {236 ,"Central African Republic"},
+ {235 ,"Chad"},
+ {56 ,"Chile, Republic of"},
+ {86 ,"China"},
+// {6101,"Cocos-Keeling Islands"}, /* removed (double): see Australia, Cocos (Keeling) Islands */
+ {57 ,"Colombia"},
+ {269 ,"Comoros"}, /* change county code (from 2691) */
+ {243 ,"Congo, Democratic Republic of (Zaire)"},
+ {242 ,"Congo, Republic of the"},
+ {682 ,"Cook Islands"},
+ {506 ,"Costa Rica"},
+ {225 ,"Cote d'Ivoire (Ivory Coast)"},
+ {385 ,"Croatia"},
+ {53 ,"Cuba"},
+ {357 ,"Greek, Republic of South Cyprus"}, /* rename coz Turkey, Republic of Northern Cyprus */
+ {420 ,"Czech Republic"},
+ {45 ,"Denmark"},
+ {246 ,"Diego Garcia"},
+ {253 ,"Djibouti"},
+ {1767,"Dominica"}, /* change county code to NANP (from 109) */
+ {1809,"Dominican Republic"}, /* change county code to NANP 809, 829, 849 (from 110) */
+ {593 ,"Ecuador"},
+ {20 ,"Egypt"},
+ {503 ,"El Salvador"},
+ {240 ,"Equatorial Guinea"},
+ {291 ,"Eritrea"},
+ {372 ,"Estonia"},
+ {251 ,"Ethiopia"},
+ {3883,"Europe"}, /* add county code +388 3 official European Telephony Numbering Space*/
+ {298 ,"Faeroe Islands"},
+ {500 ,"Falkland Islands"},
+ {679 ,"Fiji"},
+ {358 ,"Finland"},
+ {33 ,"France"},
+ {5901,"French Antilles"},
+ {594 ,"French Guiana"},
+ {689 ,"French Polynesia"},
+ {241 ,"Gabon"},
+ {220 ,"Gambia"},
+ {995 ,"Georgia"},
+ {49 ,"Germany"},
+ {233 ,"Ghana"},
+ {350 ,"Gibraltar"},
+ {30 ,"Greece"},
+ {299 ,"Greenland"},
+ {1473,"Grenada"}, /* change county code to NANP (from 111) */
+ {590 ,"Guadeloupe"},
+ {1671,"Guam, US Territory of"}, /* change county code to NANP (from 671) */
+ {502 ,"Guatemala"},
+ {224 ,"Guinea"},
+ {245 ,"Guinea-Bissau"},
+ {592 ,"Guyana"},
+ {509 ,"Haiti"},
+ {504 ,"Honduras"},
+ {852 ,"Hong Kong"},
+ {36 ,"Hungary"},
+ {354 ,"Iceland"},
+ {91 ,"India"},
+ {62 ,"Indonesia"},
+ {98 ,"Iran (Islamic Republic of)"},
+ {964 ,"Iraq"},
+ {353 ,"Ireland"},
+ {972 ,"Israel"},
+ {39 ,"Italy"},
+ {1876,"Jamaica"}, /* change county code to NANP (from 112) */
+ {81 ,"Japan"},
+ {962 ,"Jordan"},
+ {705 ,"Kazakhstan"},
+ {254 ,"Kenya"},
+ {686 ,"Kiribati"},
+ {850 ,"Korea, North"},
+ {82 ,"Korea, South"},
+ {965 ,"Kuwait"},
+ {996 ,"Kyrgyzstan"}, /* change county code (from 706) */
+ {856 ,"Laos"},
+ {371 ,"Latvia"},
+ {961 ,"Lebanon"},
+ {266 ,"Lesotho"},
+ {231 ,"Liberia"},
+ {218 ,"Libyan Arab Jamahiriya"},
+ {423 ,"Liechtenstein"}, /* change county code (from 4101) */
+ {370 ,"Lithuania"},
+ {352 ,"Luxembourg"},
+ {853 ,"Macau"},
+ {389 ,"Macedonia, Republic of"}, /* rename coz war */
+ {261 ,"Madagascar"},
+ {265 ,"Malawi"},
+ {60 ,"Malaysia"},
+ {960 ,"Maldives"},
+ {223 ,"Mali"},
+ {356 ,"Malta"},
+ {692 ,"Marshall Islands"},
+ {596 ,"Martinique"},
+ {222 ,"Mauritania"},
+ {230 ,"Mauritius"},
+ {262 ,"Mayotte Island"}, /* change county code coz bug (from 269) */
+ {52 ,"Mexico"},
+ {691 ,"Micronesia, Federated States of"},
+ {373 ,"Moldova, Republic of"},
+ {377 ,"Monaco"},
+ {976 ,"Mongolia"},
+ {1664,"Montserrat"}, /* change county code to NANP (from 113) */
+ {212 ,"Morocco"},
+ {258 ,"Mozambique"},
+ {95 ,"Myanmar"},
+ {264 ,"Namibia"},
+ {674 ,"Nauru"},
+ {977 ,"Nepal"},
+ {31 ,"Netherlands"},
+ {599 ,"Netherlands Antilles"}, /* dissolved 2010 */
+ {5995 ,"St. Maarten"}, /* add new country in 2010 (from Netherlands Antilles) */
+ {5999 ,"Curacao"}, /* add new country in 2010 (from Netherlands Antilles) */
+ {5997 ,"Netherlands (Bonaire Island)"}, /* add new Part of Netherlands in 2010 (from Netherlands Antilles) */
+ {59946,"Netherlands (Saba Island)"}, /* add new Part of Netherlands in 2010 (from Netherlands Antilles) */
+ {59938,"Netherlands (St. Eustatius Island)"}, /* add new Part of Netherlands in 2010 (from Netherlands Antilles) */
+ // {114 ,"Nevis"}, /* removed: it is not a country, it's part of Saint Kitts and Nevis*/
+ {687 ,"New Caledonia"},
+ {64 ,"New Zealand"},
+ {505 ,"Nicaragua"},
+ {227 ,"Niger"},
+ {234 ,"Nigeria"},
+ {683 ,"Niue"},
+ {1670,"Northern Mariana Islands, US Territory of"}, /* added NANP */
+ {47 ,"Norway"},
+ {968 ,"Oman"},
+ {92 ,"Pakistan"},
+ {680 ,"Palau"},
+ {507 ,"Panama"},
+ {675 ,"Papua New Guinea"},
+ {595 ,"Paraguay"},
+ {51 ,"Peru"},
+ {63 ,"Philippines"},
+ {48 ,"Poland"},
+ {351 ,"Portugal"},
+ {1939,"Puerto Rico"}, /* change county code to NANP 939, 787 (from 121) */
+ {974 ,"Qatar"},
+ {262 ,"Reunion Island"},
+ {40 ,"Romania"},
+// {6701,"Rota Island"}, /* removed: it is not a country it is part of Northern Mariana Islands, US Territory of */
+ {7 ,"Russia"},
+ {250 ,"Rwanda"},
+ {1684,"Samoa (USA)"}, /* rename (from American Samoa) change county code to NANP (from 684) */
+ {685 ,"Samoa, Western"}, /* rename (from Western Samoa) */
+ {290 ,"Saint Helena"}, /* UK (St. Helena, Ascension and Tristan da Cunha) */
+ {247 ,"Ascension Island"}, /* UK (St. Helena, Ascension and Tristan da Cunha) */
+ {2897,"Tristan da Cunha"}, /* UK (St. Helena, Ascension and Tristan da Cunha) */
+// {115 ,"Saint Kitts"}, /* removed: it is not a country it is part of Saint Kitts and Nevis*/
+ {1869,"Saint Kitts and Nevis"}, /* change county code to NANP (from 1141) */
+ {1758,"Saint Lucia"}, /* change county code to NANP (from 122) */
+ {508 ,"Saint Pierre and Miquelon"},
+ {1784,"Saint Vincent and the Grenadines"}, /* change county code to NANP (from 116) */
+// {670 ,"Saipan Island"}, /* removed: it is not a country it is part of Northern Mariana Islands, US Territory of */
+ {378 ,"San Marino"},
+ {239 ,"Sao Tome and Principe"},
+ {966 ,"Saudi Arabia"},
+ {442 ,"Scotland"},
+ {221 ,"Senegal"},
+ {248 ,"Seychelles"},
+ {232 ,"Sierra Leone"},
+ {65 ,"Singapore"},
+ {421 ,"Slovakia"},
+ {386 ,"Slovenia"},
+ {677 ,"Solomon Islands"},
+ {252 ,"Somalia"},
+ {27 ,"South Africa"},
+ {34 ,"Spain"},
+ {3492,"Spain, Canary Islands"}, /*rename and change county code to 34(92) spain + canary code*/
+ {94 ,"Sri Lanka"},
+ {249 ,"Sudan"},
+ {597 ,"Suriname"},
+ {268 ,"Swaziland"},
+ {46 ,"Sweden"},
+ {41 ,"Switzerland"},
+ {963 ,"Syrian Arab Republic"},
+ {886 ,"Taiwan"},
+ {992 ,"Tajikistan"}, /* change county code (from 708) */
+ {255 ,"Tanzania"},
+ {66 ,"Thailand"},
+// {6702,"Tinian Island"}, /* removed: it is not a country it is part of Northern Mariana Islands, US Territory of */
+ {670 ,"Timor, East"}, /* added (is part off Northern Mariana Islands but not US Territory*/
+ {228 ,"Togo"},
+ {690 ,"Tokelau"},
+ {676 ,"Tonga"},
+ {1868,"Trinidad and Tobago"}, /* change county code to NANP (from 1141) */
+ {216 ,"Tunisia"},
+ {90 ,"Turkey"},
+ {90392,"Turkey, Republic of Northern Cyprus"}, /* added (is diffrent from Greek part)*/
+ {993 ,"Turkmenistan"}, /* change county code (from 709) */
+ {1649,"Turks and Caicos Islands"}, /* change county code to NANP (from 118) */
+ {688 ,"Tuvalu"},
+ {256 ,"Uganda"},
+ {380 ,"Ukraine"},
+ {971 ,"United Arab Emirates"},
+ {44 ,"United Kingdom"},
+ {598 ,"Uruguay"},
+ {1 ,"USA"},
+ {998 ,"Uzbekistan"}, /* change county code (from 711) */
+ {678 ,"Vanuatu"},
+ {379 ,"Vatican City"},
+ {58 ,"Venezuela"},
+ {84 ,"Vietnam"},
+ {1284,"Virgin Islands (UK)"}, /* change county code to NANP (from 105) - rename coz Virgin Islands (USA) */
+ {1340,"Virgin Islands (USA)"}, /* change county code to NANP (from 123) */
+ {441 ,"Wales"},
+ {681 ,"Wallis and Futuna Islands"},
+ {967 ,"Yemen"},
+ {38 ,"Yugoslavia"}, /* added for old values like birth-country */
+ {381 ,"Serbia, Republic of"}, /* rename need (from Yugoslavia)*/
+ {383 ,"Kosovo, Republic of"}, /*change country code (from 3811), rename need (from Yugoslavia - Serbia) */
+ {382 ,"Montenegro, Republic of"}, /* rename need (from Yugoslavia - Montenegro) */
+ {260 ,"Zambia"},
+ {263 ,"Zimbabwe"},
+};
+
+INT_PTR ServiceGetCountryByNumber(WPARAM wParam,LPARAM lParam)
+{
+ int i;
+ UNREFERENCED_PARAMETER(lParam);
+ for(i=0; i<SIZEOF(countries); ++i)
+ if((int)wParam==countries[i].id)
+ return (INT_PTR)countries[i].szName;
+ return NULL;
+}
+
+INT_PTR ServiceGetCountryList(WPARAM wParam,LPARAM lParam)
+{
+ if((int*)wParam==NULL || (void*)lParam==NULL) return 1;
+ *(int*)wParam=SIZEOF(countries);
+ *(struct CountryListEntry**)lParam=countries;
+ return 0;
+}
+
+/************************* Misc ***********************************/
+
+VOID InitCountryListExt()
+{
+ /* hack to replace built-in country list */
+ if(!myDestroyServiceFunction(MS_UTILS_GETCOUNTRYLIST))
+ myCreateServiceFunction(MS_UTILS_GETCOUNTRYLIST,ServiceGetCountryList);
+ if(!myDestroyServiceFunction(MS_UTILS_GETCOUNTRYBYNUMBER))
+ myCreateServiceFunction(MS_UTILS_GETCOUNTRYBYNUMBER,ServiceGetCountryByNumber);
+}
diff --git a/plugins/UserInfoEx/Flags/svc_countrylistext.h b/plugins/UserInfoEx/Flags/svc_countrylistext.h
new file mode 100644
index 0000000000..a49a289542
--- /dev/null
+++ b/plugins/UserInfoEx/Flags/svc_countrylistext.h
@@ -0,0 +1,39 @@
+/*
+UserinfoEx plugin for Miranda IM
+
+Copyright:
+ 2006-2010 DeathAxe, Yasnovidyashii, Merlin, K. Romanov, Kreol
+
+part of this code based on:
+Miranda IM Country Flags Plugin Copyright 2006-2007 H. Herkenrath
+
+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 : $HeadURL: https://userinfoex.googlecode.com/svn/trunk/Flags/svc_countrylistext.h $
+Revision : $Revision: 199 $
+Last change on : $Date: 2010-09-22 17:21:44 +0400 (Ср, 22 сен 2010) $
+Last change by : $Author: ing.u.horn $
+
+===============================================================================
+*/
+#ifndef _UINFOEX_COUNTRYLIST_H_INCLUDED_
+#define _UINFOEX_COUNTRYLIST_H_INCLUDED_
+
+VOID InitCountryListExt();
+INT_PTR ServiceGetCountryByNumber(WPARAM wParam,LPARAM lParam);
+
+#endif /* _UINFOEX_COUNTRYLIST_H_INCLUDED_ */ \ No newline at end of file
diff --git a/plugins/UserInfoEx/Flags/svc_flags.cpp b/plugins/UserInfoEx/Flags/svc_flags.cpp
new file mode 100644
index 0000000000..bc3619f273
--- /dev/null
+++ b/plugins/UserInfoEx/Flags/svc_flags.cpp
@@ -0,0 +1,765 @@
+/*
+UserinfoEx plugin for Miranda IM
+
+Copyright:
+ 2006-2010 DeathAxe, Yasnovidyashii, Merlin, K. Romanov, Kreol
+
+part of this code based on:
+Miranda IM Country Flags Plugin Copyright 2006-2007 H. Herkenrath
+
+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 : $HeadURL: https://userinfoex.googlecode.com/svn/trunk/Flags/svc_flags.cpp $
+Revision : $Revision: 187 $
+Last change on : $Date: 2010-09-08 16:05:54 +0400 (Ср, 08 сен 2010) $
+Last change by : $Author: ing.u.horn $
+
+===============================================================================
+*/
+
+#include "..\commonheaders.h"
+#include "svc_flags.h"
+#include "svc_flagsicons.h"
+#include "svc_countrylistext.h"
+
+#define M_ENABLE_SUBCTLS (WM_APP+1)
+
+FLAGSOPTIONS gFlagsOpts;
+
+/* Misc */
+int nCountriesCount;
+struct CountryListEntry *countries;
+static HANDLE *phExtraImageList = NULL; //return value(s) from MS_CLIST_EXTRA_ADD_ICON
+static HANDLE hExtraIconSvc = INVALID_HANDLE_VALUE;
+/* hook */
+static HANDLE hRebuildIconsHook = NULL;
+static HANDLE hApplyIconHook = NULL;
+static HANDLE hMsgWndEventHook = NULL;
+static HANDLE hIconsChangedHook = NULL;
+static HANDLE hSettingChangedHook = NULL;
+
+static HANDLE hExtraIconSvcHook = NULL;
+static HANDLE hOptInitHook = NULL;
+
+static int OnContactSettingChanged(WPARAM wParam,LPARAM lParam);
+
+/***********************************************************************************************************
+ * Buffered functions
+ ***********************************************************************************************************/
+
+struct BufferedCallData {
+ DWORD startTick;
+ UINT uElapse;
+ BUFFEREDPROC pfnBuffProc;
+ LPARAM lParam;
+ #ifdef _DEBUG
+ const char *pszProcName;
+ #endif
+};
+
+static UINT_PTR idBufferedTimer;
+static struct BufferedCallData *callList;
+static int nCallListCount;
+
+// always gets called in main message loop
+static void CALLBACK BufferedProcTimer(HWND hwnd, UINT msg, UINT idTimer, DWORD currentTick) {
+ int i;
+ struct BufferedCallData *buf;
+ UINT uElapsed, uElapseNext = USER_TIMER_MAXIMUM;
+ BUFFEREDPROC pfnBuffProc;
+ LPARAM lParam;
+ #ifdef _DEBUG
+ char szDbgLine[256];
+ const char *pszProcName;
+ #endif
+ UNREFERENCED_PARAMETER(msg);
+
+ for(i=0;i<nCallListCount;++i) {
+ /* find elapsed procs */
+ uElapsed=currentTick-callList[i].startTick; /* wraparound works */
+ if((uElapsed+USER_TIMER_MINIMUM)>=callList[i].uElapse) {
+ /* call elapsed proc */
+ pfnBuffProc=callList[i].pfnBuffProc;
+ lParam=callList[i].lParam;
+ #ifdef _DEBUG
+ pszProcName=callList[i].pszProcName;
+ #endif
+ /* resize storage array */
+ if((i+1)<nCallListCount)
+ MoveMemory(&callList[i],&callList[i+1],((nCallListCount-i-1)*sizeof(struct BufferedCallData)));
+ --nCallListCount;
+ --i; /* reiterate current */
+ if(nCallListCount) {
+ buf=(struct BufferedCallData*)mir_realloc(callList,nCallListCount*sizeof(struct BufferedCallData));
+ if(buf!=NULL) callList=buf;
+ } else {
+ mir_free(callList);
+ callList=NULL;
+ }
+ #ifdef _DEBUG
+ mir_snprintf(szDbgLine,sizeof(szDbgLine),"buffered call: %s(0x%X)\n",pszProcName,lParam); /* all ascii */
+ OutputDebugStringA(szDbgLine);
+ #endif
+ CallFunctionAsync((void (CALLBACK *)(void*))pfnBuffProc,(void*)lParam); /* compatible */
+ }
+ /* find next timer delay */
+ else if((callList[i].uElapse-uElapsed)<uElapseNext)
+ uElapseNext=callList[i].uElapse-uElapsed;
+ }
+
+ /* set next timer */
+ if(nCallListCount) {
+ #ifdef _DEBUG
+ mir_snprintf(szDbgLine,sizeof(szDbgLine),"next buffered timeout: %ums\n",uElapseNext); /* all ascii */
+ OutputDebugStringA(szDbgLine);
+ #endif
+ idBufferedTimer=SetTimer(hwnd, idBufferedTimer, uElapseNext, (TIMERPROC)BufferedProcTimer); /* will be reset */
+ } else {
+ KillTimer(hwnd,idTimer);
+ idBufferedTimer=0;
+ #ifdef _DEBUG
+ OutputDebugStringA("empty buffered queue\n");
+ #endif
+ }
+}
+
+// assumes to be called in context of main thread
+#ifdef _DEBUG
+void _CallFunctionBuffered(BUFFEREDPROC pfnBuffProc,const char *pszProcName,LPARAM lParam,BOOL fAccumulateSameParam,UINT uElapse)
+#else
+void _CallFunctionBuffered(BUFFEREDPROC pfnBuffProc,LPARAM lParam,BOOL fAccumulateSameParam,UINT uElapse)
+#endif
+{
+ struct BufferedCallData *data=NULL;
+ int i;
+
+ /* find existing */
+ for(i=0;i<nCallListCount;++i)
+ if(callList[i].pfnBuffProc==pfnBuffProc)
+ if(!fAccumulateSameParam || callList[i].lParam==lParam) {
+ data=&callList[i];
+ break;
+ }
+ /* append new */
+ if(data==NULL) {
+ /* resize storage array */
+ data=(struct BufferedCallData*)mir_realloc(callList,(nCallListCount+1)*sizeof(struct BufferedCallData));
+ if(data==NULL) return;
+ callList=data;
+ data=&callList[nCallListCount];
+ ++nCallListCount;
+ }
+ /* set delay */
+ data->startTick=GetTickCount();
+ data->uElapse=uElapse;
+ data->lParam=lParam;
+ data->pfnBuffProc=pfnBuffProc;
+ #ifdef _DEBUG
+ { char szDbgLine[256];
+ data->pszProcName=pszProcName;
+ mir_snprintf(szDbgLine,sizeof(szDbgLine),"buffered queue: %s(0x%X)\n",pszProcName,lParam); /* all ascii */
+ OutputDebugStringA(szDbgLine);
+ if(!idBufferedTimer) {
+ mir_snprintf(szDbgLine,sizeof(szDbgLine),"next buffered timeout: %ums\n",uElapse); /* all ascii */
+ OutputDebugStringA(szDbgLine);
+ }
+ }
+ #endif
+ /* set next timer */
+ if(idBufferedTimer) uElapse=USER_TIMER_MINIMUM; /* will get recalculated */
+ idBufferedTimer=SetTimer(NULL,idBufferedTimer,uElapse,(TIMERPROC)BufferedProcTimer);
+}
+
+// assumes to be called in context of main thread
+void PrepareBufferedFunctions()
+{
+ idBufferedTimer=0;
+ nCallListCount=0;
+ callList=NULL;
+}
+
+// assumes to be called in context of main thread
+void KillBufferedFunctions()
+{
+ if(idBufferedTimer) KillTimer(NULL,idBufferedTimer);
+ nCallListCount=0;
+ mir_free(callList); /* does NULL check */
+}
+
+/***********************************************************************************************************
+ * service functions
+ ***********************************************************************************************************/
+
+static INT_PTR ServiceDetectContactOriginCountry(WPARAM wParam,LPARAM lParam)
+{
+ WORD countryNumber;
+ char *pszProto =
+ pszProto=(char*)CallService(MS_PROTO_GETCONTACTBASEPROTO,wParam,0);
+ /* UserinfoEx */
+ if (countryNumber = (int)DB::Setting::GetWord((HANDLE)wParam,USERINFO,SET_CONTACT_ORIGIN_COUNTRY,0))
+ return (INT_PTR)countryNumber;
+ else if (countryNumber = (int)DB::Setting::GetWord((HANDLE)wParam,USERINFO,SET_CONTACT_COUNTRY,0))
+ return (INT_PTR)countryNumber;
+ else if (countryNumber = (int)DB::Setting::GetWord((HANDLE)wParam,USERINFO,SET_CONTACT_COMPANY_COUNTRY,0))
+ return (INT_PTR)countryNumber;
+ /* fallback proto settings */
+ else if (countryNumber = (int)DB::Setting::GetWord((HANDLE)wParam,pszProto,"Country",0))
+ return (INT_PTR)countryNumber;
+ else if (countryNumber = (int)DB::Setting::GetWord((HANDLE)wParam,pszProto,"CompanyCountry",0))
+ return (INT_PTR)countryNumber;
+ /* fallback ip detect
+ else if(countryNumber==0xFFFF && DBGetContactSettingByte(NULL,"Flags","UseIpToCountry",SETTING_USEIPTOCOUNTRY_DEFAULT)){
+ countryNumber=ServiceIpToCountry(DBGetContactSettingDword((HANDLE)wParam,pszProto,"RealIP",0),0);
+ }*/
+
+ return (INT_PTR)0xFFFF;
+}
+
+/***********************************************************************************************************
+ * Clist Extra Image functions
+ ***********************************************************************************************************/
+
+static void CALLBACK SetExtraImage(LPARAM lParam) {
+ /* get contact's country */
+ int countryNumber = ServiceDetectContactOriginCountry((WPARAM)lParam,0);;
+ //use ExtraIconsService ?
+ if (myGlobals.ExtraIconsServiceExist) {
+ EXTRAICON ico;
+ ico.cbSize = sizeof(ico);
+ ico.hContact = (HANDLE)lParam;
+ ico.hExtraIcon = hExtraIconSvc;
+ ico.icoName = (char*)0; //preset
+ if(countryNumber!=0xFFFF || gFlagsOpts.bUseUnknownFlag) {
+ char szId[20];
+ mir_snprintf(szId, SIZEOF(szId), (countryNumber==0xFFFF)?"%s_0x%X":"%s_%i","flags",countryNumber); /* buffer safe */
+ ico.icoName = szId;
+ }
+ CallService(MS_EXTRAICON_SET_ICON, (WPARAM)&ico, 0);
+ }
+ //use Clist ExtraImageService
+ else if(gFlagsOpts.bShowExtraImgFlag) {
+ int index;
+ IconExtraColumn iec;
+ iec.cbSize = sizeof(iec);
+ iec.ColumnType = gFlagsOpts.idExtraColumn;
+ iec.hImage = INVALID_HANDLE_VALUE; //preset
+ /* get icon for contact */
+ if(phExtraImageList!=NULL) { /* too early? */
+ if(countryNumber!=0xFFFF || gFlagsOpts.bUseUnknownFlag) {
+ index = CountryNumberToIndex(countryNumber);
+ /* icon not add to clist extra image list? */
+ if(phExtraImageList[index]==INVALID_HANDLE_VALUE) {
+ HICON hIcon=LoadFlag(countryNumber); // Returned HICON SHOULDN'T be destroyed, it is managed by IcoLib
+ if(hIcon!=NULL) {
+ phExtraImageList[index]=(HANDLE)CallService(MS_CLIST_EXTRA_ADD_ICON,(WPARAM)hIcon,0);
+ CallService(MS_SKIN2_RELEASEICON,(WPARAM)hIcon,0); /* does NULL check */
+ }
+ }
+ iec.hImage=phExtraImageList[index];
+ }
+ }
+ //Set icon for contact at needed column
+ CallService(MS_CLIST_EXTRA_SET_ICON,(WPARAM)lParam,(LPARAM)&iec);
+ }
+}
+
+static void CALLBACK RemoveExtraImages(LPARAM lParam) {
+ register HANDLE hContact;
+ //use ExtraIconsService ?
+ if (myGlobals.ExtraIconsServiceExist) {
+ EXTRAICON ico;
+ ico.cbSize = sizeof(ico);
+ ico.hExtraIcon = hExtraIconSvc;
+ ico.icoName = (char *)0; /* invalidate icon for contact*/
+ /* enum all contacts */
+ for (hContact = DB::Contact::FindFirst(); hContact != NULL; hContact = DB::Contact::FindNext(hContact)) {
+ ico.hContact = hContact;
+ CallService(MS_EXTRAICON_SET_ICON, (WPARAM)&ico, 0);
+ }
+ }
+ //use Clist ExtraImageService
+ else {
+ IconExtraColumn iec;
+ iec.cbSize = sizeof(iec);
+ iec.ColumnType = gFlagsOpts.idExtraColumn;
+ iec.hImage = INVALID_HANDLE_VALUE;
+ /* enum all contacts */
+ for (hContact = DB::Contact::FindFirst(); hContact != NULL; hContact = DB::Contact::FindNext(hContact)) {
+ /* invalidate icon for contact*/
+ CallService(MS_CLIST_EXTRA_SET_ICON,(WPARAM)hContact,(LPARAM)&iec);
+ }
+ }
+}
+
+// always call in context of main thread
+void EnsureExtraImages() //garantieren - sicherstellen - updaten
+{
+ register HANDLE hContact;
+ //use Clist ExtraImageService?
+ if(!myGlobals.ExtraIconsServiceExist) {
+ BYTE idExtraColumnNew = DB::Setting::GetByte(MODNAMEFLAGS,"ExtraImgFlagColumn",SETTING_EXTRAIMGFLAGCOLUMN_DEFAULT);
+ if(idExtraColumnNew != gFlagsOpts.idExtraColumn) {
+ /* clear previous column */
+ RemoveExtraImages(0);
+ gFlagsOpts.idExtraColumn = idExtraColumnNew;
+ /* clear new column */
+ RemoveExtraImages(0);
+ }
+ }
+ /* enum all contacts */
+ for (hContact = DB::Contact::FindFirst(); hContact != NULL; hContact = DB::Contact::FindNext(hContact)) {
+ /* update icon */
+ CallFunctionBuffered(SetExtraImage,(LPARAM)hContact,TRUE,EXTRAIMAGE_REFRESHDELAY);
+ }
+}
+
+static void CALLBACK UpdateExtraImages(LPARAM lParam) {
+ if(!lParam)
+ RemoveExtraImages(0);
+ else EnsureExtraImages();
+
+/* if(!myGlobals.ExtraIconsServiceExist && !gFlagsOpts.bShowExtraImgFlag)
+ RemoveExtraImages();
+ else EnsureExtraImages(); */
+}
+
+//hookProc ME_CLIST_EXTRA_LIST_REBUILD
+static int OnCListRebuildIcons(WPARAM wParam,LPARAM lParam) {
+ OutputDebugStringA("REBUILD EXTRA\n");
+ //use ExtraIconsService ?
+ if(myGlobals.ExtraIconsServiceExist) return 0; //delete ?
+ //use Clist ExtraImageService
+ if(phExtraImageList!=NULL) {
+ /* invalidate icons */
+ for(int i=0;i<nCountriesCount;++i)
+ phExtraImageList[i]=INVALID_HANDLE_VALUE;
+ }
+ /* update column */
+ gFlagsOpts.idExtraColumn = DB::Setting::GetByte(MODNAMEFLAGS,"ExtraImgFlagColumn",SETTING_EXTRAIMGFLAGCOLUMN_DEFAULT);
+ return 0;
+}
+
+//hookProc ME_CLIST_EXTRA_IMAGE_APPLY
+static int OnCListApplyIcons(WPARAM wParam,LPARAM lParam) {
+ //OutputDebugStringA("APPLY EXTRA\n");
+ if(myGlobals.ExtraIconsServiceExist || gFlagsOpts.bShowExtraImgFlag)
+ SetExtraImage((LPARAM)wParam); /* unbuffered */
+ return 0;
+}
+
+//hookProc (ME_DB_CONTACT_SETTINGCHANGED) - workaround for missing event from ExtraIconSvc
+static int OnExtraIconSvcChanged(WPARAM wParam,LPARAM lParam) {
+ DBCONTACTWRITESETTING *dbcws=(DBCONTACTWRITESETTING*)lParam;
+ if((HANDLE)wParam!=NULL)return 0;
+ if(!lstrcmpA(dbcws->szModule, "ExtraIcons") &&
+ !lstrcmpA(dbcws->szSetting,"Slot_Flags") ){
+ BOOL bEnable;
+ switch (dbcws->value.type) {
+ case DBVT_BYTE:
+ bEnable = dbcws->value.bVal != (BYTE)-1;
+ break;
+ case DBVT_WORD:
+ bEnable = dbcws->value.wVal != (WORD)-1;
+ break;
+ case DBVT_DWORD:
+ bEnable = dbcws->value.dVal != (DWORD)-1;
+ break;
+ default:
+ bEnable = -1;
+ break;
+ }
+ if(bEnable == -1) {
+ return 0;
+ }
+ else if(bEnable && !hApplyIconHook) {
+ hApplyIconHook = HookEvent(ME_CLIST_EXTRA_IMAGE_APPLY, OnCListApplyIcons);
+ }
+ else if(!bEnable && hApplyIconHook) {
+ UnhookEvent(hApplyIconHook); hApplyIconHook = NULL;
+ }
+ CallFunctionBuffered(UpdateExtraImages,(LPARAM)bEnable,FALSE,EXTRAIMAGE_REFRESHDELAY);
+ }
+ return 0;
+}
+
+VOID SvcFlagsEnableExtraIcons(BYTE bColumn, BOOLEAN bUpdateDB) {
+ if (!myGlobals.HaveCListExtraIcons) return;
+ gFlagsOpts.bShowExtraImgFlag = (bColumn!=((BYTE)-1));
+ if (bUpdateDB) {
+ if(gFlagsOpts.bShowExtraImgFlag) DB::Setting::WriteByte(MODNAMEFLAGS,"ExtraImgFlagColumn", bColumn);
+ DB::Setting::WriteByte(MODNAMEFLAGS,"ShowExtraImgFlag", bColumn!=(BYTE)-1);
+ }
+
+ // Flags is on
+ if (gFlagsOpts.bShowExtraImgFlag) {
+ //use ExtraIconsService ?
+ if(myGlobals.ExtraIconsServiceExist) {
+ if(hExtraIconSvc == INVALID_HANDLE_VALUE) {
+ char szId[20];
+ //get local langID for descIcon (try to use user local Flag as icon)
+ DWORD langid = 0;
+ int r = GetLocaleInfo(
+ LOCALE_USER_DEFAULT,
+ LOCALE_ICOUNTRY | LOCALE_RETURN_NUMBER ,
+ (LPTSTR)&langid, sizeof(langid)/sizeof(TCHAR));
+ if(!CallService(MS_UTILS_GETCOUNTRYBYNUMBER,langid,0)) langid = 1;
+
+ EXTRAICON_INFO ico = {0};
+ ico.cbSize = sizeof(ico);
+ ico.type = EXTRAICON_TYPE_ICOLIB;
+ ico.name = "Flags";
+ ico.description = "Flags (uinfoex)";
+ mir_snprintf(szId, SIZEOF(szId), (langid==0xFFFF)?"%s_0x%X":"%s_%i","flags",langid); /* buffer safe */
+ ico.descIcon = szId;
+ hExtraIconSvc=(HANDLE)CallService(MS_EXTRAICON_REGISTER, (WPARAM)&ico, 0);
+ if(hExtraIconSvc)
+ hExtraIconSvcHook = HookEvent(ME_DB_CONTACT_SETTINGCHANGED, OnExtraIconSvcChanged);
+
+ }
+ }
+ //use Clist ExtraImageService
+ else {
+ if(phExtraImageList == NULL){
+ phExtraImageList = (HANDLE*)mir_alloc(nCountriesCount*sizeof(HANDLE));
+ /* invalidate icons */
+ if(phExtraImageList!=NULL)
+ for(int i=0;i<nCountriesCount;++i)
+ phExtraImageList[i]=INVALID_HANDLE_VALUE;
+ }
+ if(!hRebuildIconsHook) {
+ hRebuildIconsHook = HookEvent(ME_CLIST_EXTRA_LIST_REBUILD, OnCListRebuildIcons);
+ }
+ }
+ //init hooks
+ if(!hApplyIconHook) {
+ hApplyIconHook = HookEvent(ME_CLIST_EXTRA_IMAGE_APPLY, OnCListApplyIcons);
+ }
+ if(!hSettingChangedHook) {
+ hSettingChangedHook = HookEvent(ME_DB_CONTACT_SETTINGCHANGED, OnContactSettingChanged);
+ }
+ }
+ // Flags is off
+ else {
+ //use ExtraIconsService ?
+ if (myGlobals.ExtraIconsServiceExist) {
+ //nothing to do, until plugin has a hookable event for status
+ return;
+ }
+ //use Clist ExtraImageService
+ //unhook
+ if (hRebuildIconsHook) {
+ UnhookEvent(hRebuildIconsHook); hRebuildIconsHook = NULL;
+ }
+ if (hApplyIconHook) {
+ UnhookEvent(hApplyIconHook); hApplyIconHook = NULL;
+ }
+ if (hSettingChangedHook && !gFlagsOpts.bShowStatusIconFlag) {
+ UnhookEvent(hSettingChangedHook); hSettingChangedHook = NULL;
+ }
+ //SvcFlagsApplyCListIcons();
+ //RemoveExtraImages();
+ CallFunctionBuffered(RemoveExtraImages,0,FALSE,EXTRAIMAGE_REFRESHDELAY);
+ }
+}
+
+/***********************************************************************************************************
+ * message winsow status icon functions
+ ***********************************************************************************************************/
+
+MsgWndData::MsgWndData(HWND hwnd, HANDLE hContact) {
+ m_hwnd = hwnd;
+ m_hContact = hContact;
+ m_contryID = (int)ServiceDetectContactOriginCountry((WPARAM)m_hContact,0);
+ FlagsIconUpdate();
+}
+
+MsgWndData::~MsgWndData() {
+ FlagsIconUnset(); //check if realy need
+}
+
+void
+MsgWndData::FlagsIconSet() {
+ HICON hIcon = NULL;
+ StatusIconData sid = {0};
+ sid.cbSize = sizeof(sid);
+ sid.szModule = MODNAMEFLAGS;
+ /* ensure status icon is registered */
+ if( m_contryID!=0xFFFF || gFlagsOpts.bUseUnknownFlag) {
+ /* copy icon as status icon API will call DestroyIcon() on it */
+ hIcon = LoadFlagIcon(m_contryID);
+ sid.hIcon = (hIcon!=NULL)?CopyIcon(hIcon):NULL;
+ CallService(MS_SKIN2_RELEASEICON,(WPARAM)hIcon,0); /* does NULL check */
+ hIcon = sid.hIcon;
+ sid.dwId = (DWORD)m_contryID;
+ sid.hIconDisabled = sid.hIcon/*NULL*/;
+ sid.szTooltip = Translate((char*)CallService(MS_UTILS_GETCOUNTRYBYNUMBER,m_contryID,0));
+ sid.flags = 0;
+ if(CallService(MS_MSG_MODIFYICON,(WPARAM)m_hContact,(LPARAM)&sid) !=0) /* not yet registered? */
+ CallService(MS_MSG_ADDICON,0,(LPARAM)&sid);
+ }
+ sid.hIcon = NULL;
+ sid.szTooltip = NULL;
+ sid.hIconDisabled = NULL;
+ for(int i=0;i<nCountriesCount;++i) {
+ sid.dwId = (DWORD)countries[i].id;
+ sid.flags = (m_contryID==countries[i].id && hIcon!=NULL)? 0:MBF_HIDDEN;
+ CallService(MS_MSG_MODIFYICON,(WPARAM)m_hContact,(LPARAM)&sid);
+ }
+}
+
+void
+MsgWndData::FlagsIconUnset() {
+ StatusIconData sid = {0};
+ sid.cbSize = sizeof(sid);
+ sid.szModule = MODNAMEFLAGS;
+ sid.dwId = (DWORD)m_contryID;
+ sid.flags = MBF_HIDDEN;
+ CallService(MS_MSG_MODIFYICON,(WPARAM)m_hContact,(LPARAM)&sid);
+ /* can't call MS_MSG_REMOVEICON here as the icon might be
+ * in use by other contacts simultanously, removing them all at exit */
+}
+
+static int CompareMsgWndData(const MsgWndData* p1, const MsgWndData* p2)
+{
+ return (int)((INT_PTR)p1->m_hContact - (INT_PTR)p2->m_hContact);
+}
+static LIST<MsgWndData> gMsgWndList(10, CompareMsgWndData);
+
+static int CompareIconListData(const IconList* p1, const IconList* p2)
+{
+ return (int)((INT_PTR)p1->m_ID - (INT_PTR)p2->m_ID);
+}
+static OBJLIST<IconList> gIListMW(10, CompareIconListData);
+
+IconList::IconList(StatusIconData *sid) {
+ m_StatusIconData.cbSize = sid->cbSize;
+ m_StatusIconData.szModule = mir_strdup(sid->szModule);
+ m_StatusIconData.dwId = sid->dwId;
+ m_StatusIconData.hIcon = CopyIcon(sid->hIcon);
+ m_StatusIconData.hIconDisabled = sid->hIconDisabled;
+ m_StatusIconData.flags = sid->flags;
+ m_StatusIconData.szTooltip = mir_strdup(sid->szTooltip);
+
+ m_ID = sid->dwId;
+ CallService(MS_MSG_ADDICON,0,(LPARAM)sid);
+
+}
+IconList::~IconList() {
+ mir_free(m_StatusIconData.szModule);
+ mir_free(m_StatusIconData.szTooltip);
+}
+// const char *pszName; // [Optional] Name of an icon registered with icolib to be used in GUI.
+static __inline int MessageAPI_AddIcon(const char* pszName, const char* szModul/*StatusIconData *sid*/,int ID, int flags, const char* szTooltip)
+{
+ HICON hIcon = (HICON)CallService(MS_SKIN2_GETICON,(WPARAM)0/* =small 1=big*/,(LPARAM)pszName);
+
+ StatusIconData sid = {0};
+ sid.cbSize = sizeof(sid);
+ sid.szModule = (char*)szModul;
+ sid.dwId = (DWORD)ID;
+ sid.hIcon = (hIcon!=NULL)?CopyIcon(hIcon):NULL;
+ CallService(MS_SKIN2_RELEASEICON,(WPARAM)hIcon,0); /* does NULL check */
+// sid.hIconDisabled = sid.hIcon/*NULL*/;
+ sid.flags = 0;
+ sid.szTooltip = Translate((char*)CallService(MS_UTILS_GETCOUNTRYBYNUMBER,ID,0));
+
+ int res = -1;
+ IconList* p = new IconList(&sid);
+ if(!p->m_ID)delete p;
+ else res = gIListMW.insert(p);
+ if(res == -1)delete p;
+ return res;
+}
+
+void CALLBACK UpdateStatusIcons(LPARAM lParam) {
+ if(!lParam) {
+ /* enum all opened message windows */
+ for (int i = 0; i < gMsgWndList.getCount(); i++)
+ gMsgWndList[i]->FlagsIconUpdate();
+ }
+ else {
+ int i = gMsgWndList.getIndex((MsgWndData*)&lParam);
+ if (i!= -1) gMsgWndList[i]->FlagsIconUpdate();
+ }
+}
+
+//hookProc ME_MSG_WINDOWEVENT
+static int OnMsgWndEvent(WPARAM wParam,LPARAM lParam) {
+ MessageWindowEventData *msgwe=(MessageWindowEventData*)lParam;
+ /* sanity check */
+ if(msgwe->hContact==NULL)
+ return 0;
+
+ switch(msgwe->uType) {
+ case MSG_WINDOW_EVT_OPENING:
+ {
+ MsgWndData* msgwnd = gMsgWndList.find((MsgWndData*)&msgwe->hContact);
+ if(msgwnd == NULL) {
+ msgwnd = new MsgWndData(msgwe->hwndWindow, msgwe->hContact);
+ gMsgWndList.insert(msgwnd);
+ }
+ }
+ break;
+
+ case MSG_WINDOW_EVT_CLOSE:
+ {
+ int i = gMsgWndList.getIndex((MsgWndData*)&msgwe->hContact);
+ if (i != -1) {
+ delete gMsgWndList[i];
+ gMsgWndList.remove(i);
+ }
+ }
+ break;
+ }
+ return 0;
+}
+
+//hookProc ME_SKIN2_ICONSCHANGED
+static int OnStatusIconsChanged(WPARAM wParam,LPARAM lParam) {
+ if(myGlobals.MsgAddIconExist && gFlagsOpts.bShowStatusIconFlag)
+ CallFunctionBuffered(UpdateStatusIcons,0,FALSE,STATUSICON_REFRESHDELAY);
+ return 0;
+}
+
+/***********************************************************************************************************
+ * option page (not used yet)
+ ***********************************************************************************************************/
+static INT_PTR CALLBACK ExtraImgOptDlgProc(HWND hwndDlg,UINT msg,WPARAM wParam,LPARAM lParam)
+{
+ return FALSE;
+}
+
+//hookProc ME_OPT_INITIALISE
+static int ExtraImgOptInit(WPARAM wParam,LPARAM lParam)
+{
+ OPTIONSDIALOGPAGE odp = { 0 };
+ return 0;
+}
+
+/***********************************************************************************************************
+ * misc functions
+ ***********************************************************************************************************/
+//hookProc ME_DB_CONTACT_SETTINGCHANGED
+static int OnContactSettingChanged(WPARAM wParam,LPARAM lParam) {
+ if((HANDLE)wParam==NULL) return 0;
+ DBCONTACTWRITESETTING *dbcws=(DBCONTACTWRITESETTING*)lParam;
+
+ /* user details update */
+ if(/*!lstrcmpA(dbcws->szSetting,"RealIP") || */
+ !lstrcmpA(dbcws->szSetting,SET_CONTACT_COUNTRY) ||
+ !lstrcmpA(dbcws->szSetting,SET_CONTACT_ORIGIN_COUNTRY) ||
+ !lstrcmpA(dbcws->szSetting,SET_CONTACT_COMPANY_COUNTRY))
+ {
+ /* Extra Image */
+ if(myGlobals.HaveCListExtraIcons)
+ CallFunctionBuffered(SetExtraImage,(LPARAM)wParam,TRUE,EXTRAIMAGE_REFRESHDELAY);
+ /* Status Icon */
+ if(hMsgWndEventHook) {
+ int i = gMsgWndList.getIndex((MsgWndData*)&wParam);
+ if (i != -1) {
+ gMsgWndList[i]->ContryIDchange((int)ServiceDetectContactOriginCountry(wParam,0));
+ gMsgWndList[i]->FlagsIconUpdate();
+ }
+ }
+ }
+ return 0;
+}
+
+
+/***********************************************************************************************************
+ * module loading & unloading
+ ***********************************************************************************************************/
+
+/**
+ * This function initially loads all required stuff for Flags.
+ *
+ * @param none
+ *
+ * @return nothing
+ **/
+void SvcFlagsLoadModule()
+{
+ PrepareBufferedFunctions();
+ InitCountryListExt(); /* hack to replace core country list */
+ if(CallService(MS_UTILS_GETCOUNTRYLIST,(WPARAM)&nCountriesCount,(LPARAM)&countries))
+ nCountriesCount=0;
+ InitIcons(); /* load in iconlib */
+ //InitIpToCountry(); /* not implementet */
+ myCreateServiceFunction(MS_FLAGS_DETECTCONTACTORIGINCOUNTRY,ServiceDetectContactOriginCountry);
+ //init settings
+ gFlagsOpts.bShowExtraImgFlag = DB::Setting::GetByte(MODNAMEFLAGS,"ShowExtraImgFlag", SETTING_SHOWEXTRAIMGFLAG_DEFAULT);
+ gFlagsOpts.bUseUnknownFlag = DB::Setting::GetByte(MODNAMEFLAGS,"UseUnknownFlag", SETTING_USEUNKNOWNFLAG_DEFAULT);
+ gFlagsOpts.idExtraColumn = DB::Setting::GetByte(MODNAMEFLAGS,"ExtraImgFlagColumn", SETTING_EXTRAIMGFLAGCOLUMN_DEFAULT);
+ gFlagsOpts.bShowStatusIconFlag = DB::Setting::GetByte(MODNAMEFLAGS,"ShowStatusIconFlag", SETTING_SHOWSTATUSICONFLAG_DEFAULT);
+
+ hOptInitHook = HookEvent(ME_OPT_INITIALISE,ExtraImgOptInit);
+ hIconsChangedHook = HookEvent(ME_SKIN2_ICONSCHANGED,OnStatusIconsChanged);
+}
+
+/**
+ * This function is called by Miranda just after loading all system modules.
+ *
+ * @param none
+ *
+ * @return nothing
+ **/
+void SvcFlagsOnModulesLoaded() {
+ //use ExtraIconsService ?
+ if ( myGlobals.ExtraIconsServiceExist) {
+ SvcFlagsEnableExtraIcons(DB::Setting::GetByte(SET_CLIST_EXTRAICON_FLAGS2, 0), FALSE);
+ }
+ //use Clist ExtraImageService
+ else {
+ SvcFlagsEnableExtraIcons(gFlagsOpts.bShowExtraImgFlag? gFlagsOpts.idExtraColumn : -1, FALSE);
+ }
+ /* Status Icon */
+ if(myGlobals.MsgAddIconExist)
+ hMsgWndEventHook = HookEvent(ME_MSG_WINDOWEVENT, OnMsgWndEvent);
+}
+
+/**
+ * This function unloads the module.
+ *
+ * @param none
+ *
+ * @return nothing
+ **/
+void SvcFlagsUnloadModule() {
+ KillBufferedFunctions();
+ //Uninit ExtraImg
+ UnhookEvent(hRebuildIconsHook);
+ UnhookEvent(hApplyIconHook);
+ UnhookEvent(hIconsChangedHook);
+ UnhookEvent(hExtraIconSvcHook);
+ mir_free(phExtraImageList); /* does NULL check */
+ //Uninit message winsow
+ UnhookEvent(hMsgWndEventHook);
+ for(int i = 0; i < gMsgWndList.getCount(); i++) {
+ //this should not happen
+ delete gMsgWndList[i];
+ gMsgWndList.remove(i);
+ }
+ gMsgWndList.destroy();
+ gIListMW.destroy();
+ //Uninit misc
+ UnhookEvent(hSettingChangedHook);
+ UnhookEvent(hOptInitHook);
+ UninitIcons();
+
+ //UninitIpToCountry(); /* not implementet */
+}
+
diff --git a/plugins/UserInfoEx/Flags/svc_flags.h b/plugins/UserInfoEx/Flags/svc_flags.h
new file mode 100644
index 0000000000..e7f97ab963
--- /dev/null
+++ b/plugins/UserInfoEx/Flags/svc_flags.h
@@ -0,0 +1,102 @@
+/*
+UserinfoEx plugin for Miranda IM
+
+Copyright:
+ 2006-2010 DeathAxe, Yasnovidyashii, Merlin, K. Romanov, Kreol
+
+part of this code based on:
+Miranda IM Country Flags Plugin Copyright 2006-2007 H. Herkenrath
+
+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 : $HeadURL: https://userinfoex.googlecode.com/svn/trunk/Flags/svc_flags.h $
+Revision : $Revision: 187 $
+Last change on : $Date: 2010-09-08 16:05:54 +0400 (Ср, 08 сен 2010) $
+Last change by : $Author: ing.u.horn $
+
+===============================================================================
+*/
+#ifndef _UINFOEX_FLAGS_H_INCLUDED_
+#define _UINFOEX_FLAGS_H_INCLUDED_
+
+#define EXTRAIMAGE_REFRESHDELAY 100 /* time for which setting changes are buffered */
+#define STATUSICON_REFRESHDELAY 100 /* time for which setting changes are buffered */
+
+typedef struct _FLAGSOPTIONS
+{
+ BYTE bShowExtraImgFlag;
+ BYTE bUseUnknownFlag;
+ BYTE idExtraColumn;
+// BYTE bUseIpToCountry;
+ BYTE bShowStatusIconFlag;
+} FLAGSOPTIONS, *LPFLAGSOPTIONS;
+
+extern int nCountriesCount;
+extern struct CountryListEntry *countries;
+extern FLAGSOPTIONS gFlagsOpts;
+
+class MsgWndData {
+ public:
+ HANDLE m_hContact;
+ HWND m_hwnd;
+ int m_contryID;
+
+ MsgWndData(HWND hwnd, HANDLE hContact);
+ ~MsgWndData();
+
+ void FlagsIconSet();
+ void FlagsIconUnset();
+ void FlagsIconUpdate() {
+ gFlagsOpts.bShowStatusIconFlag ? FlagsIconSet():FlagsIconUnset();
+ };
+ void ContryIDchange(int ID) {
+ m_contryID = ID; FlagsIconUpdate();
+ };
+};
+
+class IconList {
+ public:
+ int m_ID;
+ HANDLE m_hIcon; //register
+ HANDLE m_hImage; //return value from MS_CLIST_EXTRA_ADD_ICON -INVALID_HANDLE_VALUE; //preset
+ BYTE m_TypeFlag;
+ StatusIconData m_StatusIconData;
+
+ IconList(StatusIconData* sid);
+// IconList(HWND hwnd, HANDLE hContact);
+ ~IconList();
+
+};
+
+typedef void (CALLBACK *BUFFEREDPROC)(LPARAM lParam);
+#ifdef _DEBUG
+ void _CallFunctionBuffered(BUFFEREDPROC pfnBuffProc,const char *pszProcName,LPARAM lParam,BOOL fAccumulateSameParam,UINT uElapse);
+ #define CallFunctionBuffered(proc,param,acc,elapse) _CallFunctionBuffered(proc,#proc,param,acc,elapse)
+#else
+ void _CallFunctionBuffered(BUFFEREDPROC pfnBuffProc,LPARAM lParam,BOOL fAccumulateSameParam,UINT uElapse);
+ #define CallFunctionBuffered(proc,param,acc,elapse) _CallFunctionBuffered(proc,param,acc,elapse)
+#endif
+
+void EnsureExtraImages();
+VOID SvcFlagsEnableExtraIcons(BOOLEAN bEnable, BOOLEAN bUpdateDB);
+void CALLBACK UpdateStatusIcons(LPARAM lParam);
+
+void SvcFlagsLoadModule();
+void SvcFlagsOnModulesLoaded();
+void SvcFlagsUnloadModule();
+
+#endif /* _UINFOEX_FLAGS_H_INCLUDED_ */ \ No newline at end of file
diff --git a/plugins/UserInfoEx/Flags/svc_flagsicons.cpp b/plugins/UserInfoEx/Flags/svc_flagsicons.cpp
new file mode 100644
index 0000000000..d01941e323
--- /dev/null
+++ b/plugins/UserInfoEx/Flags/svc_flagsicons.cpp
@@ -0,0 +1,457 @@
+/*
+UserinfoEx plugin for Miranda IM
+
+Copyright:
+ 2006-2010 DeathAxe, Yasnovidyashii, Merlin, K. Romanov, Kreol
+
+part of this code based on:
+Miranda IM Country Flags Plugin Copyright 2006-2007 H. Herkenrath
+
+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 : $HeadURL: https://userinfoex.googlecode.com/svn/trunk/Flags/svc_flagsicons.cpp $
+Revision : $Revision: 206 $
+Last change on : $Date: 2010-09-28 18:43:50 +0400 (Вт, 28 сен 2010) $
+Last change by : $Author: ing.u.horn $
+
+===============================================================================
+*/
+
+#include "..\commonheaders.h"
+#include "svc_flags.h"
+#include "svc_flagsicons.h"
+
+/************************* Bitmap Access **************************/
+
+static HANDLE *phIconHandles = NULL;
+
+static int CountryNumberToBitmapIndex(int countryNumber)
+{
+ /* country number indices (same order as in flags.bmp) */
+ const int BitmapIndexMap[239]={
+ 0, 1, 7, 20, 27, 30, 31, 32, 33, 34,
+ 36, 38, 39, 40, 41, 43, 44, 45, 46, 47,
+ 48, 49, 51, 52, 53, 54, 55, 56, 57, 58,
+ 60, 61, 62, 63, 64, 65, 66, 81, 82, 84,
+ 86, 90, 91, 92, 93, 94, 95, 98, 212, 213,
+ 216, 218, 220, 221, 222, 223, 224, 225, 226, 227,
+ 228, 229, 230, 231, 232, 233, 234, 235, 236, 237,
+ 238, 239, 240, 241, 242, 243, 244, 245, 246, 247,
+ 248, 249, 250, 251, 252, 253, 254, 255, 256, 257,
+ 258, 260, 261, 263, 264, 265, 266, 267, 268, 269,
+ 290, 291, 297, 298, 299, 350, 351, 352, 353, 354,
+ 355, 356, 357, 358, 359, 370, 371, 372, 373, 374,
+ 375, 376, 377, 378, 379, 380, 381, 382, 383, 385,
+ 386, 387, 389, 420, 421, 423, 441, 442, 500, 501,
+ 502, 503, 504, 505, 506, 507, 508, 509, 591, 592,
+ 593, 595, 597, 598, 599, 614, 670, 673, 674, 675,
+ 676, 677, 678, 679, 680, 681, 682, 683, 685, 686,
+ 688, 689, 690, 691, 692, 705, 850, 852, 853, 855,
+ 856, 880, 886, 960, 961, 962, 963, 964, 965, 966,
+ 967, 968, 971, 972, 973, 974, 975, 976, 977, 992,
+ 993, 994, 995, 996, 998, 1002, 1242, 1246, 1264, 1268,
+ 1284, 1340, 1345, 1441, 1473, 1649, 1664, 1670, 1671, 1684,
+ 1758, 1767, 1784, 1809, 1868, 1869, 1876, 1939, 2897, 3492,
+ 3883, 5995, 5999, 6720, 6723, 9999, 61891, 65535, 90392
+ };
+ /* shared flags by multiple countries */
+ switch(countryNumber) {
+ case 9999: /* Other */
+ case 65535: /* 0xFFFF,"Unknown" */
+ countryNumber=0; /* Unspecified */
+ break;
+ case 262: /* Reunion Island */
+ case 594: /* French Guiana */
+ case 5901: /* remove French Antilles */
+ countryNumber=33; /* France */
+ break;
+ case 120: /* remove Barbuda */
+ countryNumber=1268; /* Antigua and Barbuda */
+ break;
+ case 6702: /* removed Tinian Island */
+ case 6701: /* removed Rota Island */
+ case 670: /* removed Saipan Island */
+ countryNumber=1670; /* Northern Mariana Islands, US Territory of*/
+ break;
+ case 115: /* removed Saint Kitts */
+ case 114: /* removed Nevis */
+ countryNumber=1869; /* Saint Kitts and Nevis */
+ break;
+ case 247: /* Ascension Island */
+ countryNumber=44; /* United Kingdom */
+ break;
+ case 6720: /* Australian Antarctic Territory */
+ countryNumber=61; /* Australia */
+ break;
+ case 5997: /* Netherlands (Bonaire Island)*/
+ case 59946: /* Netherlands (Saba Island) */
+ case 59938: /* Netherlands (St. Eustatius Island) */
+ countryNumber=599; /* Netherlands Antilles (dissolved 2010) */
+ //countryNumber=31; /* Netherlands */
+ break;
+ case 5995: /* St. Maarten (new country in 2010 (from Netherlands Antilles) new country in 2010 (from Netherlands Antilles) ) */
+ countryNumber=599; /* Netherlands Antilles (dissolved 2010) */
+ break;
+ case 5999: /* Curacao (new country in 2010 (from Netherlands Antilles) new country in 2010 (from Netherlands Antilles) ) */
+ countryNumber=599; /* Netherlands Antilles (dissolved 2010) */
+ break;
+ case 5399: /* missing Guantanamo Bay */
+ countryNumber=1; /* USA */
+ }
+ /* binary search in index array */
+ if (countryNumber > 0) {
+ int i,high/*,low=0*/;
+ high=SIZEOF(BitmapIndexMap);
+ /*old code need sortet BitmapIndexMap*/
+ /*if(countryNumber<=BitmapIndexMap[high])
+ while(low<=high) {
+ i=low+((high-low)/2);
+ // never happens
+ if(i<0 || i>=SIZEOF(BitmapIndexMap)) DebugBreak();
+ if(BitmapIndexMap[i]==countryNumber) return i;
+ if(countryNumber>BitmapIndexMap[i]) low=i+1;
+ else high=i-1;
+ }*/
+ for( i=0; i < high; i++ ){
+ if(BitmapIndexMap[i]==countryNumber) return i;
+ }
+ }
+ /* Other,Unknown,Unspecified */
+ return 0;
+}
+
+/************************* Utils **********************************/
+
+HICON LoadFlag(int countryNumber)
+{
+ char szId[20],*szCountry;
+ /* create identifier */
+ szCountry=(char*)CallService(MS_UTILS_GETCOUNTRYBYNUMBER,countryNumber,0);
+ if(szCountry==NULL) {
+ szCountry=(char*)CallService(MS_UTILS_GETCOUNTRYBYNUMBER,countryNumber=0xFFFF,0);
+ }
+ wsprintfA(szId,(countryNumber==0xFFFF)?"%s_0x%X":"%s_%i","flags",countryNumber); /* buffer safe */
+ return (HICON)CallService(MS_SKIN2_GETICON,(WPARAM)0/* =small 1=big*/,(LPARAM)szId);
+}
+
+int CountryNumberToIndex(int countryNumber)
+{
+ int i,nf=0;
+ for(i=0;i<nCountriesCount;++i) {
+ if(countries[i].id==countryNumber) return i;
+ if(countries[i].id==0xFFFF) nf=i;
+ }
+ return nf; /* Unknown */
+}
+
+FIBITMAP* ConvertTo(FIBITMAP* dib, UINT destBits, bool greyscale)
+{
+ FIBITMAP* dib_res = NULL;
+ switch (destBits) {
+ case 8:
+ // convert to 8Bits
+ if(greyscale) {
+ dib_res = FIP->FI_ConvertTo8Bits(dib);
+ }
+ else {
+ FIBITMAP* dib_tmp = FIP->FI_ConvertTo24Bits(dib);
+ if(dib_tmp) {
+ dib_res = FIP->FI_ColorQuantize(dib_tmp, FIQ_WUQUANT/*FIQ_NNQUANT*/);
+ FIP->FI_Unload(dib_tmp);
+ }
+ } break;
+ case 16:
+ // convert to 16Bits
+ dib_res = FIP->FI_ConvertTo16Bits555(dib);
+ break;
+ case 24:
+ // convert to 24Bits
+ dib_res = FIP->FI_ConvertTo24Bits(dib);
+ break;
+ case 32:
+ // convert to 32Bits
+ dib_res = FIP->FI_ConvertTo32Bits(dib);
+ break;
+ default:
+ break;
+ }
+ FIP->FI_Unload(dib);
+ return dib_res;
+}
+
+FIBITMAP* LoadResource(UINT ID, LPTSTR lpType)
+{
+ FIBITMAP *dib = NULL;
+ if(lpType) {
+ HRSRC hResInfo = FindResource(ghInst,MAKEINTRESOURCE(ID),lpType);
+ DWORD ResSize = SizeofResource(ghInst,hResInfo);
+ HGLOBAL hRes = LoadResource(ghInst,hResInfo);
+ BYTE* buffer = (BYTE*)LockResource(hRes);
+ if (buffer)
+ {
+ // attach the binary data to a memory stream
+ FIMEMORY *hmem = FIP->FI_OpenMemory(buffer, ResSize);
+ // get the file type
+ FREE_IMAGE_FORMAT fif = FIP->FI_GetFileTypeFromMemory(hmem, 0);
+ // load an image from the memory stream
+ dib = FIP->FI_LoadFromMemory(fif, hmem, 0);
+ // always close the memory stream
+ FIP->FI_CloseMemory(hmem);
+
+ UnlockResource(buffer);
+ }
+ FreeResource(hRes);
+ }
+ else {
+ HBITMAP hScrBM = 0;
+ if(NULL == (hScrBM = (HBITMAP)LoadImage(ghInst,MAKEINTRESOURCE(ID), IMAGE_BITMAP, 0, 0,LR_SHARED)))
+ return dib;
+ dib = FIP->FI_CreateDIBFromHBITMAP(hScrBM);
+ DeleteObject(hScrBM);
+ }
+ return dib;
+}
+
+/************************* Services *******************************/
+
+static INT_PTR ServiceLoadFlagIcon(WPARAM wParam,LPARAM lParam)
+{
+ /* return handle */
+ if((BOOL)lParam) {
+ if(phIconHandles==NULL) return NULL;
+ return (INT_PTR)phIconHandles[CountryNumberToIndex((int)wParam)];
+ }
+ /* return icon */
+ return (INT_PTR)LoadFlag(wParam);
+}
+
+static INT_PTR ServiceCreateMergedFlagIcon(WPARAM wParam,LPARAM lParam)
+{
+ //TODO: use freeimage to create merget icon and add RGB(A) support
+ HICON hUpperIcon,hLowerIcon;
+ ICONINFO icoi;
+ BITMAP bm;
+ HDC hdc;
+ POINT aptTriangle[3];
+ HICON hIcon=NULL;
+ HRGN hrgn;
+ HBITMAP hbmPrev;
+ /* load both icons */
+ if(NULL == (hLowerIcon=(HICON)ServiceLoadFlagIcon((WPARAM)lParam,0))) return NULL;
+ hUpperIcon=(HICON)ServiceLoadFlagIcon(wParam,0);
+ /* merge them */
+ if(GetIconInfo(hLowerIcon,&icoi)) {
+ if(hUpperIcon!=NULL && GetObject(icoi.hbmColor,sizeof(bm),&bm)) {
+ hdc=CreateCompatibleDC(NULL);
+ if(hdc!=NULL) {
+ ZeroMemory(&aptTriangle,sizeof(aptTriangle));
+ aptTriangle[1].y=bm.bmHeight-1;
+ aptTriangle[2].x=bm.bmWidth-1;
+ hrgn=CreatePolygonRgn(aptTriangle,SIZEOF(aptTriangle),WINDING);
+ if(hrgn!=NULL) {
+ SelectClipRgn(hdc,hrgn);
+ DeleteObject(hrgn);
+ hbmPrev=(HBITMAP)SelectObject(hdc,icoi.hbmColor);
+ if(hbmPrev!=NULL) { /* error on select? */
+ if(DrawIconEx(hdc,0,0,hUpperIcon,bm.bmWidth,bm.bmHeight,0,NULL,DI_NOMIRROR|DI_IMAGE)) {
+ if(SelectObject(hdc,icoi.hbmMask)!=NULL) /* error on select? */
+ DrawIconEx(hdc,0,0,hUpperIcon,bm.bmWidth,bm.bmHeight,0,NULL,DI_NOMIRROR|DI_MASK);
+ }
+ SelectObject(hdc,hbmPrev);
+ }
+ DeleteObject(hrgn);
+ }
+ DeleteDC(hdc);
+ }
+ }
+ /* create icon */
+ hIcon=CreateIconIndirect(&icoi);
+ DeleteObject(icoi.hbmColor);
+ DeleteObject(icoi.hbmMask);
+ }
+ return (INT_PTR)hIcon;
+}
+
+/************************* Misc ***********************************/
+
+VOID InitIcons()
+{
+ HIMAGELIST himl = {0};
+ HBITMAP hScrBM = 0;
+ HBITMAP hbmMask = 0;
+ FIBITMAP *dib = NULL,
+ *dib_ico = NULL;
+ UINT bitDest = ILC_COLOR8,
+ bit = 24;
+
+// BOOL res;
+// FREE_IMAGE_FORMAT fif = FIP->FI_GetFIFFromFilename("dummy.bmp");
+
+ /* all those flag icons storing in a large 24bit opaque bitmap to reduce file size */
+ if(NULL == (dib = LoadResource(IDB_FLAGSPNG,_T("PNG"))))
+ return;
+
+ if (IsWinVerXPPlus()) bitDest = bit = ILC_COLOR32;
+ else if (IsWinVer2000Plus()) bitDest = ILC_COLOR24;
+ else if (IsWinVerMEPlus()) bitDest = ILC_COLOR16;
+ /*else preset bitDest = ILC_COLOR8;*/
+
+ //we work always with 24bit if bitDest < xp+
+ //coz we cannot perform paste operations between palettized images,
+ //unless both src and dst images use the same palette.
+
+ if (FIP->FI_GetBPP(dib) != bit)
+ if (NULL == (dib = ConvertTo(dib, bit, 0))) return;
+
+ //create new dib
+ if (NULL == (dib_ico = FIP->FI_Allocate(FIP->FI_GetWidth(dib), 16, bit,0,0,0))) {
+ FIP->FI_Unload(dib);
+ return;
+ }
+
+// res = FIP->FI_IsTransparent(dib_ico);
+ if(bit<32) {
+ //disable transparency
+ FIP->FI_SetTransparent(dib, FALSE);
+ FIP->FI_SetTransparent(dib_ico, FALSE);
+ }
+
+ UINT h = FIP->FI_GetHeight(dib_ico);
+ UINT w = FIP->FI_GetWidth(dib_ico);
+ UINT t = ((h - FIP->FI_GetHeight(dib))/2)+1;
+ UINT b = t + FIP->FI_GetHeight(dib);
+
+ //copy dib to new dib_ico (centered)
+ if(FIP->FI_Paste(dib_ico, dib, 0, t-1, 255+1)) {
+ FIP->FI_Unload(dib); dib = NULL;
+ switch (bitDest) {
+ case 8:
+ case 16:
+ case 24:
+ {//transparency by 1bit monocrome icon mask (for bit < 32)
+ BYTE value;
+ FIBITMAP *dib_mask;
+ if(NULL == (dib_mask = FIP->FI_Allocate(w, h, 1, 0, 0, 0))) {
+ FIP->FI_Unload(dib_ico);
+ return;
+ }
+ for(unsigned y = 0; y < h; y++)
+ for(unsigned x = 0; x < w; x++) {
+ value = ((y<t || y>=b)? 0:1);
+ FIP->FI_SetPixelIndex(dib_mask, x, y, &value);
+ }
+ hbmMask = FIP->FI_CreateHBITMAPFromDIB(dib_mask);
+ FIP->FI_Unload(dib_mask);
+
+ //convert to target resolution
+ if(!hbmMask || !(dib_ico = ConvertTo(dib_ico, bitDest, 0))) {
+ FIP->FI_Unload(dib_ico);
+ if(hbmMask) DeleteObject(hbmMask);
+ return;
+ }
+ } break;
+ case 32:
+ {//transparency by alpha schannel
+ //Calculate the number of bytes per pixel (3 for 24-bit or 4 for 32-bit)
+ int bytespp = FIP->FI_GetLine(dib_ico) / w;
+ //set alpha schannel
+ for(unsigned y = 0; y < h; y++) {
+ BYTE *bits = FIP->FI_GetScanLine(dib_ico, y);
+ for(unsigned x = 0; x < w; x++) {
+ bits[FI_RGBA_ALPHA] = (y<t || y>=b)? 0:255;
+ // jump to next pixel
+ bits += bytespp;
+ }
+ }
+ } break;
+ default:
+ FIP->FI_Unload(dib_ico);
+ return;
+ }
+ //FIP->FI_SaveU(fif,dib_ico,_T("d:\\CD-Archiv\\Miranda\\trunk\\miranda\\bin9\\Debug Unicode\\Plugins\\dib_ico.bmp"),0);
+ }
+ else {
+ FIP->FI_Unload(dib);
+ FIP->FI_Unload(dib_ico);
+ return;
+ }
+
+ hScrBM = FIP->FI_CreateHBITMAPFromDIB(dib_ico);
+ FIP->FI_Unload(dib_ico);
+
+ if(!hScrBM) {
+ DeleteObject(hbmMask);
+ return;
+ }
+
+ //create ImageList
+ himl = ImageList_Create(16, 16 , bitDest | ILC_MASK, 0, nCountriesCount);
+ ImageList_Add(himl, hScrBM, hbmMask);
+ DeleteObject(hScrBM); hScrBM = NULL;
+ DeleteObject(hbmMask); hbmMask = NULL;
+
+ if(himl!=NULL) {
+ phIconHandles=(HANDLE*)mir_alloc(nCountriesCount*sizeof(HANDLE));
+ if(phIconHandles!=NULL) {
+ char szId[20];
+ int i,index;
+ SKINICONDESC skid;
+
+ /* register icons */
+ ZeroMemory(&skid,sizeof(skid));
+ skid.cbSize = sizeof(skid);
+ skid.ptszSection = LPGENT("Country Flags");
+ skid.pszName = szId; // name to refer to icon when playing and in db
+ //skid.pszDefaultFile = NULL; // default icon file to use
+ //skid.iDefaultIndex = NULL; // index of icon in default file
+ skid.cx = GetSystemMetrics(SM_CXSMICON);
+ skid.cy = GetSystemMetrics(SM_CYSMICON);
+ skid.flags = SIDF_SORTED|SIDF_TCHAR;
+
+ for(i=0;i<nCountriesCount;++i) {
+ skid.ptszDescription = mir_a2t(LPGEN(countries[i].szName));
+ /* create identifier */
+ wsprintfA(szId,(countries[i].id==0xFFFF)?"%s0x%X":"%s%i","flags_",countries[i].id); /* buffer safe */
+ index = CountryNumberToBitmapIndex(countries[i].id);
+ /* create icon */
+ skid.hDefaultIcon=ImageList_ExtractIcon(NULL, himl, index);
+ index = CountryNumberToIndex(countries[i].id);
+
+ phIconHandles[index]=(HANDLE)CallService(MS_SKIN2_ADDICON,0,(LPARAM)&skid);
+ if(skid.hDefaultIcon!=NULL) DestroyIcon(skid.hDefaultIcon);
+ mir_free(skid.ptszDescription); skid.ptszDescription = NULL;
+ }
+ }
+ ImageList_Destroy(himl);
+ }
+
+ /* create services */
+ myCreateServiceFunction(MS_FLAGS_LOADFLAGICON,ServiceLoadFlagIcon);
+ myCreateServiceFunction(MS_FLAGS_CREATEMERGEDFLAGICON,ServiceCreateMergedFlagIcon);
+}
+
+VOID UninitIcons()
+{
+ int i;
+ char szId[20];
+ for(i=0;i<nCountriesCount;++i) {
+ /* create identifier */
+ wsprintfA(szId,(countries[i].id==0xFFFF)?"%s0x%X":"%s%i","flags_",countries[i].id); /* buffer safe */
+ CallService(MS_SKIN2_REMOVEICON,0,(LPARAM)&szId);
+ }
+ mir_free(phIconHandles); /* does NULL check */
+}
diff --git a/plugins/UserInfoEx/Flags/svc_flagsicons.h b/plugins/UserInfoEx/Flags/svc_flagsicons.h
new file mode 100644
index 0000000000..7f29330a11
--- /dev/null
+++ b/plugins/UserInfoEx/Flags/svc_flagsicons.h
@@ -0,0 +1,43 @@
+/*
+UserinfoEx plugin for Miranda IM
+
+Copyright:
+ 2006-2010 DeathAxe, Yasnovidyashii, Merlin, K. Romanov, Kreol
+
+part of this code based on:
+Miranda IM Country Flags Plugin Copyright 2006-2007 H. Herkenrath
+
+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 : $HeadURL: https://userinfoex.googlecode.com/svn/trunk/Flags/svc_flagsicons.h $
+Revision : $Revision: 204 $
+Last change on : $Date: 2010-09-28 16:48:38 +0400 (Вт, 28 сен 2010) $
+Last change by : $Author: ing.u.horn $
+
+===============================================================================
+*/
+#ifndef _UINFOEX_FLAGSICONS_H_INCLUDED_
+#define _UINFOEX_FLAGSICONS_H_INCLUDED_
+
+int CountryNumberToIndex(int countryNumber);
+HICON LoadFlag(int countryNumber);
+
+VOID InitIcons();
+//VOID SvcFlagsOnModulesLoaded();
+VOID UninitIcons();
+
+#endif /* _UINFOEX_FLAGSICONS_H_INCLUDED_ */