Leaked source code of windows server 2003
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.

558 lines
13 KiB

  1. /*++
  2. Copyright (c) 1990-1996 Microsoft Corporation
  3. Module Name:
  4. mkgly.c
  5. Abstract:
  6. Construct FD_GLYPHSET structure in memory and dump it as binary
  7. data so that a printer driver can include it in its resource.
  8. The input data format is as following:
  9. <codepage>
  10. <multibyte code>\t<run length>
  11. <multibyte code>\t<run length>
  12. ...
  13. "codepage" is the codepage id to be used in multibyte to Unicode
  14. conversion. "Multibyte code" and "run length" pairs describes
  15. which codepoints of multibyte codes are available on the device.
  16. mkgly will warn if there are multiple multibyte codepoints which
  17. are mapped to single Unicode codepoint. The user is expected
  18. to fix this in the source, then re-run mkgly.
  19. Follogins are command line options recogized by mkgly:
  20. -e Allow EUDC codepoints. Default is not allow.
  21. -t Output mapping table in text format also.
  22. -v Verbose.
  23. Author:
  24. 08-Apr-1995 Sat 00:00:00 created -by- Takashi Matsuzawa (takashim)
  25. 03-Mar-1996 Sat 00:00:00 updated -by- Takashi Matsuzawa (takashim)
  26. Environment:
  27. GDI device drivers (printer)
  28. Notes:
  29. Revision History:
  30. --*/
  31. #include <stddef.h>
  32. #include <stdlib.h>
  33. #include <stdio.h>
  34. #include <windows.h>
  35. #include <winddi.h>
  36. #include <wingdi.h>
  37. #define MIN_WCHAR_VALUE 0x0000
  38. #define MAX_WCHAR_VALUE 0xfffd
  39. #define INVALID_WCHAR_VALUE 0xffff
  40. #define IS_COMMENT(c) \
  41. ((c) == ';' || (c) == '#' || (c) == '%' || (c) == '\n')
  42. #define IS_EUDC_W(wc) \
  43. ((wc) >= 0xe000 && (wc) <= 0xf8ff)
  44. WORD awMultiByteArray[0x10000];
  45. BOOL bEudc, bTable, bGTTHandleBase;
  46. INT iVerbose;
  47. FD_GLYPHSET
  48. *pvBuildGlyphSet(
  49. WORD *pwArray,
  50. DWORD dwcbByte)
  51. /*++
  52. Routine Description:
  53. Build FD_GLYPHSET data on memory.
  54. Arguments:
  55. Return Value:
  56. None.
  57. Author:
  58. 08-Apr-1995 Sat 00:00:00 created -by- Takashi Matsuzawa (takashim)
  59. Revision History:
  60. --*/
  61. {
  62. DWORD cGlyphs; // count of glyph handles.
  63. DWORD cRuns; // count of runs within FD_GLYPHSET.
  64. DWORD cbTotalMem; // count of bytes needed for FD_GLYPHSET.
  65. HGLYPH *phg; // pointer to HGLYPH's.
  66. FD_GLYPHSET *pGlyphSet;
  67. WCRUN *pWCRun;
  68. BOOL bFirst;
  69. WCHAR wcChar, wcPrev, wcGTTHandle;
  70. DWORD cEudc;
  71. DWORD cRunsGlyphs = 0;
  72. if (NULL == pwArray ||
  73. 0 == dwcbByte )
  74. {
  75. fprintf( stderr, "pvBuildGlyphSet: Invalid paremeters.\n" );
  76. return NULL;
  77. }
  78. if (dwcbByte < MAX_WCHAR_VALUE * 2)
  79. {
  80. fprintf( stderr, "pvBuildGlyphSet: Invalid paremeters.\n" );
  81. return NULL;
  82. }
  83. cRuns = 0;
  84. cGlyphs = 0;
  85. cEudc = 0;
  86. bFirst = TRUE;
  87. for ( wcChar = MIN_WCHAR_VALUE; wcChar <= MAX_WCHAR_VALUE; wcChar++)
  88. {
  89. if (pwArray[wcChar] == INVALID_WCHAR_VALUE)
  90. continue;
  91. // GDI can't handle the value which cRunsGlyphs over 256. sueyas
  92. if (bFirst || (wcChar - wcPrev) > 1 || cRunsGlyphs++ > 255)
  93. {
  94. if (bFirst)
  95. bFirst = FALSE;
  96. cRuns++;
  97. cRunsGlyphs = 1;
  98. }
  99. if (IS_EUDC_W(wcChar))
  100. cEudc++;
  101. cGlyphs++;
  102. wcPrev = wcChar;
  103. }
  104. if (iVerbose > 1) {
  105. fprintf( stderr, "cGlyphs = %d, cRuns = %d\n", cGlyphs, cRuns );
  106. }
  107. // Allocate memory to build the FD_GLYPHSET structure in. this
  108. // include space for the FD_GLYPHSET structure itself, as well
  109. // as space for all the glyph handles.
  110. // DWORD bound it.
  111. cbTotalMem = sizeof(FD_GLYPHSET) - sizeof(WCRUN)
  112. + cRuns * sizeof(WCRUN) + cGlyphs * sizeof(HGLYPH);
  113. cbTotalMem = (cbTotalMem + 3) & ~3;
  114. if ((phg = (PVOID)GlobalAlloc( 0, cbTotalMem )) == NULL) {
  115. fprintf( stderr, "Error alloating memory\n" );
  116. return NULL;
  117. }
  118. // fill in the FD_GLYPHSET structure.
  119. pGlyphSet = (FD_GLYPHSET *)phg;
  120. pGlyphSet->cjThis
  121. = sizeof(FD_GLYPHSET) - sizeof(WCRUN)
  122. + cRuns * sizeof(WCRUN); // size excluding HGLYPH array.
  123. pGlyphSet->flAccel = 0; // no accelerators for us.
  124. pGlyphSet->cGlyphsSupported = cGlyphs;
  125. pGlyphSet->cRuns = cRuns;
  126. // Now set the phg pointer to the first WCRUN structure.
  127. (PBYTE)phg += (sizeof(FD_GLYPHSET) - sizeof(WCRUN));
  128. pWCRun = (WCRUN *)phg;
  129. (PBYTE)phg += sizeof(WCRUN) * cRuns;
  130. if (bTable || iVerbose > 0)
  131. {
  132. fprintf(stdout, "; Number of glyphs = %ld\n", cGlyphs );
  133. fprintf(stdout, "; Number of eudc = %ld\n", cEudc);
  134. }
  135. bFirst = TRUE;
  136. cRunsGlyphs = 0;
  137. for ( wcGTTHandle = 1,wcChar = MIN_WCHAR_VALUE;
  138. wcChar <= MAX_WCHAR_VALUE;
  139. wcChar++)
  140. {
  141. if (pwArray[wcChar] == INVALID_WCHAR_VALUE)
  142. continue;
  143. // GDI can't handle the value which cRunsGlyphs over 256. sueyas
  144. if (bFirst || (wcChar - wcPrev) > 1 || cRunsGlyphs++ > 255)
  145. {
  146. if (bFirst)
  147. bFirst = FALSE;
  148. else
  149. pWCRun++;
  150. pWCRun->wcLow = wcChar;
  151. pWCRun->cGlyphs = 0;
  152. pWCRun->phg = phg;
  153. cRunsGlyphs = 1;
  154. }
  155. // Glyph handle needs to be stored anyway.
  156. *phg++ = (HGLYPH)wcGTTHandle++;
  157. pWCRun->cGlyphs++;
  158. wcPrev = wcChar;
  159. if (bTable)
  160. {
  161. fprintf(stdout, "%x\t%x\n", wcChar, pwArray[wcChar]);
  162. }
  163. }
  164. // Debug output
  165. if (iVerbose > 1) {
  166. INT i, j;
  167. fprintf( stderr, "FD_GLYPHSET\n" );
  168. fprintf( stderr, "->cjThis = %d (%d + %d)\n", pGlyphSet->cjThis,
  169. sizeof (FD_GLYPHSET) - sizeof (WCRUN),
  170. pGlyphSet->cjThis - sizeof (FD_GLYPHSET) + sizeof (WCRUN) );
  171. fprintf( stderr, "->fdAccel = %08lx\n", pGlyphSet->flAccel );
  172. fprintf( stderr, "->cGlyphsSupported = %d\n",
  173. pGlyphSet->cGlyphsSupported );
  174. fprintf( stderr, "->cRuns = %d\n", pGlyphSet->cRuns );
  175. if (iVerbose > 2)
  176. {
  177. for ( i = 0; i < (INT)pGlyphSet->cRuns; i++ ) {
  178. fprintf( stderr, "awcrun[%d]->wcLow = %04x\n",
  179. i, pGlyphSet->awcrun[i].wcLow );
  180. fprintf( stderr, "awcrun[%d]->cGlyphs = %d\n",
  181. i, pGlyphSet->awcrun[i].cGlyphs );
  182. //
  183. // This casting could chop a 64 pointer.
  184. // This tools is assumed to be used only on 32.
  185. // Also this is a verbose mode output to stdout. It won't
  186. // cause any serious problem.
  187. //
  188. fprintf( stderr, "awcrun[%d]->phg = %lx\n",
  189. i, (LONG)pGlyphSet->awcrun[i].phg );
  190. if (iVerbose > 3)
  191. {
  192. for ( j = 0; j < pGlyphSet->awcrun[i].cGlyphs; j++ )
  193. fprintf( stderr, "%02x,",
  194. pGlyphSet->awcrun[i].phg[j] );
  195. fprintf( stderr, "\n" );
  196. } /* iVerbose > 3 */
  197. }
  198. } /* iVerbose > 2 */
  199. }
  200. return pGlyphSet;
  201. }
  202. BOOL
  203. bWriteGlyphSet(
  204. FD_GLYPHSET *pGlyphSet,
  205. CHAR *pFileName )
  206. /*++
  207. Routine Description:
  208. Dump FD_GLYPHSET data into specified file.
  209. Arguments:
  210. Return Value:
  211. None.
  212. Author:
  213. 08-Apr-1995 Sat 00:00:00 created -by- Takashi Matsuzawa (takashim)
  214. Revision History:
  215. --*/
  216. {
  217. HANDLE hFile;
  218. ULONG iIndex;
  219. WCRUN *pWcRun;
  220. HGLYPH *phg;
  221. DWORD dwTmp;
  222. if ((hFile = CreateFileA(
  223. pFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0))
  224. == INVALID_HANDLE_VALUE) {
  225. return FALSE;
  226. }
  227. // FD_GLYPHSET structure itself + WCRUN array
  228. if (!WriteFile( hFile, pGlyphSet, pGlyphSet->cjThis,
  229. &dwTmp, NULL )) {
  230. return FALSE;
  231. }
  232. // HGLYPH array
  233. if (!WriteFile( hFile, pGlyphSet->awcrun[0].phg,
  234. pGlyphSet->cGlyphsSupported * sizeof (HGLYPH),
  235. &dwTmp, NULL )) {
  236. return FALSE;
  237. }
  238. if (!CloseHandle( hFile )) {
  239. return FALSE;
  240. }
  241. return TRUE;
  242. }
  243. VOID
  244. Usage()
  245. {
  246. fprintf ( stderr, "\nUsage : mkgly [-etvv] outfile\n" );
  247. exit (EXIT_FAILURE);
  248. }
  249. BOOL
  250. GetLine(
  251. BYTE *pjBuffer,
  252. INT cjSize)
  253. {
  254. do
  255. {
  256. if(fgets(pjBuffer, cjSize, stdin) == NULL)
  257. return FALSE;
  258. } while (IS_COMMENT(*pjBuffer));
  259. return TRUE;
  260. }
  261. void __cdecl
  262. main(
  263. int argc,
  264. char *argv[] )
  265. /*++
  266. Routine Description:
  267. Main routine for mkgly.exe
  268. Arguments:
  269. Output filename. Input data is read from standard input.
  270. Return Value:
  271. None.
  272. Author:
  273. 08-Apr-1995 Sat 00:00:00 created -by- Takashi Matsuzawa (takashim)
  274. Revision History:
  275. --*/
  276. {
  277. FD_GLYPHSET *pGlyphSet;
  278. CHAR *pFileName;
  279. INT iRet;
  280. INT iMbLen;
  281. CHAR *pStr;
  282. WORD wCodePage;
  283. WORD wMbChar, wMbRun, wMbChar2;
  284. WCHAR wcSysChar;
  285. BYTE ajMbChar[2];
  286. BYTE ajBuffer[256];
  287. bEudc = FALSE;
  288. bTable = FALSE;
  289. iVerbose = 0;
  290. pFileName = NULL;
  291. bGTTHandleBase = FALSE;
  292. while (--argc)
  293. {
  294. pStr = *(++argv);
  295. if (*pStr == '-')
  296. {
  297. for ( pStr++; *pStr; pStr++)
  298. {
  299. if (*pStr == 'e')
  300. bEudc = TRUE;
  301. else if (*pStr == 't')
  302. bTable = TRUE;
  303. else if (*pStr == 'v')
  304. iVerbose++;
  305. else if (*pStr == 'g')
  306. bGTTHandleBase = TRUE;
  307. else
  308. Usage();
  309. }
  310. }
  311. else
  312. {
  313. pFileName = pStr;
  314. break;
  315. }
  316. }
  317. if (pFileName == NULL)
  318. {
  319. Usage();
  320. }
  321. // get the codepage id used for conversion
  322. if (!GetLine(ajBuffer, sizeof(ajBuffer)))
  323. {
  324. fprintf(stderr, "mkgly: unexpected end of file\n");
  325. exit(EXIT_FAILURE);
  326. }
  327. if (EOF == (iRet = sscanf(ajBuffer, "%hd", &wCodePage )))
  328. {
  329. fprintf(stderr, "mkgly: unexpected end of file.\n");
  330. exit(EXIT_FAILURE);
  331. }
  332. if (0 == iRet)
  333. {
  334. fprintf(stderr, "mkgly: unexpected string.\n");
  335. exit(EXIT_FAILURE);
  336. }
  337. if (iVerbose)
  338. {
  339. fprintf(stderr, "mkgly: wCodePage = %d\n", wCodePage);
  340. }
  341. memset(awMultiByteArray, 0xff, sizeof(awMultiByteArray));
  342. while (1)
  343. {
  344. if (!GetLine(ajBuffer, sizeof(ajBuffer)))
  345. break;
  346. if ( sscanf (ajBuffer, "%hx%hd", &wMbChar, &wMbRun ) != 2 )
  347. {
  348. fprintf(stderr, "mkgly: unrecognized line - \"%s\"\n", ajBuffer);
  349. exit(EXIT_FAILURE);
  350. }
  351. if (iVerbose > 1)
  352. {
  353. fprintf(stderr, "mkgly: wMbChar = %x, wMbrun = %d\n",
  354. wMbChar, wMbRun);
  355. }
  356. for (; wMbRun--; wMbChar++)
  357. {
  358. iMbLen = 0;
  359. if (wMbChar & 0xff00)
  360. {
  361. ajMbChar[iMbLen++] = (BYTE)((wMbChar >> 8) & 0xff);
  362. }
  363. ajMbChar[iMbLen++] = (BYTE)(wMbChar & 0xff);
  364. if (MultiByteToWideChar(wCodePage, MB_ERR_INVALID_CHARS,
  365. ajMbChar, iMbLen, &wcSysChar, 1) != 1)
  366. {
  367. fprintf(stderr, "mkgly: MultiByteToWideChar failed - %d\n",
  368. GetLastError());
  369. exit(EXIT_FAILURE);
  370. }
  371. if ((iMbLen = WideCharToMultiByte(wCodePage, 0,
  372. &wcSysChar, 1, ajMbChar, sizeof(ajMbChar), NULL, NULL)) == FALSE)
  373. {
  374. fprintf(stderr, "mkgly: WideCharToMultiByte failed - %d\n",
  375. GetLastError());
  376. exit(EXIT_FAILURE);
  377. }
  378. if (iMbLen == 2)
  379. wMbChar2 = (ajMbChar[0] << 8) + ajMbChar[1];
  380. else
  381. wMbChar2 = ajMbChar[0];
  382. if (wMbChar != wMbChar2)
  383. {
  384. fprintf(stderr, "mkgly: round-trip not achieved %x => %x => %x\n",
  385. wMbChar, wcSysChar, wMbChar2 );
  386. }
  387. if (IS_EUDC_W(wcSysChar))
  388. {
  389. if (iVerbose > 1)
  390. {
  391. fprintf(stderr, "mkgly: eudc character %x => %x%s\n",
  392. wcSysChar, wMbChar, (bEudc ? "" : " ignored."));
  393. }
  394. if (!bEudc)
  395. continue;
  396. }
  397. if (awMultiByteArray[wcSysChar] != INVALID_WCHAR_VALUE)
  398. {
  399. fprintf(stderr, "mkgly: duplicate mapping %x => %x overwritten by => %x\n",
  400. wcSysChar, awMultiByteArray[wcSysChar], wMbChar);
  401. }
  402. awMultiByteArray[wcSysChar] = wMbChar;
  403. }
  404. }
  405. if ((pGlyphSet = pvBuildGlyphSet( awMultiByteArray, sizeof(awMultiByteArray) )) == NULL) {
  406. fprintf( stderr, "Error creating FD_GLYPHSET structure.\n" );
  407. return;
  408. }
  409. bWriteGlyphSet( pGlyphSet, pFileName );
  410. GlobalFree( pGlyphSet );
  411. }