campo-sirio/xvaga/XFont.cpp
guy 941d28df75 Aggiunto supporto per mail senza outlook
git-svn-id: svn://10.65.10.50/branches/R_10_00@23147 c028cbd2-c16b-5b4b-a496-9718f37d4682
2015-11-30 16:29:32 +00:00

677 lines
19 KiB
C++
Executable File

// XFont.cpp Version 1.1
//
// Author: Philip Patrick (GetFontProperties)
//
// Version 1.0 - Initial release of GetFontProperties()
//
// Modified by: Hans Dietrich
// hdietrich2@hotmail.com
//
// Version 1.1: - Removed MFC dependency from GetFontProperties()
// - Converted CFile file I/O to memory mapped file
// - Added Unicode support
// - Combined with my GetFontFile() routine
//
///////////////////////////////////////////////////////////////////////////////
#include "XTrace.h"
#include "XFont.h"
#include <crtdbg.h>
#include <shlobj.h>
///////////////////////////////////////////////////////////////////////////////
//
// If you do not want TRACE output you can
// uncomment the following lines:
//
#undef TRACE
#if _MSC_VER > 1300
#define TRACE __noop
#else
#define TRACE ((void)0)
#endif
//
///////////////////////////////////////////////////////////////////////////////
#pragma warning(disable : 4127) // conditional expression is constant
///////////////////////////////////////////////////////////////////////////////
// private routines
static LONG GetNextNameValue(HKEY key, LPCTSTR subkey, LPTSTR szName, LPTSTR szData);
///////////////////////////////////////////////////////////////////////////////
// defines used by GetWinVer()
#define WUNKNOWNSTR _T("unknown Windows version")
#define W2KSTR _T("Windows 2000")
#define WXPSTR _T("Windows XP")
#define W2003STR _T("Windows Server 2003")
#define WVISTASTR _T("Windows Vista")
#define W2008STR _T("Windows Server 2008")
#define W2008R2STR _T("Windows Server 2008 R2")
#define W7STR _T("Windows 7")
#define W2012STR _T("Windows Server 2012")
#define W8STR _T("Windows 8")
#define W10STR _T("Windows 10")
#define W2016STR _T("Windows Server 2016")
#define WUNKNOWN 0
#define W9XFIRST 1
#define W95 1
#define W95SP1 2
#define W95OSR2 3
#define W98 4
#define W98SP1 5
#define W98SE 6
#define WME 7
#define W9XLAST 99
#define WNTFIRST 101
#define WNT351 101
#define WNT4 102
#define W2K 103
#define WXP 104
#define W2003 105
#define WVISTA 106
#define W2008 107
#define W2008R2 108
#define W7 109
#define W2012 110
#define W8 111
#define W10 112
#define W2016 103
#define WNTLAST 199
#define WCEFIRST 201
#define WCE 201
#define WCELAST 299
///////////////////////////////////////////////////////////////////////////////
//
// structs used by GetFontProperties()
//
typedef struct _tagFONT_PROPERTIES_ANSI
{
char csName[1024];
char csCopyright[1024];
char csTrademark[1024];
char csFamily[1024];
} FONT_PROPERTIES_ANSI;
typedef struct _tagTT_OFFSET_TABLE
{
USHORT uMajorVersion;
USHORT uMinorVersion;
USHORT uNumOfTables;
USHORT uSearchRange;
USHORT uEntrySelector;
USHORT uRangeShift;
} TT_OFFSET_TABLE;
typedef struct _tagTT_TABLE_DIRECTORY
{
char szTag[4]; //table name
ULONG uCheckSum; //Check sum
ULONG uOffset; //Offset from beginning of file
ULONG uLength; //length of the table in bytes
} TT_TABLE_DIRECTORY;
typedef struct _tagTT_NAME_TABLE_HEADER
{
USHORT uFSelector; //format selector. Always 0
USHORT uNRCount; //Name Records count
USHORT uStorageOffset; //Offset for strings storage, from start of the table
} TT_NAME_TABLE_HEADER;
typedef struct _tagTT_NAME_RECORD
{
USHORT uPlatformID;
USHORT uEncodingID;
USHORT uLanguageID;
USHORT uNameID;
USHORT uStringLength;
USHORT uStringOffset; //from start of storage area
} TT_NAME_RECORD;
#define SWAPWORD(x) MAKEWORD(HIBYTE(x), LOBYTE(x))
#define SWAPLONG(x) MAKELONG(SWAPWORD(HIWORD(x)), SWAPWORD(LOWORD(x)))
///////////////////////////////////////////////////////////////////////////////
//
// GetFontFile()
//
// Purpose: Find the name of font file from the font name
//
// Parameters: lpszFontName - name of font
// lpszDisplayName - pointer to buffer where font display name
// will be copied
// nDisplayNameSize - size of display name buffer in TCHARs
// lpszFontFile - pointer to buffer where font file name
// will be copied
// nFontFileSize - size of font file buffer in TCHARs
//
// Returns: BOOL - TRUE = success
//
// Notes: This is *not* a foolproof method for finding the name of a
// font file. If a font has been installed in a normal manner,
// and if it is in the Windows "Font" directory, then this method
// will probably work. It will probably work for most screen
// fonts and TrueType fonts. However, this method might not work
// for fonts that are created or installed dynamically, or that
// are specific to a particular device, or that are not installed
// into the font directory.
//
BOOL GetFontFile(LPCTSTR lpszFontName,
LPTSTR lpszDisplayName,
int nDisplayNameSize,
LPTSTR lpszFontFile,
int nFontFileSize)
{
_ASSERTE(lpszFontName && lpszFontName[0] != 0);
if (!lpszFontName || lpszFontName[0] == 0)
return FALSE;
_ASSERTE(lpszDisplayName);
if (!lpszDisplayName)
return FALSE;
_ASSERTE(lpszFontFile);
if (!lpszFontFile)
return FALSE;
lpszDisplayName[0] = _T('\0');
lpszFontFile[0] = _T('\0');
TCHAR szName[2 * MAX_PATH];
TCHAR szData[2 * MAX_PATH];
int nVersion;
TCHAR szVersion[100];
GetWinVer(szVersion, sizeof(szVersion)/sizeof(TCHAR)-1, &nVersion);
LPCTSTR szFontPath = NULL;
if ((nVersion >= WNTFIRST) && (nVersion <= WNTLAST))
szFontPath = _T("Software\\Microsoft\\Windows NT\\CurrentVersion\\Fonts");
else
szFontPath = _T("Software\\Microsoft\\Windows\\CurrentVersion\\Fonts");
BOOL bResult = FALSE;
while (GetNextNameValue(HKEY_LOCAL_MACHINE, szFontPath, szName, szData) == ERROR_SUCCESS)
{
if (_tcsnicmp(lpszFontName, szName, _tcslen(lpszFontName)) == 0)
{
TRACE(_T("found font\n"));
_tcsncpy(lpszDisplayName, szName, nDisplayNameSize-1);
_tcsncpy(lpszFontFile, szData, nFontFileSize-1);
bResult = TRUE;
break;
}
szFontPath = _T(""); // this will get next value, same key
}
GetNextNameValue(HKEY_LOCAL_MACHINE, NULL, NULL, NULL); // close the registry key
return bResult;
}
bool GetFontsFolder(LPTSTR lpszFontPath, int nFontPathSize)
{
_ASSERTE(nFontPathSize >= _MAX_PATH);
*lpszFontPath = '\0';
SHGetFolderPath(NULL, CSIDL_FONTS, NULL, 0, lpszFontPath);
return *lpszFontPath != '\0';
}
///////////////////////////////////////////////////////////////////////////////
//
// GetFontProperties()
//
// Purpose: Get font name from font file
//
// Parameters: lpszFilePath - file path of font file
// lpFontPropsX - pointer to font properties struct
//
// Returns: BOOL - TRUE = success
//
BOOL GetFontProperties(LPCTSTR lpszFilePath, FONT_PROPERTIES * lpFontPropsX)
{
FONT_PROPERTIES_ANSI fp;
FONT_PROPERTIES_ANSI * lpFontProps = &fp;
memset(lpFontProps, 0, sizeof(FONT_PROPERTIES_ANSI));
HANDLE hFile = INVALID_HANDLE_VALUE;
hFile = ::CreateFile(lpszFilePath,
GENERIC_READ,// | GENERIC_WRITE,
0,
NULL,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
TRACE(_T("ERROR: failed to open '%s'\n"), lpszFilePath);
TRACE(_T("ERROR: %s failed\n"), _T("CreateFile"));
return FALSE;
}
// get the file size
DWORD dwFileSize = ::GetFileSize(hFile, NULL);
if (dwFileSize == INVALID_FILE_SIZE)
{
TRACE(_T("ERROR: %s failed\n"), _T("GetFileSize"));
::CloseHandle(hFile);
return FALSE;
}
TRACE(_T("dwFileSize = %d\n"), dwFileSize);
// Create a file mapping object that is the current size of the file
HANDLE hMappedFile = NULL;
hMappedFile = ::CreateFileMapping(hFile,
NULL,
PAGE_READONLY, //PAGE_READWRITE,
0,
dwFileSize,
NULL);
if (hMappedFile == NULL)
{
TRACE(_T("ERROR: %s failed\n"), _T("CreateFileMapping"));
::CloseHandle(hFile);
return FALSE;
}
LPBYTE lpMapAddress = (LPBYTE) ::MapViewOfFile(hMappedFile, // handle to file-mapping object
FILE_MAP_READ,//FILE_MAP_WRITE, // access mode
0, // high-order DWORD of offset
0, // low-order DWORD of offset
0); // number of bytes to map
if (lpMapAddress == NULL)
{
TRACE(_T("ERROR: %s failed\n"), _T("MapViewOfFile"));
::CloseHandle(hMappedFile);
::CloseHandle(hFile);
return FALSE;
}
BOOL bRetVal = FALSE;
int index = 0;
TT_OFFSET_TABLE ttOffsetTable;
memcpy(&ttOffsetTable, &lpMapAddress[index], sizeof(TT_OFFSET_TABLE));
index += sizeof(TT_OFFSET_TABLE);
ttOffsetTable.uNumOfTables = SWAPWORD(ttOffsetTable.uNumOfTables);
ttOffsetTable.uMajorVersion = SWAPWORD(ttOffsetTable.uMajorVersion);
ttOffsetTable.uMinorVersion = SWAPWORD(ttOffsetTable.uMinorVersion);
//check is this is a true type font and the version is 1.0
if (ttOffsetTable.uMajorVersion != 1 || ttOffsetTable.uMinorVersion != 0)
return bRetVal;
TT_TABLE_DIRECTORY tblDir;
memset(&tblDir, 0, sizeof(TT_TABLE_DIRECTORY));
BOOL bFound = FALSE;
char szTemp[4096];
memset(szTemp, 0, sizeof(szTemp));
for (int i = 0; i< ttOffsetTable.uNumOfTables; i++)
{
//f.Read(&tblDir, sizeof(TT_TABLE_DIRECTORY));
memcpy(&tblDir, &lpMapAddress[index], sizeof(TT_TABLE_DIRECTORY));
index += sizeof(TT_TABLE_DIRECTORY);
strncpy(szTemp, tblDir.szTag, 4);
if (_stricmp(szTemp, "name") == 0)
{
bFound = TRUE;
tblDir.uLength = SWAPLONG(tblDir.uLength);
tblDir.uOffset = SWAPLONG(tblDir.uOffset);
break;
}
else if (szTemp[0] == 0)
{
break;
}
}
if (bFound)
{
index = tblDir.uOffset;
TT_NAME_TABLE_HEADER ttNTHeader;
memcpy(&ttNTHeader, &lpMapAddress[index], sizeof(TT_NAME_TABLE_HEADER));
index += sizeof(TT_NAME_TABLE_HEADER);
ttNTHeader.uNRCount = SWAPWORD(ttNTHeader.uNRCount);
ttNTHeader.uStorageOffset = SWAPWORD(ttNTHeader.uStorageOffset);
TT_NAME_RECORD ttRecord;
bFound = FALSE;
for (int i = 0;
i < ttNTHeader.uNRCount &&
(lpFontProps->csCopyright[0] == 0 ||
lpFontProps->csName[0] == 0 ||
lpFontProps->csTrademark[0] == 0 ||
lpFontProps->csFamily[0] == 0);
i++)
{
memcpy(&ttRecord, &lpMapAddress[index], sizeof(TT_NAME_RECORD));
index += sizeof(TT_NAME_RECORD);
ttRecord.uNameID = SWAPWORD(ttRecord.uNameID);
ttRecord.uStringLength = SWAPWORD(ttRecord.uStringLength);
ttRecord.uStringOffset = SWAPWORD(ttRecord.uStringOffset);
if (ttRecord.uNameID == 1 || ttRecord.uNameID == 0 || ttRecord.uNameID == 7)
{
int nPos = index; //f.GetPosition();
index = tblDir.uOffset + ttRecord.uStringOffset + ttNTHeader.uStorageOffset;
memset(szTemp, 0, sizeof(szTemp));
memcpy(szTemp, &lpMapAddress[index], ttRecord.uStringLength);
index += ttRecord.uStringLength;
if (szTemp[0] != 0)
{
_ASSERTE(strlen(szTemp) < sizeof(lpFontProps->csName));
switch (ttRecord.uNameID)
{
case 0:
if (lpFontProps->csCopyright[0] == 0)
strncpy(lpFontProps->csCopyright, szTemp,
sizeof(lpFontProps->csCopyright)-1);
break;
case 1:
if (lpFontProps->csFamily[0] == 0)
strncpy(lpFontProps->csFamily, szTemp,
sizeof(lpFontProps->csFamily)-1);
bRetVal = TRUE;
break;
case 4:
if (lpFontProps->csName[0] == 0)
strncpy(lpFontProps->csName, szTemp,
sizeof(lpFontProps->csName)-1);
break;
case 7:
if (lpFontProps->csTrademark[0] == 0)
strncpy(lpFontProps->csTrademark, szTemp,
sizeof(lpFontProps->csTrademark)-1);
break;
default:
break;
}
}
index = nPos;
}
}
}
::UnmapViewOfFile(lpMapAddress);
::CloseHandle(hMappedFile);
::CloseHandle(hFile);
if (lpFontProps->csName[0] == 0)
strcpy(lpFontProps->csName, lpFontProps->csFamily);
memset(lpFontPropsX, 0, sizeof(FONT_PROPERTIES));
#ifdef _UNICODE
::MultiByteToWideChar(CP_ACP, 0, lpFontProps->csName, -1, lpFontPropsX->csName,
sizeof(lpFontPropsX->csName)/sizeof(TCHAR)-1);
::MultiByteToWideChar(CP_ACP, 0, lpFontProps->csCopyright, -1, lpFontPropsX->csCopyright,
sizeof(lpFontPropsX->csCopyright)/sizeof(TCHAR)-1);
::MultiByteToWideChar(CP_ACP, 0, lpFontProps->csTrademark, -1, lpFontPropsX->csTrademark,
sizeof(lpFontPropsX->csTrademark)/sizeof(TCHAR)-1);
::MultiByteToWideChar(CP_ACP, 0, lpFontProps->csFamily, -1, lpFontPropsX->csFamily,
sizeof(lpFontPropsX->csFamily)/sizeof(TCHAR)-1);
#else
strcpy(lpFontPropsX->csName, lpFontProps->csName);
strcpy(lpFontPropsX->csCopyright, lpFontProps->csCopyright);
strcpy(lpFontPropsX->csTrademark, lpFontProps->csTrademark);
strcpy(lpFontPropsX->csFamily, lpFontProps->csFamily);
#endif
return bRetVal;
}
///////////////////////////////////////////////////////////////////////////////
//
// GetNextNameValue()
//
// Purpose: Get first/next name/value pair from registry
//
// Parameters: key - handle to open key, or predefined key
// pszSubkey - subkey name
// pszName - pointer to buffer that receives the value string
// pszData - pointer to buffer that receives the data string
//
// Returns: LONG - return code from registry function; ERROR_SUCCESS = success
//
// Notes: If pszSubkey, pszName, and pszData are all NULL, then the open
// handle will be closed.
//
// The first time GetNextNameValue is called, pszSubkey should be
// specified. On subsequent calls, pszSubkey should be NULL or
// an empty string.
//
static LONG GetNextNameValue(HKEY key, LPCTSTR pszSubkey, LPTSTR pszName, LPTSTR pszData)
{
static HKEY hkey = NULL; // registry handle, kept open between calls
static DWORD dwIndex = 0; // count of values returned
LONG retval = ERROR_SUCCESS;
// if all parameters are NULL then close key
if (pszSubkey == NULL && pszName == NULL && pszData == NULL)
{
TRACE(_T("closing key\n"));
if (hkey)
::RegCloseKey(hkey);
hkey = NULL;
return ERROR_SUCCESS;
}
// if subkey is specified then open key (first time)
if (pszSubkey && *pszSubkey)
{
// retval = ::RegOpenKeyEx(key, pszSubkey, 0, KEY_ALL_ACCESS, &hkey); // Incapace...
retval = ::RegOpenKeyEx(key, pszSubkey, 0, KEY_READ, &hkey); // ... devi solo leggere!
if (retval != ERROR_SUCCESS)
{
TRACE(_T("ERROR: RegOpenKeyEx failed\n"));
return retval;
}
else
{
TRACE(_T("RegOpenKeyEx ok\n"));
}
dwIndex = 0;
}
else
{
dwIndex++;
}
_ASSERTE(pszName != NULL && pszData != NULL);
*pszName = 0;
*pszData = 0;
TCHAR szValueName[MAX_PATH];
DWORD dwValueNameSize = sizeof(szValueName)-1;
BYTE szValueData[MAX_PATH];
DWORD dwValueDataSize = sizeof(szValueData)-1;
DWORD dwType = 0;
retval = ::RegEnumValue(hkey, dwIndex, szValueName, &dwValueNameSize, NULL,
&dwType, szValueData, &dwValueDataSize);
if (retval == ERROR_SUCCESS)
{
TRACE(_T("szValueName=<%s> szValueData=<%s>\n"), szValueName, szValueData);
lstrcpy(pszName, (LPTSTR)szValueName);
lstrcpy(pszData, (LPTSTR)szValueData);
}
else
{
TRACE(_T("RegEnumKey failed\n"));
}
return retval;
}
// from winbase.h
#ifndef VER_PLATFORM_WIN32s
#define VER_PLATFORM_WIN32s 0
#endif
#ifndef VER_PLATFORM_WIN32_WINDOWS
#define VER_PLATFORM_WIN32_WINDOWS 1
#endif
#ifndef VER_PLATFORM_WIN32_NT
#define VER_PLATFORM_WIN32_NT 2
#endif
#ifndef VER_PLATFORM_WIN32_CE
#define VER_PLATFORM_WIN32_CE 3
#endif
/*
This table has been assembled from Usenet postings, personal
observations, and reading other people's code. Please feel
free to add to it or correct it.
dwPlatFormID dwMajorVersion dwMinorVersion dwBuildNumber
95 1 4 0 950
95 SP1 1 4 0 >950 && <=1080
95 OSR2 1 4 <10 >1080
98 1 4 10 1998
98 SP1 1 4 10 >1998 && <2183
98 SE 1 4 10 >=2183
ME 1 4 90 3000
NT 3.51 2 3 51
NT 4 2 4 0 1381
2000 2 5 0 2195
XP 2 5 1 2600
2003 2 5 2
Vista 2 6 0
2008 2 6 0
2008 R2 2 6 1
Win7 2 6 1 3600
Win8 2 6 2
Win8.1 2 6 3
Win10 2 6 4
Win10 2 10 0
CE 3
*/
///////////////////////////////////////////////////////////////////////////////
//
// GetWinVer()
//
// Purpose: Get Windows version info
//
// Parameters: lpszVersion - pointer to buffer that receives the version
// string
// nVersionSize - size of the version buffer in TCHARs
// pnVersion - pointer to int that receives the version code
//
// Returns: BOOL - TRUE = success
//
///////////////////////////////////////////////////////////////////////////////
// GetWinVer
bool GetWinVer(LPTSTR lpszVersion, int nVersionSize, int *pnVersion)
{
int nVersion = WUNKNOWN;
LPCTSTR cp = WUNKNOWNSTR;
OSVERSIONINFOEX osinfo; memset(&osinfo, 0, sizeof(osinfo));
osinfo.dwOSVersionInfoSize = sizeof(osinfo);
if (::GetVersionEx((OSVERSIONINFO*)&osinfo))
{
DWORD dwPlatformId = osinfo.dwPlatformId;
DWORD dwMinorVersion = osinfo.dwMinorVersion;
DWORD dwMajorVersion = osinfo.dwMajorVersion;
DWORD dwBuildNumber = osinfo.dwBuildNumber & 0xFFFF; // Win 95 needs this
const bool bServer = osinfo.wProductType != VER_NT_WORKSTATION;
if (dwPlatformId == VER_PLATFORM_WIN32_NT)
{
if (dwMajorVersion <= 5)
{
switch (dwMinorVersion)
{
case 0: cp = W2KSTR; nVersion = W2K; break;
case 1: cp = WXPSTR; nVersion = WXP; break;
case 2:
default: cp = W2003STR; nVersion = W2003; break;
}
} else
if (dwMajorVersion == 6)
{
switch (dwMinorVersion)
{
case 0:
if (bServer)
{ cp = W2008STR; nVersion = W2008; }
else
{ cp = WVISTASTR; nVersion = WVISTA; }
break;
case 1:
if (bServer)
{ cp = W2008R2STR; nVersion = W2008R2; }
else
{ cp = W7STR; nVersion = W7; }
break;
case 2:
case 3:
if (bServer)
{ cp = W2012STR; nVersion = W2012; }
else
{ cp = W8STR; nVersion = W8; }
break;
default:
if (bServer)
{ cp = W2016STR; nVersion = W2016; }
else
{ cp = W10STR; nVersion = W10; }
break;
}
} else
if (dwMajorVersion >= 10)
{
if (bServer)
{ cp = W2016STR; nVersion = W2016; }
else
{ cp = W10STR; nVersion = W10; }
}
}
}
if (lpszVersion != NULL && nVersionSize > 0)
_tcsncpy(lpszVersion, cp, nVersionSize-1);
if (pnVersion != NULL)
*pnVersion = nVersion;
return nVersion == WUNKNOWN;
}