From 48540940b6c28bb4378abfeb500ec45a625b37b6 Mon Sep 17 00:00:00 2001 From: Vadim Dashevskiy Date: Tue, 15 May 2012 10:38:20 +0000 Subject: initial commit git-svn-id: http://svn.miranda-ng.org/main/trunk@2 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- plugins/UserInfoEx/Flags/svc_countrylistext.cpp | 326 ++++++++++ plugins/UserInfoEx/Flags/svc_countrylistext.h | 39 ++ plugins/UserInfoEx/Flags/svc_flags.cpp | 765 ++++++++++++++++++++++++ plugins/UserInfoEx/Flags/svc_flags.h | 102 ++++ plugins/UserInfoEx/Flags/svc_flagsicons.cpp | 457 ++++++++++++++ plugins/UserInfoEx/Flags/svc_flagsicons.h | 43 ++ 6 files changed, 1732 insertions(+) create mode 100644 plugins/UserInfoEx/Flags/svc_countrylistext.cpp create mode 100644 plugins/UserInfoEx/Flags/svc_countrylistext.h create mode 100644 plugins/UserInfoEx/Flags/svc_flags.cpp create mode 100644 plugins/UserInfoEx/Flags/svc_flags.h create mode 100644 plugins/UserInfoEx/Flags/svc_flagsicons.cpp create mode 100644 plugins/UserInfoEx/Flags/svc_flagsicons.h (limited to 'plugins/UserInfoEx/Flags') 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=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)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;iszModule, "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;im_hContact - (INT_PTR)p2->m_hContact); +} +static LIST 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 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;iFI_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=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=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