From c90d55ec2adeb5864f9629116f735457f296009a Mon Sep 17 00:00:00 2001 From: Kirill Volinsky Date: Sat, 7 Jul 2012 22:13:58 +0000 Subject: CmdLine: adopted, MimCmd not adopted yet git-svn-id: http://svn.miranda-ng.org/main/trunk@839 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- plugins/CmdLine/MimCmd/langpack.cpp | 377 ++++++++++++++++++++++++++++++++++++ 1 file changed, 377 insertions(+) create mode 100644 plugins/CmdLine/MimCmd/langpack.cpp (limited to 'plugins/CmdLine/MimCmd/langpack.cpp') diff --git a/plugins/CmdLine/MimCmd/langpack.cpp b/plugins/CmdLine/MimCmd/langpack.cpp new file mode 100644 index 0000000000..096431f95b --- /dev/null +++ b/plugins/CmdLine/MimCmd/langpack.cpp @@ -0,0 +1,377 @@ +/* +CmdLine plugin for Miranda IM + +Copyright © 2007 Cristian Libotean + +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. +*/ + +//this code is mostly taken from Miranda's langpack module. + +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2007 Miranda ICQ/IM project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +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. +*/ +#include "langpack.h" + +static __inline int mir_snprintf(char *buffer, size_t count, const char* fmt, ...) { + va_list va; + int len; + + va_start(va, fmt); + len = _vsnprintf(buffer, count-1, fmt, va); + va_end(va); + buffer[count-1] = 0; + return len; +} + +int lpprintf(const char *format, ...) +{ + va_list va; + va_start(va, format); + const int MAX_SIZE = 16192; + char buffer[MAX_SIZE] = {0}; + int len = _vsnprintf(buffer, MAX_SIZE - 1, format, va); + buffer[MAX_SIZE - 1] = 0; + va_end(va); + CharToOemBuff(buffer, buffer, len); + printf("%s", buffer); + + return len; +} + +static void TrimString(char *str) +{ + int len,start; + len=lstrlenA(str); + while(str[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 void TrimStringSimple(char *str) +{ + if (str[lstrlenA(str)-1] == '\n') str[lstrlenA(str)-1] = '\0'; + if (str[lstrlenA(str)-1] == '\r') str[lstrlenA(str)-1] = '\0'; +} + +static int IsEmpty(char *str) +{ + int i = 0; + + while (str[i]) + { + if (str[i]!=' '&&str[i]!='\r'&&str[i]!='\n') + return 0; + i++; + } + return 1; +} + +static void ConvertBackslashes(char *str) +{ + char *pstr; + + for(pstr=str;*pstr;pstr=CharNextA(pstr)) { + if(*pstr=='\\') { + switch(pstr[1]) { +case 'n': *pstr='\n'; break; +case 't': *pstr='\t'; break; +case 'r': *pstr='\r'; break; +default: *pstr=pstr[1]; break; + } + MoveMemory(pstr+1,pstr+2,lstrlenA(pstr+2)+1); + } + } +} + +static DWORD LangPackHash(const char *szStr) +{ +#if defined _M_IX86 && !defined _NUMEGA_BC_FINALCHECK && !defined __GNUC__ + __asm { //this is mediocrely optimised, but I'm sure it's good enough + xor edx,edx + mov esi,szStr + xor cl,cl +lph_top: + xor eax,eax + and cl,31 + mov al,[esi] + inc esi + test al,al + jz lph_end + rol eax,cl + add cl,5 + xor edx,eax + jmp lph_top +lph_end: + mov eax,edx + } +#else + DWORD hash=0; + int i; + int shift=0; + for(i=0;szStr[i];i++) { + hash^=szStr[i]<24) hash^=(szStr[i]>>(32-shift))&0x7F; + shift=(shift+5)&0x1F; + } + return hash; +#endif +} + +static DWORD LangPackHashW(const char *szStr) +{ +#if defined _M_IX86 && !defined _NUMEGA_BC_FINALCHECK && !defined __GNUC__ + __asm { //this is mediocrely optimised, but I'm sure it's good enough + xor edx,edx + mov esi,szStr + xor cl,cl +lph_top: + xor eax,eax + and cl,31 + mov al,[esi] + inc esi + inc esi + test al,al + jz lph_end + rol eax,cl + add cl,5 + xor edx,eax + jmp lph_top +lph_end: + mov eax,edx + } +#else + DWORD hash=0; + int i; + int shift=0; + for(i=0;szStr[i];i+=2) { + hash^=szStr[i]<24) hash^=(szStr[i]>>(32-shift))&0x7F; + shift=(shift+5)&0x1F; + } + return hash; +#endif +} + +static int SortLangPackHashesProc(struct LangPackEntry *arg1,struct LangPackEntry *arg2) +{ + if(arg1->englishHashenglishHash) return -1; + if(arg1->englishHash>arg2->englishHash) return 1; + /* both source strings of the same hash (may not be the same string thou) put + the one that was written first to be found first */ + if(arg1->linePoslinePos) return -1; + if(arg1->linePos>arg2->linePos) return 1; + return 0; +} + + +static int SortLangPackHashesProc2(struct LangPackEntry *arg1,struct LangPackEntry *arg2) +{ + if(arg1->englishHashenglishHash) return -1; + if(arg1->englishHash>arg2->englishHash) return 1; + return 0; +} + +static int LoadLangPack(const TCHAR *szLangPack) +{ + FILE *fp; + char line[4096]; + char *pszColon; + char *pszLine; + int entriesAlloced; + int startOfLine=0; + unsigned int linePos=1; + USHORT langID; + + lstrcpy(langPack.filename,szLangPack); + fp = _tfopen(szLangPack,_T("rt")); + if(fp==NULL) return 1; + fgets(line,SIZEOF(line),fp); + TrimString(line); + if(lstrcmpA(line,"Miranda Language Pack Version 1")) {fclose(fp); return 2;} + //headers + while(!feof(fp)) { + startOfLine=ftell(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) {fclose(fp); return 3;} + *pszColon=0; + if(!lstrcmpA(line,"Language")) {mir_snprintf(langPack.language,sizeof(langPack.language),"%s",pszColon+1); TrimString(langPack.language);} + else if(!lstrcmpA(line,"Last-Modified-Using")) {mir_snprintf(langPack.lastModifiedUsing,sizeof(langPack.lastModifiedUsing),"%s",pszColon+1); TrimString(langPack.lastModifiedUsing);} + else if(!lstrcmpA(line,"Authors")) {mir_snprintf(langPack.authors,sizeof(langPack.authors),"%s",pszColon+1); TrimString(langPack.authors);} + else if(!lstrcmpA(line,"Author-email")) {mir_snprintf(langPack.authorEmail,sizeof(langPack.authorEmail),"%s",pszColon+1); TrimString(langPack.authorEmail);} + else if(!lstrcmpA(line, "Locale")) { + char szBuf[20], *stopped; + + TrimString(pszColon + 1); + langID = (USHORT)strtol(pszColon + 1, &stopped, 16); + langPack.localeID = MAKELCID(langID, 0); + GetLocaleInfoA(langPack.localeID, LOCALE_IDEFAULTANSICODEPAGE, szBuf, 10); + szBuf[5] = 0; // codepages have max. 5 digits + langPack.defaultANSICp = atoi(szBuf); + } + } + //body + fseek(fp,startOfLine,SEEK_SET); + entriesAlloced=0; + while(!feof(fp)) { + if(fgets(line,SIZEOF(line),fp)==NULL) break; + if(IsEmpty(line) || line[0]==';' || line[0]==0) continue; + TrimStringSimple(line); + ConvertBackslashes(line); + if(line[0]=='[' && line[lstrlenA(line)-1]==']') { + if(langPack.entryCount && langPack.entry[langPack.entryCount-1].local==NULL) { + if(langPack.entry[langPack.entryCount-1].english!=NULL) free(langPack.entry[langPack.entryCount-1].english); + langPack.entryCount--; + } + pszLine = line+1; + line[lstrlenA(line)-1]='\0'; + //TrimStringSimple(line); + if(++langPack.entryCount>entriesAlloced) { + entriesAlloced+=128; + langPack.entry=(struct LangPackEntry*)realloc(langPack.entry,sizeof(struct LangPackEntry)*entriesAlloced); + } + langPack.entry[langPack.entryCount-1].english=NULL; + langPack.entry[langPack.entryCount-1].englishHash=LangPackHash(pszLine); + langPack.entry[langPack.entryCount-1].local=NULL; + langPack.entry[langPack.entryCount-1].wlocal = NULL; + langPack.entry[langPack.entryCount-1].linePos=linePos++; + } + else if(langPack.entryCount) { + struct LangPackEntry* E = &langPack.entry[langPack.entryCount-1]; + + if(E->local==NULL) { + E->local=_strdup(line); + { + size_t iNeeded = MultiByteToWideChar(langPack.defaultANSICp, 0, line, -1, 0, 0); + E->wlocal = (wchar_t *)malloc((int) ((iNeeded+1) * sizeof(wchar_t))); + MultiByteToWideChar(langPack.defaultANSICp, 0, line, -1, E->wlocal, (int) iNeeded); + } + } + else { + E->local=(char*)realloc(E->local,lstrlenA(E->local)+lstrlenA(line)+2); + lstrcatA(E->local,"\n"); + lstrcatA(E->local,line); + { + size_t iNeeded = MultiByteToWideChar(langPack.defaultANSICp, 0, line, -1, 0, 0); + size_t iOldLen = wcslen(E->wlocal); + E->wlocal = (wchar_t*)realloc(E->wlocal, ( sizeof(wchar_t) * ( iOldLen + iNeeded + 2))); + wcscat(E->wlocal, L"\n"); + MultiByteToWideChar( langPack.defaultANSICp, 0, line, -1, E->wlocal + iOldLen+1, (int) iNeeded); + } + } + } + } + qsort(langPack.entry,langPack.entryCount,sizeof(struct LangPackEntry),(int(*)(const void*,const void*))SortLangPackHashesProc); + fclose(fp); + return 0; +} + +char *LangPackTranslateString(const char *szEnglish, const int W) +{ + struct LangPackEntry key,*entry; + + if ( langPack.entryCount == 0 || szEnglish == NULL ) return (char*)szEnglish; + + + key.englishHash = W ? LangPackHashW(szEnglish) : LangPackHash(szEnglish); + entry=(struct LangPackEntry*)bsearch(&key,langPack.entry,langPack.entryCount,sizeof(struct LangPackEntry),(int(*)(const void*,const void*))SortLangPackHashesProc2); + if(entry==NULL) return (char*)szEnglish; + while(entry>langPack.entry) + { + entry--; + if(entry->englishHash!=key.englishHash) { + entry++; + return W ? (char *)entry->wlocal : entry->local; + } + } + return W ? (char *)entry->wlocal : entry->local; +} + +int LangPackGetDefaultCodePage() +{ + return (langPack.defaultANSICp == 0) ? CP_ACP : langPack.defaultANSICp; +} + +int LangPackGetDefaultLocale() +{ + return (langPack.localeID == 0) ? LOCALE_USER_DEFAULT : langPack.localeID; +} + +int LangPackShutdown() +{ + int i; + for(i=0;i