diff options
Diffstat (limited to 'plugins/UserInfoEx/Flags/svc_flagsicons.cpp')
-rw-r--r-- | plugins/UserInfoEx/Flags/svc_flagsicons.cpp | 457 |
1 files changed, 457 insertions, 0 deletions
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 */
+}
|