Beispiel #1
0
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);
}
Beispiel #2
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;
	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;
}