From 48540940b6c28bb4378abfeb500ec45a625b37b6 Mon Sep 17 00:00:00 2001
From: Vadim Dashevskiy <watcherhd@gmail.com>
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_flagsicons.cpp | 457 ++++++++++++++++++++++++++++
 1 file changed, 457 insertions(+)
 create mode 100644 plugins/UserInfoEx/Flags/svc_flagsicons.cpp

(limited to 'plugins/UserInfoEx/Flags/svc_flagsicons.cpp')

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 */
+}
-- 
cgit v1.2.3