diff options
Diffstat (limited to 'plugins/LangMan/src')
| -rw-r--r-- | plugins/LangMan/src/common.h | 56 | ||||
| -rw-r--r-- | plugins/LangMan/src/langpack.cpp | 454 | ||||
| -rw-r--r-- | plugins/LangMan/src/langpack.h | 49 | ||||
| -rw-r--r-- | plugins/LangMan/src/main.cpp | 160 | ||||
| -rw-r--r-- | plugins/LangMan/src/options.cpp | 672 | ||||
| -rw-r--r-- | plugins/LangMan/src/options.h | 27 | ||||
| -rw-r--r-- | plugins/LangMan/src/resource.h | 49 | ||||
| -rw-r--r-- | plugins/LangMan/src/utils.cpp | 67 | ||||
| -rw-r--r-- | plugins/LangMan/src/utils.h | 23 | ||||
| -rw-r--r-- | plugins/LangMan/src/version.h | 35 | 
10 files changed, 1592 insertions, 0 deletions
diff --git a/plugins/LangMan/src/common.h b/plugins/LangMan/src/common.h new file mode 100644 index 0000000000..4ac9deb5b5 --- /dev/null +++ b/plugins/LangMan/src/common.h @@ -0,0 +1,56 @@ +/*
 +
 +'Language Pack Manager'-Plugin for Miranda IM
 +
 +Copyright (C) 2005-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 (LangMan-License.txt); if not, write to the Free Software
 +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 +*/
 +
 +#define _CRT_SECURE_NO_WARNINGS
 +
 +#define __RPCASYNC_H__        /* header shows warnings in VS6 */
 +#include <windows.h>
 +#pragma warning(disable:4201) /* nonstandard extension used : nameless struct/union */
 +#include <commctrl.h>
 +#pragma warning(default:4201) /* nonstandard extension used : nameless struct/union */
 +#include <ShlObj.h>
 +#include <vsstyle.h>
 +
 +#include <tchar.h>
 +#include <stdio.h>            /* for mir_snprintf() */
 +#include <time.h>             /* for time() */
 +
 +#define MIRANDA_VER  0x0600
 +#include <newpluginapi.h>
 +#include <m_system.h>
 +#include <m_utils.h>
 +#include <m_database.h>
 +#include <m_langpack.h>
 +#include <m_options.h>
 +#include <m_skin.h>
 +#include <m_icolib.h>
 +#include <m_flags.h>
 +#include <m_netlib.h>
 +#include <m_clist.h>
 +#include <win2k.h>
 +
 +#include "langpack.h"
 +#include "options.h"
 +//#include "update.h"
 +//#include "unzip.h"
 +#include "utils.h"
 +#include "resource.h"
 +#include "m_langman.h"
 diff --git a/plugins/LangMan/src/langpack.cpp b/plugins/LangMan/src/langpack.cpp new file mode 100644 index 0000000000..0f783e0bbe --- /dev/null +++ b/plugins/LangMan/src/langpack.cpp @@ -0,0 +1,454 @@ +/*
 +
 +'Language Pack Manager'-Plugin for Miranda IM
 +
 +Copyright (C) 2005-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 (LangMan-License.txt); if not, write to the Free Software
 +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 +*/
 +
 +#include "common.h"
 +
 +/************************* Load ***************************************/
 +
 +static void TrimString(char *str)
 +{
 +	int len, start;
 +	len = lstrlenA(str);
 +	while (str[0]!='\0' && (unsigned char)str[len-1] <= ' ') str[--len] = 0;
 +	for (start = 0; str[start] && (unsigned char)str[start] <= ' '; ++start);
 +	MoveMemory(str, str+start, len-start+1);
 +}
 +
 +static BOOL IsEmpty(const char *str)
 +{
 +	int i;
 +	for(i = 0;str[i]!='\0';i++)
 +		if (str[i]!=' ' && str[i]!='\r' && str[i]!='\n')
 +			return FALSE;
 +	return TRUE;
 +}
 +
 +static void CleanupLanguage(char *szLanguage)
 +{
 +	char *p;
 +	/* remove any appended ' (default)' */
 +	p = strstr(szLanguage, " (default)");
 +	if (p!=NULL) *p = '\0';
 +}
 +
 +static void CleanupAuthors(char *szAuthors)
 +{
 +	char *p, *p2;
 +	/* remove trailing dot (if any) */
 +	p = &szAuthors[lstrlenA(szAuthors)-1];
 +	if (*p == '.') *p = '\0';
 +	/* remove any extra info in parentheses, which is ok
 +	 * but makes the list very long for some packs */
 +	for (;;) {
 +		p = strchr(szAuthors, '(');
 +		p2 = strchr(szAuthors, ')');
 +		if (p == NULL || p2 == NULL) {
 +			p = strchr(szAuthors, '[');
 +			p2 = strchr(szAuthors, ']');
 +			if (p == NULL || p2 == NULL) break;
 +		}
 +		if (*(p-1) == ' ') --p;
 +		MoveMemory(p, p2+1, lstrlenA(p2+1)+1);
 +	}
 +}
 +
 +static void CleanupEmail(char *szAuthorEmail)
 +{
 +	char c, *p, *pAt;
 +	/* replace ' dot ' with '.' (may be removed) */
 +	p = strstr(szAuthorEmail, " dot ");
 +	if (p!=NULL) {
 +		*p = '.';
 +		MoveMemory(p+1, p+5, lstrlenA(p+5)+1);
 +	}
 +	/* also allow ' at ' instead of '@' for obfuscation */
 +	p = strstr(szAuthorEmail, " at ");
 +	if (p!=NULL) {
 +		*p = '@';
 +		MoveMemory(p+1, p+4, lstrlenA(p+4)+1);
 +	}
 +	/* is valid? */
 +	pAt = strchr(szAuthorEmail, '@');
 +	if (pAt == NULL) {
 +		szAuthorEmail[0] = '\0';
 +		return;
 +	}
 +	/* strip-off extra text except exactly one email address
 +	 * this is needed as a click on the email addres brings up the mail client */
 +	for(c = ' ';;c = ',') {
 +		p = strchr(pAt, c);
 +		if (p!=NULL) *p = '\0';
 +		p = strrchr(szAuthorEmail, c);
 +		if (p!=NULL) MoveMemory(szAuthorEmail, p+1, lstrlenA(p+1)+1);
 +		if (c == ',') break;
 +	}
 +	p = strstr(szAuthorEmail, "__");
 +	if (p!=NULL) MoveMemory(szAuthorEmail, p+2, lstrlenA(p+2)+1);
 +	/* lower case */
 +	CharLowerA(szAuthorEmail);
 +	/* 'none' specified */
 +	if (!lstrcmpiA(szAuthorEmail, "none")) szAuthorEmail[0] = '\0';
 +}
 +
 +static void CleanupLastModifiedUsing(char *szLastModifiedUsing, int nSize)
 +{
 +	char *p;
 +	/* remove 'Unicode', as it doesn't matter */
 +	p = strstr(szLastModifiedUsing, " Unicode");
 +	if (p!=NULL) MoveMemory(p, p+8, lstrlenA(p+8)+1);
 +	/* use 'Miranda IM' instead of 'Miranda' */
 +	p = strstr(szLastModifiedUsing, "Miranda");
 +	if (p!=NULL && strncmp(p+7, " IM", 3)) {
 +		MoveMemory(p+10, p+7, lstrlenA(p+7)+1);
 +		CopyMemory(p+7, " IM", 3);
 +	}
 +	/* use 'Plugin' instead of 'plugin' */
 +	p = strstr(szLastModifiedUsing, " plugin");
 +	if (p!=NULL) CopyMemory(p, " Plugin", 7);
 +	/* remove 'v' prefix */
 +	p = strstr(szLastModifiedUsing, " v0.");
 +	if (p!=NULL) MoveMemory(p+1, p+2, lstrlenA(p+2)+1);
 +	/* default if empty */
 +	if (!szLastModifiedUsing[0]) {
 +		lstrcpynA(szLastModifiedUsing, MIRANDANAME" ", nSize);
 +		CallService(MS_SYSTEM_GETVERSIONTEXT, nSize-lstrlenA(szLastModifiedUsing), (LPARAM)szLastModifiedUsing+lstrlenA(szLastModifiedUsing));
 +	}
 +}
 +
 +// pack struct should be initialized to zero before call
 +// pack->szFileName needs to be filled in before call
 +static BOOL LoadPackData(LANGPACK_INFO *pack, BOOL fEnabledPacks, const char *pszFileVersionHeader)
 +{
 +	FILE *fp;
 +	TCHAR szFileName[MAX_PATH];
 +	char line[4096], *pszColon, *buf;
 +	char szLanguageA[64]; /* same size as pack->szLanguage */
 +	/*
 +		Miranda Language Pack Version 1
 +		Language: (optional)
 +		Locale: 0809
 +		Authors: Miranda IM Development Team (multiple tags allowed)
 +		Author-email: project-info at miranda-im.org (" at " instead of "@" allowed)
 +		Last-Modified-Using: Miranda IM 0.7
 +		Plugins-included: (multiple tags allowed)
 +		X-FLName: name as used on the file listing (non-standard extension)
 +		X-Version: 1.2.3.4 (non-standard extension)
 +		see 'LangMan-Translation.txt' for some header quidelines 
 +	*/
 +	if ( !GetPackPath( szFileName, SIZEOF(szFileName), fEnabledPacks, pack->szFileName))
 +		return FALSE;
 +
 +	fp = _tfopen(szFileName, _T("rt"));
 +	if (fp  ==  NULL)
 +		return FALSE;
 +
 +	fgets(line, sizeof(line), fp);
 +	TrimString(line);
 +	buf = line;
 +
 +	if (strlen(line) >=  3 && line[0]  ==  '\xef' && line[1]  ==  '\xbb' && line[2]  ==  '\xbf') {
 +		pack->codepage = CP_UTF8;
 +		buf += 3;
 +	}
 +
 +	if ( lstrcmpA(buf, pszFileVersionHeader )) {
 +		fclose(fp);
 +		return FALSE;
 +	}
 +	pack->flags = LPF_NOLOCALE;
 +	szLanguageA[0] = '\0';
 +	while( !feof( fp )) {
 +		if ( fgets(line, sizeof(line), fp)  ==  NULL) break;
 +		TrimString(line);
 +		if ( IsEmpty(line) || line[0] == ';' || line[0] == '\0') continue;
 +		if ( line[0] == '[' ) break;
 +		pszColon = strchr(line, ':');
 +		if ( pszColon  ==  NULL ) continue;
 +		*pszColon = '\0';
 +		TrimString(pszColon+1);
 +		if ( !lstrcmpA(line, "Language") && !pack->szLanguage[0] )
 +			lstrcpynA(szLanguageA, pszColon+1, sizeof(szLanguageA)); /* buffer safe */
 +		else if ( !lstrcmpA(line, "Last-Modified-Using") && !pack->szLastModifiedUsing[0] )
 +			lstrcpynA(pack->szLastModifiedUsing, pszColon+1, sizeof(pack->szLastModifiedUsing)); /* buffer safe */
 +		else if ( !lstrcmpA(line, "Authors")) {
 +			buf = pack->szAuthors+lstrlenA(pack->szAuthors); /* allow multiple tags */
 +			if ((sizeof(pack->szAuthors)-lstrlenA(pack->szAuthors))>0) /* buffer safe */
 +				mir_snprintf(buf, sizeof(pack->szAuthors)-lstrlenA(pack->szAuthors), (pack->szAuthors[0] == '\0')?"%s":" %s", pszColon+1);
 +		} else if ( !lstrcmpA(line, "Author-email") && !pack->szAuthorEmail[0])
 +			lstrcpynA(pack->szAuthorEmail, pszColon+1, sizeof(pack->szAuthorEmail)); /* buffer safe */
 +		else if ( !lstrcmpA(line, "Locale") && (pack->flags & LPF_NOLOCALE)) {
 +			pack->Locale = MAKELCID((USHORT)strtol(pszColon+1, NULL, 16), SORT_DEFAULT);
 +			if (pack->Locale) pack->flags &= ~LPF_NOLOCALE;
 +		}
 +		else if ( !lstrcmpA(line, "Plugins-included")) {
 +			buf = pack->szPluginsIncluded + lstrlenA(pack->szPluginsIncluded); /* allow multiple tags */
 +			if (( sizeof(pack->szPluginsIncluded)-lstrlenA(pack->szPluginsIncluded)) > 0 ) /* buffer safe */
 +				mir_snprintf(buf, sizeof(pack->szPluginsIncluded)-lstrlenA(pack->szPluginsIncluded), (pack->szPluginsIncluded[0] == '\0')?"%s":", %s", CharLowerA(pszColon+1));
 +		}
 +		else if ( !lstrcmpA(line, "X-Version") && !pack->szVersion[0] )
 +			lstrcpynA(pack->szVersion, pszColon+1, sizeof(pack->szVersion)); /* buffer safe */
 +		else if ( !lstrcmpA(line, "X-FLName") && !pack->szFLName[0] )
 +			lstrcpynA(pack->szFLName, pszColon+1, sizeof(pack->szFLName)); /* buffer safe */
 +	}
 +	CleanupLanguage(szLanguageA);
 +	CleanupAuthors(pack->szAuthors);
 +	CleanupEmail(pack->szAuthorEmail);
 +	CleanupLastModifiedUsing(pack->szLastModifiedUsing, sizeof(pack->szLastModifiedUsing));
 +	/* codepage */
 +	if (!(pack->flags&LPF_NOLOCALE))
 +		if (GetLocaleInfoA(pack->Locale, LOCALE_IDEFAULTANSICODEPAGE, line, 6))
 +			pack->codepage = (WORD)atoi(line); /* CP_ACP on error */
 +	/* language */
 +
 +	MultiByteToWideChar(pack->codepage, 0, szLanguageA, -1, pack->szLanguage, SIZEOF(pack->szLanguage));
 +
 +	/* ensure the pack always has a language name */
 +	if (!pack->szLanguage[0] && !GetLocaleInfo(pack->Locale, LOCALE_SENGLANGUAGE, pack->szLanguage, SIZEOF(pack->szLanguage))) {
 +		TCHAR *p;
 +		lstrcpyn(pack->szLanguage, pack->szFileName, SIZEOF(pack->szLanguage)); /* buffer safe */
 +		p = _tcsrchr(pack->szLanguage, _T('.'));
 +		if (p!=NULL) *p = '\0';
 +	}
 +	/* ensure the pack always has a filelisting name */
 +	if (!pack->szFLName[0])
 +		lstrcatA(lstrcpyA(pack->szFLName, szLanguageA), " Language Pack"); /* buffer safe */
 +	fclose(fp);
 +	return TRUE;
 +}
 +
 +/************************* Enum ***************************************/
 +
 +BOOL GetPackPath(TCHAR *pszPath, int nSize, BOOL fEnabledPacks, const TCHAR *pszFile)
 +{
 +	TCHAR *p;
 +	/* main path */
 +	if (!GetModuleFileName(NULL, pszPath, nSize)) return FALSE;
 +	p = _tcsrchr(pszPath, _T('\\'));
 +	if (p!=NULL) *(p+1) = _T('\0');
 +	/* subdirectory */
 +	if (!fEnabledPacks) {
 +		if (nSize<(lstrlen(pszPath)+10)) return FALSE;
 +		lstrcat(pszPath, _T("Plugins\\Language\\"));
 +	}
 +	/* file name */
 +	if (pszFile!=NULL) {
 +		if (nSize<(lstrlen(pszFile)+11)) return FALSE;
 +		lstrcat(pszPath, pszFile);
 +	}
 +	return TRUE;
 +}
 +
 +// callback is allowed to be NULL
 +// returns TRUE if any pack exists except default
 +BOOL EnumPacks(ENUM_PACKS_CALLBACK callback, const TCHAR *pszFilePattern, const char *pszFileVersionHeader, BOOL fEnglishDefault, WPARAM wParam, LPARAM lParam)
 +{
 +	BOOL fPackFound = FALSE;
 +	BOOL res = FALSE;
 +	LANGPACK_INFO pack;
 +	WIN32_FIND_DATA wfd;	
 +	HANDLE hFind;
 +
 +	/* enabled packs */
 +	if (GetPackPath(pack.szFileName, SIZEOF(pack.szFileName), TRUE, pszFilePattern)) {
 +		hFind = FindFirstFile(pack.szFileName, &wfd);
 +		if (hFind!=INVALID_HANDLE_VALUE) {
 +			do {
 +				if (wfd.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY) continue;
 +				if ((lstrlen(wfd.cFileName)<4) || wfd.cFileName[lstrlen(wfd.cFileName)-4]!=_T('.')) continue;
 +				/* get data */
 +				ZeroMemory(&pack, sizeof(pack));
 +				lstrcpy(pack.szFileName, CharLower(wfd.cFileName)); /* buffer safe */
 +				if (LoadPackData(&pack, TRUE, pszFileVersionHeader)) {
 +					pack.ftFileDate = wfd.ftLastWriteTime;
 +					/* enabled? */
 +					if (!fPackFound) pack.flags |= LPF_ENABLED;
 +					fPackFound = TRUE;
 +					/* callback */
 +					if (callback!=NULL) res = callback(&pack, wParam, lParam);
 +					if (!res) { FindClose(hFind); return FALSE; }
 +				}
 +			} while(FindNextFile(hFind, &wfd));
 +			FindClose(hFind);
 +		}
 +	}
 +
 +	/* default: English (GB) */
 +	if (fEnglishDefault && callback!=NULL) {
 +		ZeroMemory(&pack, sizeof(pack));
 +		pack.Locale = LOCALE_USER_DEFAULT; /* miranda uses default locale in this case */
 +		lstrcpy(pack.szLanguage, _T("English (default)")); /* buffer safe */
 +		lstrcpyA(pack.szAuthors, "Miranda IM Development Team"); /* buffer safe */
 +		lstrcpyA(pack.szAuthorEmail, "project-info at miranda-im.org"); /* buffer safe */
 +		CleanupEmail(pack.szAuthorEmail); /* correct " at " */
 +		CleanupLastModifiedUsing(pack.szLastModifiedUsing, sizeof(pack.szLastModifiedUsing));
 +		/* file date */
 +		if (GetModuleFileName(NULL, pack.szFileName, SIZEOF(pack.szFileName))) {
 +			HANDLE hFile;
 +			hFile = CreateFile(pack.szFileName, 0, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
 +			if (hFile!=INVALID_HANDLE_VALUE) {
 +				GetFileTime(hFile, NULL, NULL, &pack.ftFileDate);
 +				CloseHandle(hFile);
 +			}
 +		}
 +		pack.flags = LPF_NOLOCALE|LPF_DEFAULT;
 +		if (!fPackFound) pack.flags |= LPF_ENABLED;
 +		/* callback */
 +		if (!callback(&pack, wParam, lParam)) return FALSE;
 +	}
 +
 +	/* disabled packs */
 +	if (GetPackPath(pack.szFileName, SIZEOF(pack.szFileName), FALSE, pszFilePattern)) {
 +		hFind = FindFirstFile(pack.szFileName, &wfd);
 +		if (hFind!=INVALID_HANDLE_VALUE) {
 +			do {
 +				if (wfd.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY) continue;
 +				if (lstrlen(wfd.cFileName)<4 || wfd.cFileName[lstrlen(wfd.cFileName)-4]!=_T('.')) continue;
 +				/* get data */
 +				ZeroMemory(&pack, sizeof(pack));
 +				lstrcpy(pack.szFileName, CharLower(wfd.cFileName)); /* buffer safe */
 +				if (LoadPackData(&pack, FALSE, pszFileVersionHeader)) {
 +					pack.ftFileDate = wfd.ftLastWriteTime;
 +					fPackFound = TRUE;
 +					/* callback */
 +					if (callback!=NULL) res = callback(&pack, wParam, lParam);
 +					if (!res) { FindClose(hFind); return FALSE; }
 +				}
 +			} while(FindNextFile(hFind, &wfd));
 +			FindClose(hFind);
 +		}
 +	}
 +	return fPackFound;
 +}
 +
 +BOOL IsPluginIncluded(const LANGPACK_INFO *pack, char *pszFileBaseName)
 +{
 +	char *p;
 +	if (!lstrcmpiA(pszFileBaseName, "png2dib") || !lstrcmpiA(pszFileBaseName, "loadavatars"))
 +		return TRUE; /* workaround: does not need no translation */
 +	for(p = (char*)pack->szPluginsIncluded;;) {
 +		p = strstr(p, CharLowerA(pszFileBaseName));
 +		if (p == NULL) return FALSE;
 +		if (p == pack->szPluginsIncluded || *(p-1) == ' ' || *(p-1) == ',') {
 +			p+=lstrlenA(pszFileBaseName)+1;
 +			if (*p == ',' || *p == ' ' || *p == 0) return TRUE;
 +		}
 +		else p+=lstrlenA(pszFileBaseName)+1;
 +	}
 +}
 +
 +/************************* Switch *************************************/
 +
 +BOOL EnablePack(const LANGPACK_INFO *pack, const TCHAR *pszFilePattern)
 +{
 +	TCHAR szFrom[MAX_PATH], szDest[MAX_PATH];
 +	HANDLE hFind;
 +	WIN32_FIND_DATA wfd;
 +	
 +	/* disable previous pack */
 +	if (GetPackPath(szFrom, SIZEOF(szFrom), TRUE, pszFilePattern)) {
 +		hFind = FindFirstFile(szFrom, &wfd);
 +		if (hFind!=INVALID_HANDLE_VALUE) {
 +			do {
 +				if (wfd.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY) continue;
 +				if (lstrlen(wfd.cFileName)<4 || wfd.cFileName[lstrlen(wfd.cFileName)-4]!=_T('.')) continue;
 +				/* ensure dir exists */
 +				if (GetPackPath(szFrom, SIZEOF(szFrom), FALSE, NULL))
 +					CreateDirectory(szFrom, NULL);
 +				/* move file */
 +				if (GetPackPath(szFrom, SIZEOF(szFrom), TRUE, wfd.cFileName))
 +					if (GetPackPath(szDest, SIZEOF(szDest), FALSE, wfd.cFileName))
 +						if (!MoveFile(szFrom, szDest) && GetLastError() == ERROR_ALREADY_EXISTS) {
 +							DeleteFile(szDest);
 +							MoveFile(szFrom, szDest);
 +						}
 +				break;
 +			} while(FindNextFile(hFind, &wfd));
 +			FindClose(hFind);
 +		}
 +	}
 +
 +	/* enable current pack */
 +	if (pack->flags&LPF_DEFAULT) return TRUE;
 +	if (GetPackPath(szFrom, SIZEOF(szFrom), FALSE, pack->szFileName))
 +		if (GetPackPath(szDest, SIZEOF(szDest), TRUE, pack->szFileName)) 
 +			return MoveFile(szFrom, szDest);
 +	return FALSE;
 +}
 +
 +void CorrectPacks(const TCHAR *pszFilePattern, BOOL fDisableAll)
 +{
 +	TCHAR szFrom[MAX_PATH], szDest[MAX_PATH], szDir[MAX_PATH], *pszFile;
 +	BOOL fDirCreated = FALSE;
 +	HANDLE hFind;
 +	WIN32_FIND_DATA wfd;
 +
 +	/* main path */
 +	if (!GetModuleFileName(NULL, szDir, SIZEOF(szDir))) return;
 +	pszFile = _tcsrchr(szDir, _T('\\'));
 +	if (pszFile!=NULL) *pszFile = _T('\0');
 +
 +	/* move wrongly placed packs from 'Plugins' to 'Language' */
 +	mir_sntprintf(szFrom, SIZEOF(szFrom), _T("%s\\Plugins\\%s"), szDir, pszFilePattern);
 +	hFind = FindFirstFile(szFrom, &wfd);
 +	if (hFind!=INVALID_HANDLE_VALUE) {
 +		do {
 +			if (wfd.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY) continue;
 +			if (lstrlen(wfd.cFileName)<4 || wfd.cFileName[lstrlen(wfd.cFileName)-4]!=_T('.')) continue;
 +			/* ensure dir exists */
 +			if (!fDirCreated && GetPackPath(szFrom, SIZEOF(szFrom), FALSE, NULL))
 +				fDirCreated = CreateDirectory(szFrom, NULL);
 +			/* move file */
 +			if (GetPackPath(szDest, SIZEOF(szDest), FALSE, wfd.cFileName)) {
 +				mir_sntprintf(szFrom, SIZEOF(szFrom), _T("%s\\Plugins\\%s"), szDir, wfd.cFileName);
 +				if (!MoveFile(szFrom, szDest) && GetLastError() == ERROR_ALREADY_EXISTS) {
 +					DeleteFile(szDest);
 +					MoveFile(szFrom, szDest);
 +				}
 +			}
 +		} while(FindNextFile(hFind, &wfd));
 +		FindClose(hFind);
 +	}
 +
 +	/* disable all packs except one */
 +	if (GetPackPath(szFrom, SIZEOF(szFrom), TRUE, pszFilePattern)) {
 +		hFind = FindFirstFile(szFrom, &wfd);
 +		if (hFind!=INVALID_HANDLE_VALUE) {
 +			do {
 +				if (wfd.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY) continue;
 +				if (lstrlen(wfd.cFileName)<4 || wfd.cFileName[lstrlen(wfd.cFileName)-4]!=_T('.')) continue;
 +				/* skip first file */
 +				if (!fDisableAll) { fDisableAll = TRUE; continue; }
 +				/* ensure dir exists */
 +				if (!fDirCreated && GetPackPath(szFrom, SIZEOF(szFrom), FALSE, NULL))
 +					fDirCreated = CreateDirectory(szFrom, NULL);
 +				/* move file */
 +				if (GetPackPath(szFrom, SIZEOF(szFrom), TRUE, wfd.cFileName))
 +					if (GetPackPath(szDest, SIZEOF(szDest), FALSE, wfd.cFileName)) {
 +						if (!MoveFile(szFrom, szDest) && GetLastError() == ERROR_ALREADY_EXISTS) {
 +							DeleteFile(szDest);
 +							MoveFile(szFrom, szDest);
 +						}
 +					}
 +			} while(FindNextFile(hFind, &wfd));
 +			FindClose(hFind);
 +		}
 +	}
 +}
\ No newline at end of file diff --git a/plugins/LangMan/src/langpack.h b/plugins/LangMan/src/langpack.h new file mode 100644 index 0000000000..354286b405 --- /dev/null +++ b/plugins/LangMan/src/langpack.h @@ -0,0 +1,49 @@ +/*
 +
 +'Language Pack Manager'-Plugin for Miranda IM
 +
 +Copyright (C) 2005-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 (LangMan-License.txt); if not, write to the Free Software
 +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 +*/
 +
 +/* Langpack Info */
 +typedef struct {
 +	TCHAR szLanguage[64];
 +	LCID Locale;
 +	WORD codepage;
 +	char szAuthors[1024];
 +	char szAuthorEmail[128];
 +	char szLastModifiedUsing[64];
 +	char szPluginsIncluded[4080];
 +	char szVersion[21];
 +	char szFLName[128];
 +	FILETIME ftFileDate;
 +	TCHAR szFileName[MAX_PATH]; /* just the file name itself */
 +	BYTE flags; /* see LPIF_* flags */
 +} LANGPACK_INFO;
 +#define LPF_ENABLED   0x01  // pack is enabled
 +#define LPF_NOLOCALE  0x02  // pack has no valid locale
 +#define LPF_DEFAULT   0x04  // pack is the english default (no langpack)
 +
 +/* Enum */
 +BOOL GetPackPath(TCHAR *pszPath, int nSize, BOOL fEnabledPacks, const TCHAR *pszFile);
 +typedef BOOL (*ENUM_PACKS_CALLBACK)(LANGPACK_INFO *pack, WPARAM wParam, LPARAM lParam);
 +BOOL EnumPacks(ENUM_PACKS_CALLBACK callback, const TCHAR *pszFilePattern, const char *pszFileVersionHeader, BOOL fEnglishDefault, WPARAM wParam, LPARAM lParam);
 +BOOL IsPluginIncluded(const LANGPACK_INFO *pack, char *pszFileBaseName);
 +
 +/* Switch */
 +BOOL EnablePack(const LANGPACK_INFO *pack, const TCHAR *pszFilePattern);
 +void CorrectPacks(const TCHAR *pszFilePattern, BOOL fDisableAll);
 diff --git a/plugins/LangMan/src/main.cpp b/plugins/LangMan/src/main.cpp new file mode 100644 index 0000000000..2309bf1ec8 --- /dev/null +++ b/plugins/LangMan/src/main.cpp @@ -0,0 +1,160 @@ +/*
 +
 +'Language Pack Manager'-Plugin for Miranda IM
 +
 +Copyright (C) 2005-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 (LangMan-License.txt); if not, write to the Free Software
 +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 +*/
 +
 +#include "common.h"
 +#include "version.h"
 +
 +HINSTANCE hInst;
 +
 +static HANDLE hHookModulesLoaded;
 +int hLangpack;
 +
 +static PLUGININFOEX pluginInfo = {
 +	sizeof(PLUGININFOEX), 
 +	"Language Pack Manager", 
 +	PLUGIN_VERSION, 
 +	"Helps you manage Language Packs of different languages.", /* autotranslated */
 +	"H. Herkenrath", 
 +	"hrathh@users.sourceforge.net",
 +	"© 2005-2007 H. Herkenrath", 
 +	PLUGIN_WEBSITE, 
 +	UNICODE_AWARE, 
 +	// {D4BDD1EB-56F1-4a87-A187-67246EE919A2}
 +	{0xd4bdd1eb, 0x56f1, 0x4a87, {0xa1, 0x87, 0x67, 0x24, 0x6e, 0xe9, 0x19, 0xa2}}, 
 +};
 +
 +///////////////////////////////////////////////////////////////////////////////
 +
 +BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, void*)
 +{
 +	if (fdwReason  ==  DLL_PROCESS_ATTACH)
 +		hInst = hinstDLL;
 +
 +	return TRUE;
 +}
 +
 +///////////////////////////////////////////////////////////////////////////////
 +
 +static void InstallFile(const TCHAR *pszFileName, const TCHAR *pszDestSubDir)
 +{
 +	TCHAR szFileFrom[MAX_PATH+1], szFileTo[MAX_PATH+1];
 +	if ( !GetModuleFileName(hInst, szFileFrom, SIZEOF(szFileFrom) - lstrlen(pszFileName)))
 +		return;
 +
 +	TCHAR *p = _tcsrchr(szFileFrom, _T('\\'));
 +	if ( p != NULL ) *(++p) = 0;
 +	lstrcat(szFileFrom, pszFileName); /* buffer safe */
 +
 +	HANDLE hFile = CreateFile(szFileFrom, 0, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
 +	if ( hFile  ==  INVALID_HANDLE_VALUE ) return;
 +	CloseHandle(hFile);
 +
 +	if ( !GetModuleFileName(NULL, szFileTo, SIZEOF(szFileTo) - lstrlen(pszDestSubDir) - lstrlen(pszFileName)))
 +		return;
 +	
 +	p = _tcsrchr(szFileTo, _T('\\'));
 +	if ( p != NULL ) *(++p) = 0;
 +	lstrcat(szFileTo, pszDestSubDir); /* buffer safe */
 +	CreateDirectory(szFileTo, NULL);
 +	lstrcat(szFileTo, pszFileName);  /* buffer safe */
 +
 +	if ( !MoveFile(szFileFrom, szFileTo) && GetLastError()  ==  ERROR_ALREADY_EXISTS) {
 +		DeleteFile(szFileTo);
 +		MoveFile(szFileFrom, szFileTo);
 +	}
 +}
 +
 +#ifdef __cplusplus
 +extern "C" {
 +#endif 
 +
 +///////////////////////////////////////////////////////////////////////////////
 +
 +__declspec(dllexport) const PLUGININFOEX* MirandaPluginInfoEx(DWORD)
 +{
 +	return &pluginInfo;
 +}
 +
 +///////////////////////////////////////////////////////////////////////////////
 +
 +extern "C" __declspec(dllexport) const MUUID MirandaInterfaces[] = {MIID_LANGMAN, MIID_LAST};
 +
 +///////////////////////////////////////////////////////////////////////////////
 +
 +static int LangManModulesLoaded(WPARAM, LPARAM)
 +{
 +	if ( ServiceExists("DBEditorpp/RegisterSingleModule"))
 +		CallService("DBEditorpp/RegisterSingleModule", (WPARAM)"LangMan", 0);
 +	return 0;
 +}
 +
 +__declspec(dllexport) int Load(void)
 +{
 +
 +	mir_getLP( &pluginInfo );
 +	
 +	/* existance of MS_SYSTEM_GETVERSION and MS_LANGPACK_TRANSLATESTRING
 +	 * is checked in MirandaPluginInfo().
 +	 * Not placed in MirandaPluginInfo() to avoid MessageBoxes on plugin options. 
 +	 * Using ANSI as LANG_UNICODE might not be supported. */
 +	if ( CallService(MS_SYSTEM_GETVERSION, 0, 0) < NEEDED_MIRANDA_VERSION ) {
 +		char szText[256];
 +		mir_snprintf(szText, sizeof(szText), Translate("The Language Pack Manager Plugin can not be loaded. It requires Miranda IM %hs or later."), NEEDED_MIRANDA_VERSION_STR);
 +		MessageBoxA(NULL, szText, Translate("Language Pack Manager Plugin"), MB_OK|MB_ICONERROR|MB_SETFOREGROUND|MB_TOPMOST|MB_TASKMODAL);
 +		return 1;
 +	}
 +
 +	INITCOMMONCONTROLSEX icc;
 +	icc.dwSize = sizeof(icc);
 +	icc.dwICC = ICC_TREEVIEW_CLASSES|ICC_USEREX_CLASSES;
 +	InitCommonControlsEx(&icc);
 +	InitOptions();
 +
 +	/* menu item */
 +
 +	CLISTMENUITEM mi = {0};
 +	mi.cbSize = sizeof(mi);
 +	mi.position = 2000089999;
 +	mi.icolibItem = LoadIcon(hInst, MAKEINTRESOURCE(IDI_RELOAD));
 +	mi.pszName = LPGEN("Reload langpack");
 +	mi.pszService = MS_LANGPACK_RELOAD;
 +	Menu_AddMainMenuItem(&mi);
 +
 +	/* installation */
 +	InstallFile(_T("LangMan-Readme.txt"), _T("Docs\\"));
 +	InstallFile(_T("LangMan-License.txt"), _T("Docs\\"));
 +	InstallFile(_T("LangMan-SDK.zip"), _T("Docs\\"));
 +	hHookModulesLoaded = HookEvent(ME_SYSTEM_MODULESLOADED, LangManModulesLoaded);
 +	return 0;
 +}
 +
 +///////////////////////////////////////////////////////////////////////////////
 +
 +__declspec(dllexport) int Unload(void)
 +{
 +	UninitOptions();
 +	UnhookEvent(hHookModulesLoaded);
 +	return 0;
 +}
 +
 +#ifdef __cplusplus
 +}
 +#endif
 diff --git a/plugins/LangMan/src/options.cpp b/plugins/LangMan/src/options.cpp new file mode 100644 index 0000000000..72f78dd597 --- /dev/null +++ b/plugins/LangMan/src/options.cpp @@ -0,0 +1,672 @@ +/*
 +
 +'Language Pack Manager'-Plugin for Miranda IM
 +
 +Copyright (C) 2005-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 (LangMan-License.txt); if not, write to the Free Software
 +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 +*/
 +
 +#include "common.h"
 +
 +extern HINSTANCE hInst;
 +static HANDLE hHookOptInit;
 +
 +/************************* Utils **************************************/
 +
 +#define BOX(str)        BOX2("%s (err:%i)", str, GetLastError())
 +#define BOX2(fmt, p1, p2) { char str[256]; wsprintfA(str, fmt, p1, p2); MessageBoxA(NULL, str, "dbg", 0); }
 +
 +// ImageList_Destroy() the return value
 +// refresh on WM_THEMECHANGED
 +static HIMAGELIST CreateRadioImages(COLORREF clrBk, COLORREF clrText)
 +{
 +	register HDC hdc, hdcScreen;
 +	SIZE size;
 +	RECT rc;
 +	HBITMAP hbm, hbmPrev;
 +	HIMAGELIST himl = NULL;
 +
 +	/* the WinXP+ themed way */
 +	HMODULE hUxThemeDLL;
 +	HTHEME  (WINAPI *pfnOpenThemeData)(HWND, const WCHAR*);
 +	HTHEME  (WINAPI *pfnCloseThemeData)(HTHEME);
 +	HRESULT (WINAPI *pfnDrawThemeBackground)(HTHEME, HDC, int, int, const RECT*, const RECT*);
 +	hUxThemeDLL = LoadLibraryA("UXTHEME"); /* all ascii */
 +
 +	/* draw bitmap */
 +	hdcScreen = GetDC(NULL);
 +	if (hdcScreen!=NULL) {
 +		hdc = CreateCompatibleDC(NULL); /* compatible to screen */
 +		if (hdc!=NULL) {
 +			size.cx = GetSystemMetrics(SM_CXSMICON);
 +			size.cy = GetSystemMetrics(SM_CYSMICON);
 +			SetRect(&rc, 0, 0, 2*size.cx, size.cy);
 +			hbm = CreateCompatibleBitmap(hdcScreen, rc.right, rc.bottom);
 +			if (hbm!=NULL) {
 +				hbmPrev = (HBITMAP)SelectObject(hdc, hbm);
 +				if (hbmPrev!=NULL) { /* error on select? */
 +					/* the WinXP+ themed way */
 +					if (hUxThemeDLL!=NULL) {
 +						*(PROC*)&pfnOpenThemeData = GetProcAddress(hUxThemeDLL, "OpenThemeData");
 +						*(PROC*)&pfnCloseThemeData = GetProcAddress(hUxThemeDLL, "CloseThemeData");
 +						*(PROC*)&pfnDrawThemeBackground = GetProcAddress(hUxThemeDLL, "DrawThemeBackground");
 +						if (pfnOpenThemeData!=NULL && pfnCloseThemeData!=NULL && pfnDrawThemeBackground!=NULL) {
 +							HTHEME hTheme;
 +							hTheme = pfnOpenThemeData(NULL, L"Button");
 +							if (hTheme!=NULL) {
 +								SetRect(&rc, 0, 0, size.cx, size.cy);
 +								/* unchecked */
 +								if (!pfnDrawThemeBackground(hTheme, hdc, BP_RADIOBUTTON, RBS_UNCHECKEDNORMAL, &rc, NULL)) {
 +									/* checked */
 +									OffsetRect(&rc, size.cx, 0);
 +									if (!pfnDrawThemeBackground(hTheme, hdc, BP_RADIOBUTTON, RBS_CHECKEDNORMAL, &rc, NULL))
 +										himl = ImageList_Create(size.cx, size.cy, ILC_COLOR32|ILC_MASK, 3, 0);
 +								}
 +								pfnCloseThemeData(hTheme);
 +							}
 +						}
 +					}
 +					/* the classic way */
 +					if (himl == NULL) {
 +						register HDC hdcMono;
 +						HBITMAP hbmMono, hbmPrevMono;
 +						RECT rcRadio;
 +						COLORREF clrPrevText, clrPrevBk;
 +						HBRUSH hbrBk;
 +						hbrBk = CreateSolidBrush(clrBk);
 +						if (hbrBk!=NULL) {
 +							FillRect(hdc, &rc, hbrBk);
 +							DeleteObject(hbrBk);
 +							hdcMono = CreateCompatibleDC(hdc);
 +							if (hdcMono!=NULL) {
 +								hbmMono = CreateBitmap(rc.right, rc.bottom, 1, 1, NULL);
 +								if (hbmMono!=NULL) {
 +									hbmPrevMono = (HBITMAP)SelectObject(hdcMono, hbmMono);
 +									if (hbmPrevMono!=NULL) { /* error on select? */
 +										/* draws a black-and-white mask (see docs) 
 +										 * we need to colorize it using BitBlt with text and background color */
 +										clrPrevText = SetTextColor(hdc, clrText);
 +										clrPrevBk = SetBkColor(hdc, clrBk);
 +										/* check mark is slightly smaller than icon size */
 +										SetRect(&rcRadio, 0, 0, GetSystemMetrics(SM_CXMENUCHECK), GetSystemMetrics(SM_CYMENUCHECK));
 +										if (rcRadio.right>size.cx) rcRadio.right = size.cx;
 +										if (rcRadio.bottom>size.cy) rcRadio.bottom = size.cy;
 +										SetRect(&rc, ((size.cx-rcRadio.right)/2)+1, ((size.cy-rcRadio.bottom)/2)+1, rcRadio.right+1, rcRadio.bottom+1);
 +										/* unchecked */
 +										if (BitBlt(hdcMono, 0, 0, rcRadio.right, rcRadio.bottom, NULL, 0, 0, WHITENESS)) { /* white back */
 +											if (DrawFrameControl(hdcMono, &rcRadio, DFC_BUTTON, DFCS_BUTTONRADIO|DFCS_FLAT)) {
 +												if (BitBlt(hdc, rc.left, rc.top, rcRadio.right, rcRadio.bottom, hdcMono, 0, 0, SRCCOPY|NOMIRRORBITMAP)) {
 +													/* checked */
 +													OffsetRect(&rc, size.cx, 0);
 +													if (BitBlt(hdcMono, 0, 0, rcRadio.right, rcRadio.bottom, NULL, 0, 0, WHITENESS)) {/* white back */
 +														if (DrawFrameControl(hdcMono, &rcRadio, DFC_BUTTON, DFCS_BUTTONRADIO|DFCS_FLAT|DFCS_CHECKED)) {
 +															if (BitBlt(hdc, rc.left, rc.top, rcRadio.right, rcRadio.bottom, hdcMono, 0, 0, SRCCOPY|NOMIRRORBITMAP))
 +																himl = ImageList_Create(size.cx, size.cy, ILC_COLOR|ILC_MASK, 3, 0);
 +														} else BOX("second DrawFrameControl() failed");
 +													} else BOX("second BitBlt() failed");
 +												} else BOX("intermediate BitBlt() failed");
 +											} else BOX("DrawFrameControl() failed");
 +										} else BOX("first BitBlt() failed");
 +										/* restore */
 +										SetBkColor(hdc, clrPrevBk);
 +										SetTextColor(hdc, clrPrevText);
 +										SelectObject(hdcMono, hbmPrevMono);
 +									} else BOX("hbmPrevMono == NULL");
 +									DeleteObject(hbmMono);
 +								} else BOX("hbmMono == NULL");
 +								DeleteDC(hdcMono);
 +							} else BOX("hdcMono == NULL");
 +						}
 +					}
 +					SelectObject(hdc, hbmPrev);
 +					/* create imagelist */
 +					if (himl!=NULL) {
 +						if (himl == NULL) BOX("img list create failed");
 +						if (himl!=NULL) if (ImageList_AddMasked(himl, hbm, clrBk) == -1) BOX("add failed");
 +					} else BOX("Win9x: drawing code not reached");
 +				}
 +				DeleteObject(hbm);
 +			}
 +			DeleteDC(hdc);
 +		}
 +		ReleaseDC(NULL, hdcScreen);
 +	}
 +
 +	if (hUxThemeDLL!=NULL) FreeLibrary(hUxThemeDLL);
 +	return himl;
 +}
 +
 +static void CleanupPluginName(char *szShortName)
 +{
 +	char *p;
 +	int len;
 +	/* strip-off anything in brackets */
 +	for(p = szShortName;*p!='\0';++p)
 +		if (*p == '(' || *p == '[') {
 +			*p = '\0';
 +			break;
 +		}
 +	/* remove trailing space */
 +	len = lstrlenA(szShortName);
 +	while(szShortName[0]!='\0' && szShortName[len-1] == ' ')
 +		szShortName[--len] = 0;
 +}
 +
 +static void DisplayNotIncludedPlugins(HWND hwndListBox, const LANGPACK_INFO *pack)
 +{
 +	WIN32_FIND_DATA wfd;
 +	HANDLE hFind;
 +	TCHAR szSearch[MAX_PATH], szDir[MAX_PATH], *p;
 +	HMODULE hModule;
 +	BOOL fNeedsFree;
 +	char buf[128];
 +	TCHAR buf2[128];
 +	DWORD mirandaVersion;
 +	PLUGININFOEX *pluginInfo;
 +	PLUGININFOEX *(__cdecl *MirandaPluginInfo)(DWORD);
 +
 +	/* enum plugins */
 +	if (!(pack->flags&LPF_DEFAULT) && GetModuleFileName(NULL, szDir, SIZEOF(szDir))) {
 +		p = _tcsrchr(szDir, _T('\\'));
 +		if (p!=NULL) *p = _T('\0');
 +		mir_sntprintf(szSearch, SIZEOF(szSearch), _T("%s\\Plugins\\*.dll"), szDir);
 +		hFind = FindFirstFile(szSearch, &wfd);
 +		if (hFind!=INVALID_HANDLE_VALUE) {
 +			mirandaVersion = CallService(MS_SYSTEM_GETVERSION, 0, 0);
 +			SendMessage(hwndListBox, LB_SETLOCALE, CallService(MS_LANGPACK_GETLOCALE, 0, 0), 0); /* for sort order */
 +			SendMessage(hwndListBox, LB_INITSTORAGE, 128, lstrlenA(pack->szPluginsIncluded)); /* speed up */
 +			do {
 +				if (wfd.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY) continue;
 +				if ((lstrlen(wfd.cFileName)<4) || (wfd.cFileName[lstrlen(wfd.cFileName)-4]!=_T('.'))) continue;
 +				/* file name */
 +				lstrcpy(szSearch, wfd.cFileName); /* buffer safe */
 +				p = _tcsrchr(szSearch, _T('.'));
 +				if (p!=NULL) *p = _T('\0');
 +
 +				{	char cFileNameA[MAX_PATH];
 +					cFileNameA[0] = '\0';
 +					WideCharToMultiByte(CP_ACP, 0, szSearch, -1, cFileNameA, sizeof(cFileNameA), NULL, NULL);
 +					if (IsPluginIncluded(pack, cFileNameA)) continue;
 +				}
 +
 +				/* friendly name of the plugin */
 +				mir_sntprintf(szSearch, SIZEOF(szSearch), _T("%s\\Plugins\\%s"), szDir, wfd.cFileName);
 +				hModule = GetModuleHandle(szSearch);
 +				fNeedsFree = (hModule == NULL);
 +				if (hModule == NULL) {
 +					hModule = LoadLibrary(szSearch);
 +					if (hModule == NULL) continue;
 +				}
 +				/* plugin info */
 +				*(PROC*)&MirandaPluginInfo = GetProcAddress(hModule, "MirandaPluginInfoEx");
 +				if (MirandaPluginInfo!=NULL) { /* both structs have the same header */
 +					pluginInfo = MirandaPluginInfo(mirandaVersion);
 +					if (pluginInfo!=NULL && pluginInfo->cbSize >= sizeof(PLUGININFOEX) && pluginInfo->shortName!=NULL) {
 +						lstrcpynA(buf, pluginInfo->shortName, sizeof(buf)); /* buffer safe */
 +						CleanupPluginName(buf);
 +						mir_sntprintf(buf2, SIZEOF(buf2), TranslateT("%hs (%s)"), buf, CharLower(wfd.cFileName));
 +						SendMessage(hwndListBox, LB_ADDSTRING, 0, (LPARAM)buf2);
 +					}
 +				}
 +				if (fNeedsFree) FreeLibrary(hModule);
 +			} while(FindNextFile(hFind, &wfd));
 +			FindClose(hFind);
 +		}
 +	}
 +	/* all are included? */
 +	if (!SendMessage(hwndListBox, LB_GETCOUNT, 0, 0))
 +		SendMessage(hwndListBox, LB_ADDSTRING, 0, (LPARAM)TranslateT("All installed plugins are included."));
 +}
 +
 +static void DisplayPackInfo(HWND hwndDlg, const LANGPACK_INFO *pack)
 +{
 +	/* compute not-included from included list */
 +	SendDlgItemMessage(hwndDlg, IDC_LANGNOTINCLUDED, LB_RESETCONTENT, 0, 0);
 +	DisplayNotIncludedPlugins(GetDlgItem(hwndDlg, IDC_LANGNOTINCLUDED), pack);
 +	/* locale string */
 +	if (!(pack->flags&LPF_NOLOCALE)) {
 +		TCHAR szLocaleName[128];
 +		szLocaleName[0] = _T('\0');
 +		/* can't use LOCALE_SNAME as it is not present on pre WinVista */
 +		if (!GetLocaleInfo(pack->Locale, LOCALE_SISO639LANGNAME, szLocaleName, SIZEOF(szLocaleName))) { /* Win98/NT4+ */
 +			if (!GetLocaleInfo(pack->Locale, LOCALE_SLANGUAGE, szLocaleName, SIZEOF(szLocaleName))) /* not unique! */
 +				szLocaleName[0] = _T('\0');
 +		} else {
 +			if (GetLocaleInfo(pack->Locale, LOCALE_SISO3166CTRYNAME, &szLocaleName[3], SIZEOF(szLocaleName)-3)) /* Win98/NT4+ */
 +				szLocaleName[2] = _T('-');
 +		}
 +		/* add some note if its incompatible */
 +		if (szLocaleName[0]) {
 +			if (!IsValidLocale(pack->Locale, LCID_INSTALLED)) {
 +				TCHAR *pszIncompat;
 +				pszIncompat = TranslateT("(incompatible)");
 +				szLocaleName[SIZEOF(szLocaleName)-lstrlen(pszIncompat)-1] = 0;
 +				lstrcat(lstrcat(szLocaleName, _T(" ")), pszIncompat); /* buffer safe */
 +			}
 +			SetDlgItemText(hwndDlg, IDC_LANGLOCALE, szLocaleName);
 +		}
 +		else SetDlgItemText(hwndDlg, IDC_LANGLOCALE, TranslateT("Unknown"));
 +	}
 +	else SetDlgItemText(hwndDlg, IDC_LANGLOCALE, TranslateT("Current"));
 +	/* file date */
 +	{	SYSTEMTIME stFileDate;
 +		TCHAR szDate[128];
 +		szDate[0] = _T('\0');
 +		if (FileTimeToSystemTime(&pack->ftFileDate, &stFileDate))
 +			GetDateFormat((LCID)CallService(MS_LANGPACK_GETLOCALE, 0, 0), DATE_SHORTDATE, &stFileDate, NULL, szDate, SIZEOF(szDate));
 +		SetDlgItemText(hwndDlg, IDC_LANGDATE, szDate);
 +	}
 +	/* version */
 +	SetDlgItemTextA(hwndDlg, IDC_LANGVERSION, pack->szVersion);
 +	if (pack->szVersion[0] && pack->szFLName[0]) {
 +		if (!IsWindowVisible(GetDlgItem(hwndDlg, IDC_LANGVERSIONLABEL))) {
 +			ShowWindow(GetDlgItem(hwndDlg, IDC_LANGVERSIONLABEL), SW_SHOW);
 +			ShowWindow(GetDlgItem(hwndDlg, IDC_LANGVERSION), SW_SHOW);
 +		}
 +	} else {
 +		ShowWindow(GetDlgItem(hwndDlg, IDC_LANGVERSIONLABEL), SW_HIDE);
 +		ShowWindow(GetDlgItem(hwndDlg, IDC_LANGVERSION), SW_HIDE);
 +	}
 +	/* general */
 +	SetDlgItemTextA(hwndDlg, IDC_LANGMODUSING, pack->szLastModifiedUsing);
 +	SetDlgItemTextA(hwndDlg, IDC_LANGAUTHORS, pack->szAuthors);
 +	SetDlgItemTextA(hwndDlg, IDC_LANGEMAIL, pack->szAuthorEmail);
 +	SetDlgItemText(hwndDlg, IDC_LANGINFOFRAME, TranslateTS(pack->szLanguage));
 +}
 +
 +/************************* Insert/Delete ******************************/
 +
 +#define M_RELOADLIST   (WM_APP+1)
 +#define M_SHOWFILECOL  (WM_APP+2)
 +
 +static void DeletePackFile(HWND hwndDlg, HWND hwndList, int iItem, LANGPACK_INFO *pack)
 +{
 +	SHFILEOPSTRUCT sfo;
 +	TCHAR szFileName[MAX_PATH];
 +	ZeroMemory(&sfo, sizeof(sfo));
 +	sfo.hwnd = hwndDlg;
 +	sfo.wFunc = FO_DELETE;
 +	sfo.fFlags = FOF_SIMPLEPROGRESS|FOF_SILENT; /* silent = no progress */
 +	/* double zero terminated */
 +	if (GetPackPath(szFileName, SIZEOF(szFileName)-1, pack->flags&LPF_ENABLED, pack->szFileName)) {
 +		szFileName[lstrlen(szFileName)+1] = _T('\0');
 +		sfo.pFrom = szFileName;
 +		/* ask to delete file */
 +		if (!SHFileOperation(&sfo) && !sfo.fAnyOperationsAborted) {
 +			LVITEM lvi;
 +			int nCount;
 +			lvi.iItem = iItem;
 +			lvi.iSubItem = 0;
 +			lvi.mask = LVIF_STATE;
 +			lvi.stateMask = LVIS_STATEIMAGEMASK|LVIS_SELECTED|LVIS_FOCUSED;
 +			if (ListView_GetItem(hwndList, &lvi)) {
 +				ListView_DeleteItem(hwndList, iItem);
 +				/* enable/select next item at same position */
 +				nCount = ListView_GetItemCount(hwndList);
 +				if (iItem<nCount) lvi.iItem = iItem;
 +				else lvi.iItem = iItem-1;
 +				ListView_SetItemState(hwndList, lvi.iItem, lvi.state, lvi.stateMask);
 +				if (nCount == 1) SendMessage(hwndDlg, M_SHOWFILECOL, 0, FALSE);
 +			}
 +		}
 +	}
 +}
 +
 +static BOOL InsertPackItemEnumProc(LANGPACK_INFO *pack, WPARAM wParam, LPARAM lParam)
 +{
 +	LVITEM lvi;
 +	LANGPACK_INFO *pack2;
 +	UNREFERENCED_PARAMETER(lParam);
 +
 +	pack2 = (LANGPACK_INFO*)mir_alloc(sizeof(LANGPACK_INFO));
 +	if (pack2 == NULL) return FALSE;
 +	CopyMemory(pack2, pack, sizeof(LANGPACK_INFO));
 +	/* country flag icon */
 +	lvi.mask = LVIF_TEXT|LVIF_PARAM|LVIF_STATE;
 +	if ((HIMAGELIST)lParam!=NULL) {
 +		HICON hIcon;
 +		if (pack->flags&LPF_DEFAULT)
 +			hIcon = (HICON)CallService(MS_FLAGS_CREATEMERGEDFLAGICON, CTRY_UNITED_STATES, CTRY_UNITED_KINGDOM);
 +		else {
 +			int countryId = 0xFFFF; /* Unknown */
 +			TCHAR szBuf[6];
 +			/* get country id from locale */
 +			if (!(pack->flags&LPF_NOLOCALE))
 +				if (GetLocaleInfo(pack->Locale, LOCALE_ICOUNTRY, szBuf, SIZEOF(szBuf)))
 +					countryId = _ttoi(szBuf);
 +			hIcon = (HICON)CallService(MS_FLAGS_LOADFLAGICON, countryId, 0);
 +		}
 +		if (hIcon == NULL) lvi.iImage = -1;
 +		else lvi.iImage = ImageList_AddIcon((HIMAGELIST)lParam, hIcon);
 +		lvi.mask |= LVIF_IMAGE;
 +	}
 +	/* insert */
 +	lvi.iItem = lvi.iSubItem = 0;
 +	lvi.stateMask = LVIS_STATEIMAGEMASK|LVIS_SELECTED;
 +	lvi.state = INDEXTOSTATEIMAGEMASK((pack->flags&LPF_ENABLED)?2:1);
 +	if (pack->flags & LPF_ENABLED) lvi.state |= LVIS_SELECTED|LVIS_FOCUSED;
 +	lvi.pszText = TranslateTS(pack->szLanguage);
 +	lvi.lParam = (LPARAM)pack2;
 +	ListView_InsertItem((HWND)wParam, &lvi);
 +
 +	return TRUE;
 +}
 +
 +static int CALLBACK CompareListItem(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
 +{
 +	int cmp;
 +	cmp = CompareString((LCID)lParamSort, 0, ((LANGPACK_INFO*)lParam1)->szLanguage, -1, ((LANGPACK_INFO*)lParam2)->szLanguage, -1);
 +	if (cmp!=0) cmp -= 2;
 +	return cmp;
 +}
 +
 +/************************* Options Page *******************************/
 +
 +static HWND hwndLangOpt;
 +
 +static INT_PTR CALLBACK LangOptDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
 +{
 +	switch(msg) {
 +		case WM_INITDIALOG:
 +		{	HWND hwndList;
 +			LVCOLUMN lvc;
 +			hwndList = GetDlgItem(hwndDlg, IDC_LANGLIST);
 +			hwndLangOpt = hwndDlg;
 +			TranslateDialogDefault(hwndDlg);
 +			ListView_SetExtendedListViewStyle(hwndList, LVS_EX_FULLROWSELECT|LVS_EX_LABELTIP);
 +			ListView_SetImageList(hwndList, CreateRadioImages(ListView_GetBkColor(hwndList), ListView_GetTextColor(hwndList)), LVSIL_STATE); /* auto-destroyed */
 +
 +			lvc.mask = LVCF_TEXT;
 +			lvc.pszText = TranslateT("Installed Languages");
 +			ListView_InsertColumn(hwndList, 0, &lvc);
 +			if (ServiceExists(MS_FLAGS_LOADFLAGICON))
 +				ListView_SetImageList(hwndList, ImageList_Create(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), ILC_COLOR24, 8, 8), LVSIL_SMALL); 
 +			CorrectPacks(_T("langpack_*.txt"), FALSE);
 +			CheckDlgButton(hwndDlg, IDC_ENABLEAUTOUPDATES, DBGetContactSettingByte(NULL, "LangMan", "EnableAutoUpdates", SETTING_ENABLEAUTOUPDATES_DEFAULT)!=0);
 +			SendMessage(hwndDlg, M_RELOADLIST, 0, 0);
 +			SendMessage(hwndDlg, M_SHOWFILECOL, 0, SendMessage(GetParent(hwndDlg), PSM_ISEXPERT, 0, 0));
 +			return TRUE;
 +		}
 +		case M_RELOADLIST:
 +		{	HWND hwndList;
 +			HIMAGELIST himl;
 +			int iItem;
 +			/* init list */
 +			hwndList = GetDlgItem(hwndDlg, IDC_LANGLIST);
 +			ListView_DeleteAllItems(hwndList);
 +			ListView_DeleteColumn(hwndList, 1); /* if present */
 +			himl = ListView_GetImageList(hwndList, LVSIL_SMALL);
 +			ImageList_RemoveAll(himl);
 +			/* enum all packs */
 +			EnumPacks(InsertPackItemEnumProc, _T("langpack_*.txt"), "Miranda Language Pack Version 1", TRUE, (WPARAM)hwndList, (LPARAM)himl);
 +			/* make it use current langpack locale for sort */
 +			ListView_SortItems(hwndList, CompareListItem, CallService(MS_LANGPACK_GETLOCALE, 0, 0));
 +			CheckDlgButton(hwndDlg, IDC_ENABLEAUTOUPDATES, DBGetContactSettingByte(NULL, "LangMan", "EnableAutoUpdates", SETTING_ENABLEAUTOUPDATES_DEFAULT)!=0);
 +			/* show selection */
 +			iItem = ListView_GetNextItem(hwndList, -1, LVNI_SELECTED);
 +			if (iItem!=-1) ListView_EnsureVisible(hwndList, iItem, FALSE);
 +			return TRUE;
 +		}
 +		case M_SHOWFILECOL:
 +		{	HWND hwndList;
 +			hwndList = GetDlgItem(hwndDlg, IDC_LANGLIST);
 +			if ((BOOL)lParam && ListView_GetItemCount(hwndList)>1) {
 +				LVCOLUMN lvc;
 +				LVITEM lvi;
 +				LANGPACK_INFO *pack;
 +				/* add column */
 +				ListView_SetColumnWidth(hwndList, 0, LVSCW_AUTOSIZE_USEHEADER);
 +				lvc.mask = LVCF_TEXT|LVCF_WIDTH|LVCF_SUBITEM;
 +				lvc.pszText = TranslateT("File");
 +				lvc.cx = 160;
 +				ListView_InsertColumn(hwndList, lvc.iSubItem = 1, &lvc);
 +				ListView_SetColumnWidth(hwndList, 0, ListView_GetColumnWidth(hwndList, 0)-lvc.cx);
 +				/* add text */
 +				lvi.mask = LVIF_PARAM;
 +				lvi.iSubItem = 0;
 +				for(lvi.iItem = 0;ListView_GetItem(hwndList, &lvi);++lvi.iItem) {
 +					pack = (LANGPACK_INFO*)lvi.lParam;
 +					ListView_SetItemText(hwndList, lvi.iItem, 1, (pack->flags&LPF_DEFAULT)?TranslateT("built-in"):pack->szFileName);
 +				}
 +			}
 +			else {
 +				ListView_DeleteColumn(hwndList, 1);
 +				ListView_SetColumnWidth(hwndList, 0, LVSCW_AUTOSIZE_USEHEADER);
 +			}
 +			return TRUE;
 +		}
 +		case WM_DESTROY:
 +			ListView_DeleteAllItems(GetDlgItem(hwndDlg, IDC_LANGLIST));
 +			return TRUE;
 +		case WM_THEMECHANGED:
 +		case WM_SETTINGCHANGE:
 +		{	HIMAGELIST himl;
 +			HWND hwndList;
 +			hwndList = GetDlgItem(hwndDlg, IDC_LANGLIST);
 +			himl = ListView_SetImageList(hwndList, CreateRadioImages(ListView_GetBkColor(hwndList), ListView_GetTextColor(hwndList)), LVSIL_STATE); /* auto-destroyed */
 +			if (himl!=NULL) ImageList_Destroy(himl);
 +			break;
 +		}
 +		case WM_CTLCOLORLISTBOX: /* mimic readonly edit */
 +			return (BOOL)SendMessage(hwndDlg, WM_CTLCOLORSTATIC, wParam, lParam);
 +		case WM_COMMAND:
 +			switch(LOWORD(wParam)) {
 +				case IDC_LANGEMAIL:
 +				{	char buf[512];
 +					lstrcpyA(buf, "mailto:");
 +					if (GetWindowTextA(GetDlgItem(hwndDlg, LOWORD(wParam)), &buf[7], sizeof(buf)-7))
 +						CallService(MS_UTILS_OPENURL, FALSE, (LPARAM)buf);
 +					return TRUE;
 +				}
 +				case IDC_MORELANG:
 +					CallService(MS_UTILS_OPENURL, TRUE, (LPARAM)"http://addons.miranda-im.org/index.php?action = display&id = 23");
 +					return TRUE;
 +/*				case IDC_ENABLEAUTOUPDATES:
 +					SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); /* enable apply */
 +/*					return TRUE;
 +				case IDC_DOWNLOADLANG:
 +					ServiceShowLangDialog(0, 0);
 +					return TRUE;*/
 +			}
 +			break;
 +		case WM_CONTEXTMENU:
 +			if (GetDlgCtrlID((HWND)wParam) == IDC_LANGLIST) {
 +				LVHITTESTINFO hti;
 +				HMENU hContextMenu;
 +				RECT rc;
 +				LVITEM lvi;
 +				LANGPACK_INFO *pack;
 +				/* get item */
 +				POINTSTOPOINT(hti.pt, MAKEPOINTS(lParam));
 +				if (hti.pt.x == -1 && hti.pt.y == -1) {
 +					/* keyboard invoked */
 +					hti.iItem = ListView_GetNextItem((HWND)wParam, -1, LVNI_SELECTED);
 +					if (hti.iItem!=-1)
 +						break;
 +					if (!ListView_GetItemRect((HWND)wParam, hti.iItem, &rc, LVIR_SELECTBOUNDS))
 +						break;
 +					hti.pt.x = rc.left+(rc.right-rc.left)/2;
 +					hti.pt.y = rc.top+(rc.bottom-rc.top)/2;
 +					ClientToScreen((HWND)wParam, &hti.pt);
 +				} else {
 +					ScreenToClient((HWND)wParam, &hti.pt);
 +					if (ListView_HitTest((HWND)wParam, &hti) == -1 || !(hti.flags&LVHT_ONITEM))
 +						break;
 +					POINTSTOPOINT(hti.pt, MAKEPOINTS(lParam));
 +				}
 +				/* param */
 +				lvi.iItem = hti.iItem;
 +				lvi.iSubItem = 0;
 +				lvi.mask = LVIF_PARAM;
 +				if (!ListView_GetItem((HWND)wParam, &lvi)) break;
 +				pack = (LANGPACK_INFO*)lvi.lParam;
 +				/* context menu */
 +				if (!(pack->flags&LPF_DEFAULT)) {
 +					hContextMenu = CreatePopupMenu();
 +					if (hContextMenu!=NULL) {
 +						AppendMenu(hContextMenu, MF_STRING, 2, TranslateT("&Remove..."));
 +						if (TrackPopupMenuEx(hContextMenu, TPM_RETURNCMD|TPM_NONOTIFY|TPM_TOPALIGN|TPM_LEFTALIGN|TPM_RIGHTBUTTON|TPM_HORPOSANIMATION|TPM_VERPOSANIMATION, hti.pt.x, hti.pt.y, (HWND)wParam, NULL))
 +							DeletePackFile(hwndDlg, (HWND)wParam, hti.iItem, pack);
 +						DestroyMenu(hContextMenu);
 +					}
 +				}
 +				return TRUE;
 +			}
 +			break;
 +
 +		case WM_NOTIFYFORMAT:
 +			SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, NFR_UNICODE);
 +			return TRUE;
 +
 +		case WM_NOTIFY:
 +		{	NMHDR *nmhdr = (NMHDR*)lParam;
 +			switch(nmhdr->idFrom) {
 +				case IDC_LANGLIST:
 +					switch(nmhdr->code) {
 +						case LVN_DELETEITEM:
 +						{	LVITEM lvi;
 +							lvi.iItem = ((NMLISTVIEW*)lParam)->iItem; /* nmlv->lParam is invalid */
 +							lvi.iSubItem = 0;
 +							lvi.mask = LVIF_PARAM;
 +							if (ListView_GetItem(nmhdr->hwndFrom, &lvi))
 +								mir_free((LANGPACK_INFO*)lvi.lParam);
 +							break;
 +						}
 +						case LVN_ITEMCHANGED:
 +						{	NMLISTVIEW *nmlv = (NMLISTVIEW*)lParam;
 +							if (!(nmlv->uChanged&LVIF_STATE)) break;
 +							/* display info and check radio item */
 +							if (nmlv->uNewState&LVIS_SELECTED && !(nmlv->uOldState&LVIS_SELECTED)) {
 +								ListView_SetItemState(nmhdr->hwndFrom, nmlv->iItem, INDEXTOSTATEIMAGEMASK(2), LVIS_STATEIMAGEMASK);
 +								DisplayPackInfo(hwndDlg, (LANGPACK_INFO*)nmlv->lParam);
 +							}
 +							/* disable all other radio items */
 +							else if (nmlv->uNewState&INDEXTOSTATEIMAGEMASK(2)) {
 +								int iItem;
 +								for(iItem = ListView_GetItemCount(nmhdr->hwndFrom)-1;iItem!=-1;--iItem)
 +									if (iItem!=nmlv->iItem)
 +										ListView_SetItemState(nmhdr->hwndFrom, iItem, INDEXTOSTATEIMAGEMASK(1), LVIS_STATEIMAGEMASK);
 +								/* enable apply */
 +								if (nmlv->uOldState) {
 +									SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
 +									ShowWindow(GetDlgItem(hwndDlg, IDC_RESTART), SW_SHOW);
 +								}
 +							}
 +							break;
 +						}
 +						case LVN_KEYDOWN:
 +						{	int iItem;
 +							iItem = ListView_GetNextItem(nmhdr->hwndFrom, -1, LVNI_SELECTED);
 +							switch(((NMLVKEYDOWN*)lParam)->wVKey) {
 +								case VK_SPACE:
 +									ListView_SetItemState(nmhdr->hwndFrom, iItem, INDEXTOSTATEIMAGEMASK(2), LVIS_STATEIMAGEMASK);
 +									break;
 +								case VK_DELETE:
 +								{	LVITEM lvi;
 +									LANGPACK_INFO *pack;
 +									lvi.iItem = iItem;
 +									lvi.iSubItem = 0;
 +									lvi.mask = LVIF_PARAM;
 +									if (ListView_GetItem(nmhdr->hwndFrom, &lvi)) {
 +										pack = (LANGPACK_INFO*)lvi.lParam;
 +										if (!(pack->flags&LPF_DEFAULT))
 +											DeletePackFile(hwndDlg, nmhdr->hwndFrom, iItem, pack);
 +									}
 +									break;
 +								}
 +							}
 +							break;
 +						}
 +						case NM_CLICK:
 +						{	LVHITTESTINFO hti;
 +							lParam = GetMessagePos();
 +							POINTSTOPOINT(hti.pt, MAKEPOINTS(lParam));
 +							ScreenToClient(nmhdr->hwndFrom, &hti.pt);
 +							if (ListView_HitTest(nmhdr->hwndFrom, &hti)!=-1)
 +								if (hti.flags&(LVHT_ONITEMSTATEICON|LVHT_ONITEMICON)) /* one of them */
 +									ListView_SetItemState(nmhdr->hwndFrom, hti.iItem, LVIS_SELECTED, LVIS_SELECTED);
 +							break;
 +						}
 +					} /* switch nmhdr->code */
 +					break;
 +				case 0:
 +					switch(nmhdr->code) {
 +						case PSN_APPLY:
 +						{	HWND hwndList;
 +							LVITEM lvi;
 +							LANGPACK_INFO *pack;
 +							hwndList = GetDlgItem(hwndDlg, IDC_LANGLIST);
 +							lvi.mask = LVIF_STATE|LVIF_PARAM;
 +							lvi.stateMask = LVIS_STATEIMAGEMASK;
 +							lvi.iSubItem = 0;
 +							for(lvi.iItem = 0;ListView_GetItem(hwndList, &lvi);++lvi.iItem) {
 +								pack = (LANGPACK_INFO*)lvi.lParam;
 +								if (lvi.state&INDEXTOSTATEIMAGEMASK(2)) {
 +									EnablePack(pack, _T("langpack_*.txt"));
 +									pack->flags |= LPF_ENABLED;
 +								} else pack->flags &= ~LPF_ENABLED;
 +							}
 +							DBWriteContactSettingByte(NULL, "LangMan", "EnableAutoUpdates", (BYTE)(IsDlgButtonChecked(hwndDlg, IDC_ENABLEAUTOUPDATES)!=0));
 +							return TRUE;
 +						}
 +						case PSN_EXPERTCHANGED:
 +							SendMessage(hwndDlg, M_SHOWFILECOL, 0, ((PSHNOTIFY*)lParam)->lParam);
 +							return TRUE;
 +					} /* switch nmhdr->code */
 +					break;
 +			} /* switch nmhdr->idFrom */
 +			break;
 +		}
 +	}
 +	return FALSE;
 +}
 +
 +void ReloadLangOptList(void)
 +{
 +	if (hwndLangOpt!=NULL) {
 +		SendMessage(hwndLangOpt, M_RELOADLIST, 0, 0);
 +		SendMessage(hwndLangOpt, M_SHOWFILECOL, 0, SendMessage(GetParent(hwndLangOpt), PSM_ISEXPERT, 0, 0));
 +	}
 +}
 +
 +static int LangOptInit(WPARAM wParam, LPARAM lParam)
 +{
 +	OPTIONSDIALOGPAGE odp = { 0 };
 +	UNREFERENCED_PARAMETER(lParam);
 +	odp.cbSize = sizeof(odp);
 +	odp.hInstance = hInst;
 +	odp.flags = ODPF_BOLDGROUPS;
 +	odp.position = 1200000090;
 +	odp.pszTitle = LPGEN("Appearance");  /* autotranslated */
 +	odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_LANG);
 +	odp.pfnDlgProc = LangOptDlgProc;
 +	Options_AddPage(wParam, &odp);
 +	return 0;
 +}
 +
 +/************************* Misc ***************************************/
 +
 +void InitOptions(void)
 +{
 +	hwndLangOpt = NULL;
 +	hHookOptInit = HookEvent(ME_OPT_INITIALISE, LangOptInit);
 +	CorrectPacks(_T("langpack_*.txt"), FALSE);
 +}
 +
 +void UninitOptions(void)
 +{
 +	UnhookEvent(hHookOptInit);
 +}
