/*++ Copyright (c) 1985 - 1999, Microsoft Corporation Module Name: eudc.c Abstract: Author: KazuM Apr.19.1996 Revision History: --*/ #include "precomp.h" #pragma hdrstop #if defined(FE_SB) NTSTATUS CreateEUDC( PCONSOLE_INFORMATION Console ) { PEUDC_INFORMATION EudcInfo; EudcInfo = ConsoleHeapAlloc(EUDC_TAG, sizeof(EUDC_INFORMATION)); if (EudcInfo == NULL) { return STATUS_NO_MEMORY; } EudcInfo->LocalVDMEudcMode = FALSE; EudcInfo->LocalKeisenEudcMode = FALSE; EudcInfo->hDCLocalEudc = NULL; EudcInfo->hBmpLocalEudc = NULL; EudcInfo->EudcFontCacheInformation = NULL; EudcInfo->LocalEudcSize.X = DEFAULT_EUDCSIZE; EudcInfo->LocalEudcSize.Y = DEFAULT_EUDCSIZE; RtlZeroMemory(&EudcInfo->EudcRange,sizeof(EudcInfo->EudcRange)); EudcInfo->EudcRangeSize = GetSystemEUDCRangeW(EudcInfo->EudcRange, EUDC_RANGE_SIZE); if (EudcInfo->EudcRangeSize) EudcInfo->EudcRangeSize--; // remove terminator Console->EudcInformation = (PVOID)EudcInfo; return STATUS_SUCCESS; } VOID DeleteEUDC( PCONSOLE_INFORMATION Console ) { PEUDC_INFORMATION EudcInfo = Console->EudcInformation; if (EudcInfo->hDCLocalEudc) { ReleaseDC(NULL, EudcInfo->hDCLocalEudc); DeleteObject(EudcInfo->hBmpLocalEudc); } } NTSTATUS RegisterLocalEUDC( IN PCONSOLE_INFORMATION Console, IN WCHAR wChar, IN COORD FontSize, IN PCHAR FontFace ) { NTSTATUS Status; PCHAR TmpBuff; DWORD BuffSize; PEUDC_INFORMATION EudcInfo = Console->EudcInformation; if (EudcInfo->EudcFontCacheInformation == NULL) { Status = (NTSTATUS)CreateFontCache(&(PFONT_CACHE_INFORMATION)EudcInfo->EudcFontCacheInformation); if (!NT_SUCCESS(Status)) { RIPMSG1(RIP_WARNING, "RegisterLocalEUDC: failed in CreateFontCache, Status is %08x", Status); return Status; } } BuffSize = CalcBitmapBufferSize(FontSize, BYTE_ALIGN); TmpBuff = FontFace; while(BuffSize--) *TmpBuff++ = ~(*TmpBuff); return (NTSTATUS)SetFontImage(EudcInfo->EudcFontCacheInformation, wChar, FontSize, BYTE_ALIGN, FontFace ); } VOID FreeLocalEUDC( IN PCONSOLE_INFORMATION Console ) { PEUDC_INFORMATION EudcInfo = Console->EudcInformation; if (EudcInfo->EudcFontCacheInformation != NULL) { DestroyFontCache((PFONT_CACHE_INFORMATION)EudcInfo->EudcFontCacheInformation); } ConsoleHeapFree(Console->EudcInformation); } VOID GetFitLocalEUDCFont( IN PCONSOLE_INFORMATION Console, IN WCHAR wChar ) { NTSTATUS Status; COORD FontSize; VOID *FontFace; DWORD BuffSize; PEUDC_INFORMATION EudcInfo; PFONT_CACHE_INFORMATION FontCacheInfo; EudcInfo = (PEUDC_INFORMATION)Console->EudcInformation; FontCacheInfo = (PFONT_CACHE_INFORMATION)EudcInfo->EudcFontCacheInformation; FontSize = CON_FONTSIZE(Console); if (IsConsoleFullWidth(Console->hDC,Console->OutputCP,wChar)) { FontSize.X *= 2; } if ((EudcInfo->LocalEudcSize.X != FontSize.X) || (EudcInfo->LocalEudcSize.Y != FontSize.Y) ) { ReleaseDC(NULL, EudcInfo->hDCLocalEudc); DeleteObject(EudcInfo->hBmpLocalEudc); EudcInfo->hDCLocalEudc = CreateCompatibleDC(Console->hDC); EudcInfo->hBmpLocalEudc = CreateBitmap(FontSize.X, FontSize.Y, BITMAP_PLANES, BITMAP_BITS_PIXEL, NULL); SelectObject(EudcInfo->hDCLocalEudc, EudcInfo->hBmpLocalEudc); EudcInfo->LocalEudcSize.X = FontSize.X; EudcInfo->LocalEudcSize.Y = FontSize.Y; } BuffSize = CalcBitmapBufferSize(FontSize,WORD_ALIGN); FontFace = ConsoleHeapAlloc(TMP_DBCS_TAG, BuffSize); if (FontFace == NULL) { RIPMSG0(RIP_WARNING, "GetFitLocalEUDCFont: failed to allocate FontFace."); return; } Status = (NTSTATUS)GetFontImage(FontCacheInfo, wChar, FontSize, WORD_ALIGN, FontFace ); if (! NT_SUCCESS(Status)) { if ((Console->Flags & CONSOLE_VDM_REGISTERED) && FontSize.X == DefaultFontSize.X * 2 && FontSize.Y == DefaultFontSize.Y && FontSize.X == VDM_EUDC_FONT_SIZE_X && FontSize.Y - 2 == VDM_EUDC_FONT_SIZE_Y ) { COORD TmpFontSize = FontSize; TmpFontSize.Y -= 2; RtlFillMemory((PVOID)FontFace,BuffSize,0xff); Status = (NTSTATUS)GetFontImage(FontCacheInfo, wChar, TmpFontSize, WORD_ALIGN, FontFace ); if (! NT_SUCCESS(Status)) { Status = (NTSTATUS)GetStretchedFontImage(FontCacheInfo, wChar, FontSize, WORD_ALIGN, FontFace ); if (! NT_SUCCESS(Status)) { ASSERT(FALSE); ConsoleHeapFree(FontFace); return; } } } else { Status = (NTSTATUS)GetStretchedFontImage(FontCacheInfo, wChar, FontSize, WORD_ALIGN, FontFace ); if (! NT_SUCCESS(Status)) { ASSERT(FALSE); ConsoleHeapFree(FontFace); return; } } Status = (NTSTATUS)SetFontImage(FontCacheInfo, wChar, FontSize, WORD_ALIGN, FontFace ); if (! NT_SUCCESS(Status)) { ASSERT(FALSE); ConsoleHeapFree(FontFace); return; } } SetBitmapBits(EudcInfo->hBmpLocalEudc, BuffSize, (PBYTE)FontFace); ConsoleHeapFree(FontFace); } BOOL IsEudcRange( IN PCONSOLE_INFORMATION Console, IN WCHAR ch ) { PEUDC_INFORMATION EudcInfo; int i; EudcInfo = (PEUDC_INFORMATION)Console->EudcInformation; for (i=0; i < EudcInfo->EudcRangeSize; i+=2) { if (EudcInfo->EudcRange[i] <= ch && ch <= EudcInfo->EudcRange[i+1]) return TRUE; } return FALSE; } BOOL CheckEudcRangeInString( IN PCONSOLE_INFORMATION Console, IN PWCHAR string, IN SHORT len, OUT SHORT *find_pos ) { SHORT i; for (i = 0; i < len; i++,string++) { if (IsEudcRange(Console, *string)) { *find_pos = i; return TRUE; } } return FALSE; } LPWSTR SkipWhite( LPWSTR lpch ) { if( lpch == NULL ) return( NULL ); for ( ; ; lpch++ ) { switch (*lpch) { case L' ': case L'\t': case L'\r': case L'\n': break; default: return(lpch); } } } WORD ConvertStringToHex( LPWSTR lpch, LPWSTR *endptr ) { WCHAR ch; WORD val = 0; while ( (ch=*lpch) != L'\0') { if (L'0' <= ch && ch <= L'9') val = (val << 4) + (ch - L'0'); else if (L'A' <= ch && ch <= L'F') val = (val << 4) + (ch - L'A' + 10); else if (L'a' <= ch && ch <= L'f') val = (val << 4) + (ch - L'a' + 10); else break; lpch++; } if (endptr) *endptr = lpch; return val; } WORD ConvertStringToDec( LPWSTR lpch, LPWSTR *endptr ) { WCHAR ch; WORD val = 0; while ( (ch=*lpch) != L'\0') { if (L'0' <= ch && ch <= L'9') val = (val * 10) + (ch - L'0'); else break; lpch++; } if (endptr) *endptr = lpch; return val; } INT GetSystemEUDCRangeW( WORD *pwEUDCCharTable, UINT cjSize) { NTSTATUS Status; HKEY hkRegistry; UNICODE_STRING SystemACPString; WCHAR awcACP[10]; WCHAR awchBuffer[512]; INT iEntry = 0; /* * Check parameter * * If pwEUDCWideCharTable == NULL && cjSize == 0 * We have to return the needed buffer size to store data */ if ((pwEUDCCharTable == NULL && cjSize != 0) || (pwEUDCCharTable != NULL && cjSize == 0)) { return 0; } /* * Open registry key. */ Status = MyRegOpenKey(NULL, MACHINE_REGISTRY_EUDC, &hkRegistry); if (!NT_SUCCESS(Status)) { RIPMSG2(RIP_WARNING, "GetSystemEUDCRangeW: RegOpenKeyExW(%ws) failed, error = 0x%x", MACHINE_REGISTRY_EUDC, GetLastError()); return 0; } /* * Convert ACP to Unicode string. */ SystemACPString.Length = 0; SystemACPString.MaximumLength = ARRAY_SIZE(awcACP); SystemACPString.Buffer = awcACP; RtlIntegerToUnicodeString(WINDOWSCP, 10, &SystemACPString); /* * Read registry data. */ Status = MyRegQueryValue(hkRegistry, awcACP, sizeof(awchBuffer), (PBYTE)&awchBuffer); if (!NT_SUCCESS(Status)) { RIPMSG2(RIP_VERBOSE, "GetSystemEUDCRangeW: NtQueryValueKey(%ws) failed, error = 0x%x", awcACP, GetLastError()); } else { LPWSTR pwszBuf = awchBuffer; /* * Parse the data. */ while (pwszBuf != NULL && *pwszBuf != UNICODE_NULL) { WORD ch1,ch2; /* * Get Start Range value. */ pwszBuf = SkipWhite(pwszBuf); ch1 = ConvertStringToHex(pwszBuf, &pwszBuf); pwszBuf = SkipWhite(pwszBuf); if (*pwszBuf != L'-') { RIPMSG0(RIP_WARNING, "GetSystemEUDCRangeW: Invalid format"); iEntry = 0; goto Error; } /* * Get End Range value. */ pwszBuf = SkipWhite(pwszBuf + 1); ch2 = ConvertStringToHex(pwszBuf, &pwszBuf); /* * Confirm the data sort order is correct. */ if (ch1 > ch2) { RIPMSG0(RIP_WARNING, "GetSystemEUDCRangeW: Sort order is incorrect"); iEntry = 0; goto Error; } /* * Move pointer to next. */ pwszBuf = SkipWhite(pwszBuf); if (*pwszBuf == L',') { pwszBuf = SkipWhite(pwszBuf + 1); } /* * Above, if pwszBuf is NULL, we've reached the EOD. */ iEntry++; /* * If caller buffer is large enough to store the data, store it. * Even if that's not the case, we have to continue to parse the * data to compute the number of entry. */ /* * 3 - Because we have to store NULL as a mark of EOD. */ if (cjSize >= 3) { *pwEUDCCharTable++ = ch1; *pwEUDCCharTable++ = ch2; cjSize -= 2; } } *pwEUDCCharTable = UNICODE_NULL; iEntry = iEntry * 2 + 1; } Error: /* * Close registry handle. */ UserAssert(hkRegistry != NULL); NtClose(hkRegistry); return iEntry; } #endif