Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

607 lines
17 KiB

  1. /*++
  2. Copyright (c) 2001 Microsoft Corporation
  3. Module Name:
  4. convfont.c
  5. Abstract:
  6. This module contains the code that implements a bootfont.bin conversion
  7. program.
  8. This tool converts a bootfont.bin that is circa windows 2000 \ nt4 and
  9. converts it into the windows whistler format. The new format includes a
  10. column of information on unicode translation of MBCS characters.
  11. Author:
  12. Matt Holle (MattH) 8-March-2001
  13. Revision History:
  14. --*/
  15. #include <windows.h>
  16. #include <stdlib.h>
  17. #include <stdio.h>
  18. #include <tchar.h>
  19. #include <locale.h>
  20. // #include "..\..\lib\i386\bootfont.h"
  21. // #include "fonttable.h"
  22. #define BYTES_PER_SBCS_CHARACTER (17)
  23. #define BYTES_PER_DBCS_CHARACTER (34)
  24. //
  25. // Define maximum number of dbcs lead byte ranges we support.
  26. //
  27. #define MAX_DBCS_RANGE 5
  28. //
  29. // Define signature value.
  30. //
  31. #define BOOTFONTBIN_SIGNATURE 0x5465644d
  32. //
  33. // Define structure used as a header for the bootfont.bin file.
  34. //
  35. typedef struct _BOOTFONTBIN_HEADER {
  36. //
  37. // Signature. Must be BOOTFONTBIN_SIGNATURE.
  38. //
  39. ULONG Signature;
  40. //
  41. // Language id of the language supported by this font.
  42. // This should match the language id of resources in msgs.xxx.
  43. //
  44. ULONG LanguageId;
  45. //
  46. // Number of sbcs characters and dbcs characters contained in the file.
  47. //
  48. unsigned NumSbcsChars;
  49. unsigned NumDbcsChars;
  50. //
  51. // Offsets within the file to the images.
  52. //
  53. unsigned SbcsOffset;
  54. unsigned DbcsOffset;
  55. //
  56. // Total sizes of the images.
  57. //
  58. unsigned SbcsEntriesTotalSize;
  59. unsigned DbcsEntriesTotalSize;
  60. //
  61. // Dbcs lead byte table. Must contain a pair of 0's to indicate the end.
  62. //
  63. UCHAR DbcsLeadTable[(MAX_DBCS_RANGE+1)*2];
  64. //
  65. // Height values for the font.
  66. // CharacterImageHeight is the height in scan lines/pixels of the
  67. // font image. Each character is drawn with additional 'padding'
  68. // lines on the top and bottom, whose sizes are also contained here.
  69. //
  70. UCHAR CharacterImageHeight;
  71. UCHAR CharacterTopPad;
  72. UCHAR CharacterBottomPad;
  73. //
  74. // Width values for the font. These values contain the width in pixels
  75. // of a single byte character and double byte character.
  76. //
  77. // NOTE: CURRENTLY THE SINGLE BYTE WIDTH *MUST* BE 8 AND THE DOUBLE BYTE
  78. // WIDTH *MUST* BE 16!!!
  79. //
  80. UCHAR CharacterImageSbcsWidth;
  81. UCHAR CharacterImageDbcsWidth;
  82. } BOOTFONTBIN_HEADER, *PBOOTFONTBIN_HEADER;
  83. int
  84. __cdecl
  85. main(
  86. IN int argc,
  87. IN char *argv[]
  88. )
  89. {
  90. HANDLE hInputFile = INVALID_HANDLE_VALUE;
  91. HANDLE hOutputFile = INVALID_HANDLE_VALUE;
  92. DWORD BytesWritten = 0;
  93. BOOL b;
  94. BOOL Verbose = FALSE;
  95. BOOTFONTBIN_HEADER *pHeader;
  96. ULONG u = 0;
  97. ULONG i = 0;
  98. UCHAR *SBCSFontImage;
  99. UCHAR *DBCSFontImage;
  100. UCHAR *Operator;
  101. WCHAR UnicodeValue;
  102. UCHAR *ExistingFileBuffer = NULL;
  103. BOOLEAN DumpIt = FALSE;
  104. if( !strcmp(argv[argc-1], "-v") ) {
  105. Verbose = TRUE;
  106. } else {
  107. if( !strcmp(argv[argc-1], "-d") ) {
  108. DumpIt = TRUE;
  109. Verbose = TRUE;
  110. }
  111. }
  112. if( !DumpIt && (argc < 3)) {
  113. fprintf(stderr,"Usage: %s <inputfile> <outputfile>\n",argv[0]);
  114. fprintf(stderr,"\n" );
  115. fprintf(stderr," Where <inputfile> is a bootfont.bin file to be translated\n");
  116. fprintf(stderr," into the new format\n");
  117. fprintf(stderr,"\n" );
  118. fprintf(stderr," <outputfile> is the destination file.\n" );
  119. fprintf(stderr,"\n" );
  120. fprintf(stderr," NOTE: You must have the proper locale files installed and configured on your\n" );
  121. fprintf(stderr," machine. To do this, start up intl.cpl, go to the Advanced tab and select.\n" );
  122. fprintf(stderr," the Language setting to correspond to the language of the bootfont.bin file.\n" );
  123. fprintf(stderr," Make sure you check the 'Apply all settings to the current...' tab too.\n" );
  124. fprintf(stderr,"\n" );
  125. goto Cleanup;
  126. }
  127. if( Verbose && !DumpIt ) {
  128. //
  129. // spew input.
  130. //
  131. printf( "Running in Verbose Mode\n" );
  132. printf( "InputFile: %s\n", argv[1] );
  133. printf( "OutputFile: %s\n", argv[2] );
  134. }
  135. //
  136. // Open the input file.
  137. //
  138. hInputFile = CreateFile( argv[1],
  139. GENERIC_READ,
  140. FILE_SHARE_READ,
  141. NULL,
  142. OPEN_EXISTING,
  143. 0,
  144. NULL );
  145. if(hInputFile == INVALID_HANDLE_VALUE) {
  146. fprintf( stderr, "\nUnable to open input file %s (%u)\n", argv[1], GetLastError());
  147. goto Cleanup;
  148. }
  149. if( !DumpIt ) {
  150. //
  151. // Create the output file.
  152. //
  153. hOutputFile = CreateFile( argv[2],
  154. FILE_GENERIC_WRITE,
  155. 0,
  156. NULL,
  157. CREATE_ALWAYS,
  158. 0,
  159. NULL );
  160. if(hOutputFile == INVALID_HANDLE_VALUE) {
  161. fprintf( stderr, "\nUnable to create output file %s (%u)\n", argv[2], GetLastError());
  162. goto Cleanup;
  163. }
  164. }
  165. //
  166. // Figure out how big the existing file is.
  167. //
  168. BytesWritten = GetFileSize( hInputFile, NULL );
  169. if( BytesWritten == (DWORD)(-1) ) {
  170. fprintf( stderr, "\nAn error occured getting the file size.\n" );
  171. goto Cleanup;
  172. }
  173. //
  174. // Allocate a buffer for the file.
  175. //
  176. ExistingFileBuffer = malloc(BytesWritten + 3);
  177. b = ReadFile( hInputFile,
  178. ExistingFileBuffer,
  179. BytesWritten,
  180. &i,
  181. NULL );
  182. CloseHandle( hInputFile );
  183. hInputFile = INVALID_HANDLE_VALUE;
  184. if( !b ) {
  185. fprintf( stderr, "\nError reading input file %s\n", argv[1] );
  186. goto Cleanup;
  187. }
  188. //
  189. // Read in the header.
  190. //
  191. pHeader = (BOOTFONTBIN_HEADER *)ExistingFileBuffer;
  192. // Tell the user about the bootfont.bin file that we read.
  193. if( Verbose ) {
  194. printf( "Size of BOOTFONTBIN_HEADER: %d\n", sizeof(BOOTFONTBIN_HEADER) );
  195. printf( "\nRead Header Data:\n" );
  196. printf( "=================\n" );
  197. printf( "Header.Signature: 0x%08lx\n", pHeader->Signature );
  198. printf( "Header.LanguageId: 0x%08lx\n", pHeader->LanguageId );
  199. printf( "Header.NumSbcsChars: 0x%08lx\n", pHeader->NumSbcsChars );
  200. printf( "Header.NumDbcsChars: 0x%08lx\n", pHeader->NumDbcsChars );
  201. printf( "Header.SbcsOffset: 0x%08lx\n", pHeader->SbcsOffset );
  202. printf( "Header.DbcsOffset: 0x%08lx\n", pHeader->DbcsOffset );
  203. printf( "Header.SbcsEntriesTotalSize: 0x%08lx\n", pHeader->SbcsEntriesTotalSize );
  204. printf( "Header.DbcsEntriesTotalSize: 0x%08lx\n", pHeader->DbcsEntriesTotalSize );
  205. printf( "\n" );
  206. }
  207. if( DumpIt ) {
  208. //
  209. // Just Dump the contents of the bootfont.bin file in
  210. // a more readable format.
  211. //
  212. SBCSFontImage = ExistingFileBuffer + pHeader->SbcsOffset;
  213. DBCSFontImage = ExistingFileBuffer + pHeader->DbcsOffset;
  214. i = pHeader->SbcsEntriesTotalSize / pHeader->NumSbcsChars;
  215. if( i == BYTES_PER_SBCS_CHARACTER+2 ) {
  216. printf( "Dumping contents of file %s\n", argv[1] );
  217. printf( "\nSBCS Values:\n" );
  218. printf( "============\n" );
  219. for( u=0; u < pHeader->NumSbcsChars; u++ ) {
  220. // jump to the u-th element. 1 byte for the SBCS character, 16 for the
  221. // glyph.
  222. Operator = SBCSFontImage + (u * (BYTES_PER_SBCS_CHARACTER+2));
  223. printf( "SBCS character code: 0x%02lx Unicode value: 0x%04lx\n", *Operator, *(WCHAR *)(Operator + BYTES_PER_SBCS_CHARACTER) );
  224. }
  225. printf( "\nDBCS Values:\n" );
  226. printf( "============\n" );
  227. for( u=0; u < pHeader->NumDbcsChars; u++ ) {
  228. // jump to the u-th element. 1 byte for the SBCS character, 16 for the
  229. // glyph.
  230. Operator = DBCSFontImage + (u * (BYTES_PER_DBCS_CHARACTER+2));
  231. printf( "DBCS character code: 0x%04lx Unicode value: 0x%04lx\n", *(WCHAR *)Operator, *(WCHAR *)(Operator + BYTES_PER_DBCS_CHARACTER) );
  232. }
  233. printf( "\n\n" );
  234. goto Cleanup;
  235. }
  236. }
  237. //
  238. // Verify the header's signature.
  239. //
  240. if( pHeader->Signature != BOOTFONTBIN_SIGNATURE ) {
  241. fprintf( stderr, "\nInputfile %s does not have a valid signature\n", argv[1] );
  242. goto Cleanup;
  243. }
  244. //
  245. // Verify that this isn't already in the new format. We can test this by
  246. // looking at how many SBCS characters are stored in here. Then looking at
  247. // how big the header says the SBCS data section is.
  248. //
  249. // We know that for each SBCS character, we would have:
  250. // 1 byte for the SBCS character
  251. // 16 bytes for the glyph
  252. //
  253. // If it's an old-style bootfont.bin, the total size of the SBCS data block
  254. // should be 17 times bigger than the number of SBCS characters. However, if
  255. // it's a new-style bootfont.bin, it will be 19 times bigger because we've
  256. // added 2 bytes onto the end of each SBCS entry (for a total of 19 bytes).
  257. //
  258. i = pHeader->SbcsEntriesTotalSize / pHeader->NumSbcsChars;
  259. if( i != BYTES_PER_SBCS_CHARACTER ) {
  260. if( i == (BYTES_PER_SBCS_CHARACTER+2) ) {
  261. fprintf( stderr, "\nThis input file is already in the new format.\n" );
  262. } else {
  263. fprintf( stderr, "\nThis input file has an abnormal number of bytes per SBCS character (%d)\n", i );
  264. }
  265. goto Cleanup;
  266. }
  267. //
  268. // Now check the number of bytes per DBCS character.
  269. //
  270. i = pHeader->DbcsEntriesTotalSize / pHeader->NumDbcsChars;
  271. if( i != BYTES_PER_DBCS_CHARACTER ) {
  272. if( i == (BYTES_PER_DBCS_CHARACTER+2) ) {
  273. fprintf( stderr, "\nThis input file is already in the new format.\n" );
  274. } else {
  275. fprintf( stderr, "\nThis input file has an abnormal number of bytes per DBCS character (%d)\n", i );
  276. }
  277. goto Cleanup;
  278. }
  279. //
  280. // Looking good.
  281. //
  282. printf( "Processing %s...\n", argv[1] );
  283. //
  284. // Before updating and writing out the header, we need to examine
  285. // the header and remember where the SBCS and DBCS data blocks are
  286. // in our image.
  287. //
  288. SBCSFontImage = ExistingFileBuffer + pHeader->SbcsOffset;
  289. DBCSFontImage = ExistingFileBuffer + pHeader->DbcsOffset;
  290. //
  291. // Fixup the Header, then write it out.
  292. //
  293. // Add 2 bytes for each entry for our unicode appendage
  294. pHeader->SbcsEntriesTotalSize += (pHeader->NumSbcsChars * 2);
  295. pHeader->DbcsEntriesTotalSize += (pHeader->NumDbcsChars * 2);
  296. // The offset to the DBCS data block will have changed now too.
  297. pHeader->DbcsOffset = pHeader->SbcsOffset + pHeader->SbcsEntriesTotalSize;
  298. // Tell the user about the bootfont.bin file that we read.
  299. if( Verbose ) {
  300. printf( "\nUpdated Header Data:\n" );
  301. printf( "======================\n" );
  302. printf( "Header.Signature: 0x%08lx\n", pHeader->Signature );
  303. printf( "Header.LanguageId: 0x%08lx\n", pHeader->LanguageId );
  304. printf( "Header.NumSbcsChars: 0x%08lx\n", pHeader->NumSbcsChars );
  305. printf( "Header.NumDbcsChars: 0x%08lx\n", pHeader->NumDbcsChars );
  306. printf( "Header.SbcsOffset: 0x%08lx\n", pHeader->SbcsOffset );
  307. printf( "Header.DbcsOffset: 0x%08lx\n", pHeader->DbcsOffset );
  308. printf( "Header.SbcsEntriesTotalSize: 0x%08lx\n", pHeader->SbcsEntriesTotalSize );
  309. printf( "Header.DbcsEntriesTotalSize: 0x%08lx\n", pHeader->DbcsEntriesTotalSize );
  310. printf( "\n" );
  311. }
  312. //
  313. // Write the header.
  314. //
  315. b = WriteFile( hOutputFile,
  316. pHeader,
  317. sizeof(BOOTFONTBIN_HEADER),
  318. &BytesWritten,
  319. NULL );
  320. if(!b) {
  321. fprintf( stderr, "\nError writing output file %s (%u)\n", argv[2], GetLastError());
  322. goto Cleanup;
  323. }
  324. //
  325. // Write the sbcs images.
  326. //
  327. if( !Verbose ) {
  328. printf( "Operating on SBCS character code: 0x00" );
  329. }
  330. for( u=0; u < pHeader->NumSbcsChars; u++ ) {
  331. // jump to the u-th element. 1 byte for the SBCS character, 16 for the
  332. // glyph.
  333. Operator = SBCSFontImage + (u * BYTES_PER_SBCS_CHARACTER);
  334. b = WriteFile( hOutputFile,
  335. Operator,
  336. BYTES_PER_SBCS_CHARACTER,
  337. &BytesWritten,
  338. NULL );
  339. if( !b ) {
  340. fprintf( stderr, "\nFailed to write SBCS character data.\n" );
  341. goto Cleanup;
  342. }
  343. //
  344. // We must use MultiByteToWideChar to convert from SBCS to unicode.
  345. //
  346. // MultiByteToWideChar doesn't seem to work when converting
  347. // from DBCS to unicode, so there we use mbtowc.
  348. //
  349. #if 0
  350. if( !mbtowc( (WCHAR *)&UnicodeValue, Operator, 1 ) ) {
  351. #else
  352. if( !MultiByteToWideChar( CP_OEMCP,
  353. MB_ERR_INVALID_CHARS,
  354. Operator,
  355. 1,
  356. (WCHAR *)&UnicodeValue,
  357. sizeof(WCHAR) ) ) {
  358. #endif
  359. UnicodeValue = 0x3F;
  360. if( Verbose ) {
  361. fprintf( stderr, "\nFailed to convert SBCS character 0x%02lx to a unicode value. Using '?' character.\n", *Operator );
  362. }
  363. }
  364. if( Verbose ) {
  365. printf( "Converting SBCS character code: 0x%02lx to a unicode value: 0x%04lx\n", *Operator, UnicodeValue );
  366. } else {
  367. printf( "\b\b\b\b0x%02lx", *Operator );
  368. }
  369. b = WriteFile( hOutputFile,
  370. &UnicodeValue,
  371. sizeof(USHORT),
  372. &BytesWritten,
  373. NULL );
  374. if( !b ) {
  375. fprintf( stderr, "\nFailed to write SBCS encoded UNICODE value.\n" );
  376. goto Cleanup;
  377. }
  378. }
  379. printf( "\nCompleted processing %d SBCS characters.\n\n", pHeader->NumSbcsChars );
  380. //
  381. // Write the dbcs images.
  382. //
  383. if( !Verbose ) {
  384. printf( "Operating on DBCS character code: 0x0000" );
  385. }
  386. for( u=0; u < pHeader->NumDbcsChars; u++ ) {
  387. // jump to the u-th element. 1 byte for the SBCS character, 16 for the
  388. // glyph.
  389. Operator = DBCSFontImage + (u * BYTES_PER_DBCS_CHARACTER);
  390. b = WriteFile( hOutputFile,
  391. Operator,
  392. BYTES_PER_DBCS_CHARACTER,
  393. &BytesWritten,
  394. NULL );
  395. if( !b || (BytesWritten != BYTES_PER_DBCS_CHARACTER) ) {
  396. fprintf( stderr, "\nFailed to write DBCS character data.\n" );
  397. goto Cleanup;
  398. }
  399. //
  400. // We must use mbtowc to convert from DBCS to unicode.
  401. //
  402. // Whereas, mbtowc doesn't seem to work when converting
  403. // from SBCS to unicode, so there we use MultiByteToWideChar.
  404. //
  405. #if 0
  406. if( !mbtowc( (WCHAR *)&UnicodeValue, Operator, 2 ) ) {
  407. #else
  408. if( !MultiByteToWideChar( CP_OEMCP,
  409. MB_ERR_INVALID_CHARS,
  410. Operator,
  411. 2,
  412. (WCHAR *)&UnicodeValue,
  413. sizeof(WCHAR) ) ) {
  414. #endif
  415. UnicodeValue = 0x3F;
  416. if( Verbose ) {
  417. fprintf( stderr, "\nFailed to convert DBCS character 0x%04lx to a unicode value. Using '?' character.\n", *(WCHAR *)Operator );
  418. }
  419. }
  420. if( Verbose ) {
  421. printf( "Converting DBCS character code: 0x%04lx to Unicode value: 0x%04lx\n", *(WCHAR *)Operator, UnicodeValue );
  422. } else {
  423. printf( "\b\b\b\b\b\b0x%04lx", *(WCHAR *)Operator );
  424. }
  425. b = WriteFile( hOutputFile,
  426. &UnicodeValue,
  427. sizeof(WCHAR),
  428. &BytesWritten,
  429. NULL );
  430. if( !b || (BytesWritten != sizeof(WCHAR)) ) {
  431. fprintf( stderr, "\nFailed to write DBCS encoded UNICODE value.\n" );
  432. goto Cleanup;
  433. }
  434. }
  435. printf( "\nCompleted processing %d DBCS characters.\n", pHeader->NumDbcsChars );
  436. printf( "\nSuccessfully Processed file %s to %s.\n", argv[1], argv[2] );
  437. //
  438. // Done.
  439. //
  440. Cleanup:
  441. if( hInputFile != INVALID_HANDLE_VALUE ) {
  442. CloseHandle( hInputFile );
  443. }
  444. if( hOutputFile != INVALID_HANDLE_VALUE ) {
  445. CloseHandle( hOutputFile );
  446. }
  447. if( ExistingFileBuffer != NULL ) {
  448. free( ExistingFileBuffer );
  449. }
  450. return(0);
  451. }