\ No newline at end of file diff --git a/plugins/LangMan/src/options.h b/plugins/LangMan/src/options.h new file mode 100644 index 0000000000..2b9e93b334 --- /dev/null +++ b/plugins/LangMan/src/options.h @@ -0,0 +1,27 @@ +/*
 +
 +'Language Pack Manager'-Plugin for Miranda IM
 +
 +Copyright (C) 2005-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 (LangMan-License.txt); if not, write to the Free Software
 +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 +*/
 +
 +/* Options Page */
 +void ReloadLangOptList(void);
 +
 +/* Misc */
 +void InitOptions(void);
 +void UninitOptions(void);
 diff --git a/plugins/LangMan/src/resource.h b/plugins/LangMan/src/resource.h new file mode 100644 index 0000000000..983f304ffb --- /dev/null +++ b/plugins/LangMan/src/resource.h @@ -0,0 +1,49 @@ +//{{NO_DEPENDENCIES}}
 +// Microsoft Developer Studio generated include file.
 +// Used by resource.rc
 +//
 +#define IDD_OPT_LANG                    101
 +#define IDD_UPDATENOTIFY                102
 +#define IDD_DOWNLOADLANG                103
 +#define IDI_RELOAD                      104
 +#define IDC_LANGLIST                    1001
 +#define IDC_LANGINFOFRAME               1002
 +#define IDC_LANGAUTHORSLABEL            1003
 +#define IDC_LANGAUTHORS                 1004
 +#define IDC_LANGEMAILLABEL              1005
 +#define IDC_LANGEMAIL                   1006
 +#define IDC_LANGMODUSINGLABEL           1007
 +#define IDC_LANGMODUSING                1008
 +#define IDC_LANGDATELABEL               1009
 +#define IDC_LANGDATE                    1010
 +#define IDC_LANGVERSIONLABEL            1011
 +#define IDC_LANGVERSION                 1012
 +#define IDC_LANGLOCALELABEL             1013
 +#define IDC_LANGLOCALE                  1014
 +#define IDC_LANGNOTINCLUDEDLABEL        1015
 +#define IDC_LANGNOTINCLUDED             1016
 +#define IDC_MORELANG                    1017
 +#define IDC_RESTART                     1018
 +#define IDC_ENABLEAUTOUPDATES           1019
 +#define IDC_DOWNLOADLANG                1020
 +#define IDC_LANGCOMBO                   1021
 +#define IDC_LANGAUTHORS2                1021
 +#define IDC_DOWNLOADALL                 1022
 +#define IDC_LOADING                     1023
 +#define IDC_LANGUAGELABEL               1024
 +#define IDC_LANGUAGE                    1025
 +#define IDC_CURRENTVERSION              1026
 +#define IDC_NEWVERSION                  1027
 +#define IDC_NEWVERSIONLABEL             1028
 +
 +// Next default values for new objects
 +//
 +#ifdef APSTUDIO_INVOKED
 +#ifndef APSTUDIO_READONLY_SYMBOLS
 +#define _APS_NO_MFC                     1
 +#define _APS_NEXT_RESOURCE_VALUE        104
 +#define _APS_NEXT_COMMAND_VALUE         40001
 +#define _APS_NEXT_CONTROL_VALUE         1029
 +#define _APS_NEXT_SYMED_VALUE           2001
 +#endif
 +#endif
 diff --git a/plugins/LangMan/src/utils.cpp b/plugins/LangMan/src/utils.cpp new file mode 100644 index 0000000000..c67b9813a8 --- /dev/null +++ b/plugins/LangMan/src/utils.cpp @@ -0,0 +1,67 @@ +/*
 +
 +'Language Pack Manager'-Plugin for Miranda IM
 +
 +Copyright (C) 2005-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 (LangMan-License.txt); if not, write to the Free Software
 +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 +*/
 +
 +#include "common.h"
 +
 +/************************* Error Output ***************************/
 +
 +static void MessageBoxIndirectFree(MSGBOXPARAMSA *mbp)
 +{
 +	MessageBoxIndirectA(mbp);
 +	mir_free((char*)mbp->lpszCaption); /* does NULL check */
 +	mir_free((char*)mbp->lpszText);    /* does NULL check */
 +	mir_free(mbp);
 +}
 +
 +void ShowInfoMessage(BYTE flags, const char *pszTitle, const char *pszTextFmt, ...)
 +{
 +	va_list va;
 +	va_start(va, pszTextFmt);
 +	char szText[256]; /* max for systray */
 +	mir_vsnprintf(szText, SIZEOF(szText), pszTextFmt, va);
 +	va_end(va);
 +
 +	if (ServiceExists(MS_CLIST_SYSTRAY_NOTIFY)) {
 +		MIRANDASYSTRAYNOTIFY msn;
 +		msn.cbSize = sizeof(msn);
 +		msn.szProto = NULL;
 +		msn.szInfoTitle = (char*)pszTitle;
 +		msn.szInfo = (char*)szText;
 +		msn.uTimeout = 30000; /* max timeout */
 +		msn.dwInfoFlags = flags;
 +		if (!CallServiceSync(MS_CLIST_SYSTRAY_NOTIFY, 0, (LPARAM)&msn))
 +			return; /* success */
 +	}
 +
 +	MSGBOXPARAMSA *mbp = (MSGBOXPARAMSA*)mir_calloc(sizeof(*mbp));
 +	if (mbp == NULL) return;
 +	mbp->cbSize = sizeof(*mbp);
 +	mbp->lpszCaption = mir_strdup(pszTitle);
 +	mbp->lpszText = mir_strdup(szText);
 +	mbp->dwStyle = MB_OK|MB_SETFOREGROUND|MB_TASKMODAL;
 +	mbp->dwLanguageId = LANGIDFROMLCID((LCID)CallService(MS_LANGPACK_GETLOCALE, 0, 0));
 +	switch(flags&NIIF_ICON_MASK) {
 +		case NIIF_INFO:    mbp->dwStyle |= MB_ICONINFORMATION; break;
 +		case NIIF_WARNING: mbp->dwStyle |= MB_ICONWARNING; break;
 +		case NIIF_ERROR:   mbp->dwStyle |= MB_ICONERROR;
 +	}
 +	mir_forkthread(( pThreadFunc )MessageBoxIndirectFree, mbp);
 +}
 diff --git a/plugins/LangMan/src/utils.h b/plugins/LangMan/src/utils.h new file mode 100644 index 0000000000..8c4e299ebb --- /dev/null +++ b/plugins/LangMan/src/utils.h @@ -0,0 +1,23 @@ +/*
 +
 +'Language Pack Manager'-Plugin for Miranda IM
 +
 +Copyright (C) 2005-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 (LangMan-License.txt); if not, write to the Free Software
 +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 +*/
 +
 +/* Error Output */
 +void ShowInfoMessage(BYTE flags, const char *pszTitle, const char *pszTextFmt, ...);
 diff --git a/plugins/LangMan/src/version.h b/plugins/LangMan/src/version.h new file mode 100644 index 0000000000..69dae65ae4 --- /dev/null +++ b/plugins/LangMan/src/version.h @@ -0,0 +1,35 @@ +/*
 +
 +'Language Pack Manager'-Plugin for Miranda IM
 +
 +Copyright (C) 2005-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 (LangMan-License.txt); if not, write to the Free Software
 +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 +*/
 +
 +#define NEEDED_MIRANDA_VERSION      PLUGIN_MAKE_VERSION(0, 6, 0, 0)
 +#define NEEDED_MIRANDA_VERSION_STR  "0.6"
 +#define PLUGIN_VERSION              PLUGIN_MAKE_VERSION(1, 0, 2, 3)
 +#define FILE_VERSION                1, 0, 2, 3
 +
 +#if defined(_DEBUG)
 + #define FILE_VERSION_STR           "1.0.2.3 alpha"
 + #define USERAGENT_VERSION          "1.0.2.3 (alpha)"
 +#else
 + #define FILE_VERSION_STR           "1.0.2.3"
 + #define USERAGENT_VERSION          "1.0.2.3"
 +#endif
 +
 + #define PLUGIN_WEBSITE            "http://addons.miranda-im.org/details.php?action = viewfile&id = 3003"
  | 
