static void LoaderThread(void *arg) { LoaderThreadStartParams *dtsp = (LoaderThreadStartParams *)arg; FILE *fp; char line[4096]; char *pszLine, *pszColon, *pszBuf; int startOfLine = 0; WIN32_FIND_DATA wfd; HANDLE hFind; TCHAR szDir[MAX_PATH]; TCHAR szSearch[MAX_PATH]; TCHAR *p; int success = 0; struct DialogData dialog; struct DlgControlData *control; void *buf; ZeroMemory(&dialog, sizeof(dialog)); if (GetModuleFileName(NULL, szDir, _countof(szDir))) { p = _tcsrchr(szDir, _T('\\')); if (p) *p = _T('\0'); mir_sntprintf(szSearch, _T("%s\\helppack_*.txt"), szDir); hFind = FindFirstFile(szSearch, &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; mir_sntprintf(szSearch, _T("%s\\%s"), szDir, wfd.cFileName); success = 1; break; } while (FindNextFile(hFind, &wfd)); FindClose(hFind); } } if (!success) { if (!Miranda_Terminated() && IsWindow(hwndHelpDlg)) PostMessage(hwndHelpDlg, M_HELPLOADFAILED, 0, (LPARAM)dtsp->hwndCtl); return; } fp = _tfopen(szSearch, _T("rt")); if (fp == NULL) { if (!Miranda_Terminated() && IsWindow(hwndHelpDlg)) PostMessage(hwndHelpDlg, M_HELPLOADFAILED, 0, (LPARAM)dtsp->hwndCtl); return; } fgets(line, _countof(line), fp); TrimString(line); if (lstrcmpA(line, "Miranda Help Pack Version 1")) { fclose(fp); if (!Miranda_Terminated() && IsWindow(hwndHelpDlg)) PostMessage(hwndHelpDlg, M_HELPLOADFAILED, 0, (LPARAM)dtsp->hwndCtl); return; } // headers dialog.locale = LOCALE_USER_DEFAULT; dialog.defaultCodePage = CP_ACP; while (!feof(fp)) { startOfLine = ftell(fp); if (fgets(line, _countof(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); if (!Miranda_Terminated() && IsWindow(hwndHelpDlg)) PostMessage(hwndHelpDlg, M_HELPLOADFAILED, 0, (LPARAM)dtsp->hwndCtl); return; } *pszColon = '\0'; // locale if (!lstrcmpA(line, "Locale")) { char szCP[6]; TrimString(pszColon + 1); dialog.locale = MAKELCID((USHORT)strtol(pszColon + 1, NULL, 16), SORT_DEFAULT); // codepage if (GetLocaleInfoA(dialog.locale, LOCALE_IDEFAULTANSICODEPAGE, szCP, sizeof(szCP))) { szCP[5] = '\0'; // codepages have 5 digits at max dialog.defaultCodePage = atoi(szCP); } } } // RTL flag // see also: http://blogs.msdn.com/michkap/archive/2006/03/03/542963.aspx { LOCALESIGNATURE sig; dialog.isLocaleRTL = 0; if (GetLocaleInfo(dialog.locale, LOCALE_FONTSIGNATURE, (LPTSTR)&sig, sizeof(sig) / sizeof(TCHAR))) dialog.isLocaleRTL = (sig.lsUsb[3] & 0x8000000); // Win2000+: testing for 'Layout progress: horizontal from right to left' bit switch (PRIMARYLANGID(LANGIDFROMLCID(dialog.locale))) { // prior to Win2000 case LANG_ARABIC: case LANG_HEBREW: case LANG_FARSI: dialog.isLocaleRTL = 1; } } // body fseek(fp, startOfLine, SEEK_SET); success = 1; control = NULL; while (!feof(fp)) { if (fgets(line, _countof(line), fp) == NULL) break; if (IsEmpty(line) || line[0] == ';' || line[0] == '\0') continue; TrimStringSimple(line); if (line[0] == '[' && line[lstrlenA(line) - 1] == ']') { pszLine = line + 1; line[lstrlenA(line) - 1] = '\0'; // module pszColon = strrchr(pszLine, ':'); if (pszColon == NULL) continue; *pszColon = '\0'; pszColon++; TrimString(pszLine); if (lstrcmpiA(dtsp->szModule, pszLine)) continue; pszBuf = pszLine; // dlgid pszLine = pszColon; pszColon = strrchr(pszLine, '@'); if (pszColon == NULL) continue; *pszColon = '\0'; pszColon++; TrimString(pszColon); if (lstrcmpA(dtsp->szDlgId, pszColon)) continue; if (dialog.szModule == NULL && dialog.szId == NULL) { dialog.szModule = mir_strdup(pszBuf); dialog.szId = mir_strdup(pszColon); if (dialog.szId == NULL || dialog.szModule == NULL) { success = 0; break; } } buf = (struct DlgControlData*)mir_realloc(dialog.control, sizeof(struct DlgControlData)*(dialog.controlCount + 1)); if (buf == NULL) { success = 0; break; } dialog.controlCount++; dialog.control = (struct DlgControlData*)buf; control = &dialog.control[dialog.controlCount - 1]; ZeroMemory(control, sizeof(*control)); // ctlid TrimString(pszLine); control->id = atoi(pszLine); } else if (control != NULL) { pszLine = line; // ctltext pszColon = strchr(pszLine, '='); if (pszColon == NULL) continue; *pszColon = '\0'; pszColon++; TrimString(pszColon); TrimString(pszLine); if (*pszColon == '\0' || *pszLine == '\0') continue; int size = lstrlenA(pszLine) + 1; control->szTitle = (WCHAR*)mir_alloc(size*sizeof(WCHAR)); if (control->szTitle != NULL) { *control->szTitle = _T('\0'); MultiByteToWideChar(dialog.defaultCodePage, 0, pszLine, -1, control->szTitle, size); } // text control->szText = mir_utf8encodecp(pszColon, dialog.defaultCodePage); control = NULL; // control done } } fclose(fp); if (success) { int i, dialogInserted = 0; dialog.timeLoaded = dialog.timeLastUsed = GetTickCount(); EnterCriticalSection(&csDialogCache); for (i = 0; i < dialogCacheCount; i++) { if (dialogCache[i].timeLastUsed && dialogCache[i].timeLastUsed<(dialog.timeLoaded - DIALOGCACHEEXPIRY)) { FreeDialogCacheEntry(&dialogCache[i]); if (dialogInserted || !dialog.controlCount) { MoveMemory(dialogCache + i, dialogCache + i + 1, sizeof(struct DialogData)*(dialogCacheCount - i - 1)); dialogCacheCount--; buf = (struct DialogData*)mir_realloc(dialogCache, sizeof(struct DialogData)*dialogCacheCount); if (buf != NULL) dialogCache = (struct DialogData*)buf; else if (!dialogCacheCount) dialogCache = NULL; } else { dialogInserted = 1; dialogCache[i] = dialog; } } } if (dialog.controlCount && !dialogInserted) { buf = (struct DialogData*)mir_realloc(dialogCache, sizeof(struct DialogData)*(dialogCacheCount + 1)); if (buf != NULL) { dialogCacheCount++; dialogCache = (struct DialogData*)buf; dialogCache[dialogCacheCount - 1] = dialog; dialogInserted = 1; } } LeaveCriticalSection(&csDialogCache); if (!dialogInserted) { mir_free(dialog.szId); // does NULL check mir_free(dialog.szModule); // does NULL check mir_free(dialog.control); // does NULL check } if (!Miranda_Terminated() && IsWindow(hwndHelpDlg)) PostMessage(hwndHelpDlg, M_HELPLOADED, 0, (LPARAM)dtsp->hwndCtl); } if (!success) { mir_free(dialog.szId); // does NULL check mir_free(dialog.szModule); // does NULL check mir_free(dialog.control); // does NULL check if (!Miranda_Terminated() && IsWindow(hwndHelpDlg)) PostMessage(hwndHelpDlg, M_HELPLOADFAILED, 0, (LPARAM)dtsp->hwndCtl); } mir_free(dtsp->szDlgId); mir_free(dtsp->szModule); mir_free(dtsp); }
static int LoadLangPack(const TCHAR *szLangPack) { FILE *fp; char line[4096] = ""; char *pszColon; char *pszLine; int entriesAlloced; int startOfLine=0; unsigned int linePos=1; LCID langID; UINT fileCp = CP_ACP; lstrcpy(langPack.filename,szLangPack); fp = _tfopen(szLangPack,_T("rt")); if(fp==NULL) return 1; fgets(line,sizeof(line),fp); size_t lineLen = strlen(line); if (lineLen >= 3 && line[0]=='\xef' && line[1]=='\xbb' && line[2]=='\xbf') { fileCp = CP_UTF8; memmove(line, line + 3, lineLen - 2); } 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")) {_snprintf(langPack.language,sizeof(langPack.language),"%s",pszColon+1); TrimString(langPack.language);} else if(!lstrcmpA(line,"Last-Modified-Using")) {_snprintf(langPack.lastModifiedUsing,sizeof(langPack.lastModifiedUsing),"%s",pszColon+1); TrimString(langPack.lastModifiedUsing);} else if(!lstrcmpA(line,"Authors")) {_snprintf(langPack.authors,sizeof(langPack.authors),"%s",pszColon+1); TrimString(langPack.authors);} else if(!lstrcmpA(line,"Author-email")) {_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); if (fileCp == CP_ACP) fileCp = langPack.defaultANSICp; } } //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, fileCp); 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=hashstr(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); if (fileCp == CP_UTF8) Utf8DecodeCP(E->local, langPack.defaultANSICp, NULL); { int iNeeded = MultiByteToWideChar(fileCp, 0, line, -1, 0, 0); E->wlocal = (wchar_t *)malloc((iNeeded+1) * sizeof(wchar_t)); MultiByteToWideChar(fileCp, 0, line, -1, E->wlocal, iNeeded); } } else { size_t iOldLenA = strlen(E->local); E->local = (char*)realloc(E->local, iOldLenA + strlen(line) + 2); strcat(E->local, "\n"); strcat(E->local, line); if (fileCp == CP_UTF8) Utf8DecodeCP(E->local + iOldLenA + 1, langPack.defaultANSICp, NULL); { int iNeeded = MultiByteToWideChar(fileCp, 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(fileCp, 0, line, -1, E->wlocal + iOldLen+1, iNeeded); } } } } fclose(fp); qsort(langPack.entry,langPack.entryCount,sizeof(LangPackEntry),(int(*)(const void*,const void*))SortLangPackHashesProc); return 0; }