/*++ Copyright (c) 1996 Microsoft Corporation Module Name: makentf.c Abstract: Utility to convert AFM file(s) to NTF file. Environment: Windows NT PostScript driver. Revision History: 02/16/98 -ksuzuki- Added OCF font support. 09/08/97 -ksuzuki- Added code to look for PSFAMILY.DAT file from the directory where makentf is invoked. 09/16/96 -PPeng- Add the fucntion to write PS Encoding vectors out - for debugging and create PS Encoding Arrays as PScript resource files. 09/16/96 -slam- Created. mm/dd/yy -author- description --*/ #include #include "lib.h" #include "ppd.h" #include "pslib.h" #include "afm2ntm.h" #include "cjkfonts.h" #include "writentf.h" // // Globals // HINSTANCE ghInstance; PUPSCODEPT UnicodetoPs; PTBL pFamilyTbl; PSTR pAFMCharacterSetString; PSTR Adobe_Japan1_0 = "Adobe-Japan1-0\n"; DWORD dwLastErr; PSTR pAFMFileName = NULL; BOOL bVerbose = FALSE; BOOL bOptimize = FALSE; // Number of auxiliary character set. Its cheif // purpose is to support 83pv. #define NUM_AUX_CS 1 // This macro is used to see whether the argument // matches the differential between CS_SHIFTJIS // and CS_WEST_MAX. #define IS_CS_SHIFTJIS(delta) \ ((delta) == (CS_SHIFTJIS - CS_WEST_MAX)) // // Prototype // BOOL WritePSEncodings( IN PWSTR pwszFileName, IN WINCPTOPS *CPtoPSList, IN DWORD dwPages ); BOOL NeedBuildMoreNTM( PBYTE pAFM ); void __cdecl main( int argc, char **argv ) /*++ Routine Description: Makentf takes four steps to create a .NTF file. Step 1: Initialization. Step 2: Convert AFM(s) to NTM(s). Step 3: Write GLYPHSETDATA(s) and NTM(s) to a .NTF file. Step 4: Clean up. Arguments: argc - The path of and arguments given to this program. argv - The number of elements pointed to by argc. Return Value: None. --*/ { WCHAR wstrNTFFile[MAX_PATH]; WCHAR wstrAFMFile[MAX_PATH]; WCHAR wstrDATFile[MAX_PATH]; WCHAR DatFilePath[MAX_PATH]; PNTM *aPNTM; PNTM pNTM; PGLYPHSETDATA *aGlyphSets; PWINCODEPAGE *aWinCodePages; PWINCODEPAGE pAllWinCodePages[CS_MAX]; PUPSCODEPT pFontChars; CHSETSUPPORT flCsupFont, flCsupGlyphSet, flCsupMatch, flCsupAll; ULONG cNumNTM, cSizeNTM, ulLength, nUnicodeChars; PULONG *aUniPsTbl; LONG lMatch, lMatchAll; PBYTE pAFM; FLONG flCurCset, flLastCset; ULONG cNumGlyphSets, cSizeGlyphSets; DWORD ulFileSize; PBYTE pFamDatFile; PBYTE pCMaps[CMAPS_PER_COL]; HANDLE hmodule, hModCMaps[CMAPS_PER_COL]; USHORT cNTMCurFont; INT nArgcOffset; LONG c; ULONG i, j; BOOL bIs90mspFont; BOOL bIsKSCmsHWFont; ////////////////////////////////////////////////////////////////////////// // // Step 1: Initialization. // ////////////////////////////////////////////////////////////////////////// // // Check if there are enough parameters. // if (argc == 1) { printf("MakeNTF usage:\n"); printf("1. MakeNTF [-v] [-o] \n"); printf(" Create an NTF file from AFM files.\n"); printf(" -v: verbose (print various info)\n"); printf(" -o: optimize (write glyphset only referenced)\n"); printf("\n"); printf("2. MakeNTF \n"); printf(" Generate PS encoding name list.\n"); return; } wstrNTFFile[0] = 0; if (argc == 2) { ulLength = strlen(argv[1]) + 1; MULTIBYTETOUNICODE(wstrNTFFile, ulLength*sizeof(WCHAR), NULL, argv[1], ulLength); WritePSEncodings(wstrNTFFile, &aPStoCP[0], CS_MAX); return; } else { nArgcOffset = 0; for (i = 1; i <= 2; i++) { if (!strcmp(argv[i], "-v")) { bVerbose = TRUE; nArgcOffset++; } if (!strcmp(argv[i], "-o")) { bOptimize = TRUE; nArgcOffset++; } } } if (bVerbose) printf("%%%%[Begin MakeNTF]%%%%\n\n"); // // Initiliaze variables that relate to memory allocation. // aPNTM = NULL; aGlyphSets = NULL; pFamilyTbl = NULL; UnicodetoPs = NULL; aUniPsTbl = NULL; aWinCodePages = NULL; cNumNTM = cSizeNTM = 0; cNumGlyphSets = cSizeGlyphSets = 0; // // Initialize Glyphset counter, list of all possible Windows charsets. // for (i =0; i < CS_MAX; i++) { pAllWinCodePages[i] = &aStdCPList[i]; } // // Create a copy of the Unicode->PS char mapping table and sort it // in Unicode point order. // if ((UnicodetoPs = (PUPSCODEPT) MemAllocZ((size_t) sizeof(UPSCODEPT) * NUM_PS_CHARS)) == NULL) { dwLastErr = GetLastError(); ERR(("makentf - main: malloc for UnicodetoPs (%ld)\n", dwLastErr)); return; } memcpy(UnicodetoPs, PstoUnicode, (size_t) sizeof(UPSCODEPT) * NUM_PS_CHARS); qsort(UnicodetoPs, (size_t) NUM_PS_CHARS, (size_t) sizeof(UPSCODEPT), CmpUniCodePts); // // Build complete path name for PS family DAT file. // GetCurrentDirectory(MAX_PATH, DatFilePath); StringCchCatW(DatFilePath, CCHOF(DatFilePath), DatFileName); // // Open PS font family .DAT file and build the font family table. // if (!(hmodule = MapFileIntoMemory(DatFilePath, &pFamDatFile, &ulFileSize))) { // // One more try: look for it from the directory where makentf is // invoked (or from the root directory). // DECLSPEC_IMPORT LPWSTR* APIENTRY CommandLineToArgvW(LPCWSTR, int*); LPWSTR p, pLast, *pCmdLine; int nArgc; pCmdLine = CommandLineToArgvW(GetCommandLineW(), &nArgc); if (pCmdLine == NULL) { dwLastErr = GetLastError(); ERR(("makentf - main: CommandLineToArgvW (%ld)\n", dwLastErr)); UnmapFileFromMemory(hmodule); goto CLEAN_UP; } StringCchCopyW(DatFilePath, CCHOF(DatFilePath), pCmdLine[0]); GlobalFree(pCmdLine); p = pLast = DatFilePath; while ((p = wcsstr(p, L"\\")) != NULL) { pLast = p; p += 2; } StringCchCopyW(pLast, CCHOF(DatFilePath) - (pLast - DatFilePath), DatFileName); hmodule = MapFileIntoMemory(DatFilePath, &pFamDatFile, &ulFileSize); if (!hmodule) { dwLastErr = GetLastError(); ERR(("makentf - main: can't open PSFAMILY.DAT file (%ld)\n", dwLastErr)); UnmapFileFromMemory(hmodule); goto CLEAN_UP; } } BuildPSFamilyTable(pFamDatFile, &pFamilyTbl, ulFileSize); UnmapFileFromMemory(hmodule); // // Allocate memory to store NTM pointers. // // We quadruple the number of the arguments of this program to get the // number of NTM pointer. This is because // // 1) we need four NTM pointers maximum (two for H and V plus two for J // 90ms and 83pv) for a CJK AFM, but, // 2) we don't know at this time that how many of CJK AFMs we are going // to process. // // Since we're only allocating pointers here it's usually OK to quadruple // the number of the arguments and use it as the number of NTM pointers // we need. (Don't forget to subtract two - one for the name of this // program and the other for the target NTM file name - from the number // of the arguments prior to quadruple.) // // Add 90msp-RKSJ support. we need 2 more NTFs - H and V for 90msp. // So I change the estimation number from 4 to 6. Jack 3/15/2000 // aPNTM = MemAllocZ(((argc - 2 - nArgcOffset) * 4) * sizeof(PNTM)); aPNTM = MemAllocZ(((argc - 2 - nArgcOffset) * 6) * sizeof(PNTM)); if (aPNTM == NULL) { dwLastErr = GetLastError(); ERR(("makentf - main: malloc for aPNTM (%ld)\n", dwLastErr)); goto CLEAN_UP; } // // Allocate memory to store pointers to Glyphset related data. We don't // know how many Glyphsets we will need - but we know it will be at most // equal to the number of character sets we support, although this will // probably never occur. Since we're only allocating ptrs here we'll go // ahead and alloc the max. Don't forget an extra entry for the Unicode // GLYPHSET data. // i = CS_WEST_MAX + (CS_MAX - CS_WEST_MAX + NUM_AUX_CS) * 2; if ((aGlyphSets = MemAllocZ(i * sizeof(PGLYPHSETDATA))) == NULL) { dwLastErr = GetLastError(); ERR(("makentf - main: malloc for aGlyphSets (%ld)\n", dwLastErr)); goto CLEAN_UP; } if ((aUniPsTbl = MemAllocZ(i * sizeof(PULONG))) == NULL) { dwLastErr = GetLastError(); ERR(("makentf - main: malloc for aUniPsTbl (%ld)\n", dwLastErr)); goto CLEAN_UP; } if ((aWinCodePages = MemAllocZ(i * sizeof(PWINCODEPAGE))) == NULL) { dwLastErr = GetLastError(); ERR(("makentf - main: malloc for aWinCodePages (%ld)\n", dwLastErr)); goto CLEAN_UP; } // // Precreate Western GLYPHSETs. // Note that this for loop assumes that the enum numbers from CS_228 to // CS_WEST_MAX are in ascending order incrementally. // if (bVerbose && !bOptimize) printf("%%%%[Begin Precreate Western Glyphsets]%%%%\n\n"); for (i = CS_228; i < CS_WEST_MAX; i++, cNumGlyphSets++) { aWinCodePages[cNumGlyphSets] = &aStdCPList[i]; CreateGlyphSets(&aGlyphSets[cNumGlyphSets], aWinCodePages[cNumGlyphSets], &aUniPsTbl[cNumGlyphSets]); cSizeGlyphSets += aGlyphSets[cNumGlyphSets]->dwSize; } if (bVerbose && !bOptimize) printf("%%%%[End Precreate Western Glyphsets]%%%%\n\n"); ////////////////////////////////////////////////////////////////////////// // // Step 2: Convert AFM(s) to NTM(s). // ////////////////////////////////////////////////////////////////////////// if (bVerbose) printf("%%%%[Begin Covert AFM to NTM]%%%%\n\n"); for (i = 2 + nArgcOffset; i < (ULONG)argc; i++) { // // Get AFM filename. // ulLength = strlen(argv[i]) + 1; MULTIBYTETOUNICODE(wstrAFMFile, ulLength*sizeof(WCHAR), NULL, argv[i], ulLength); // // Map AFM file into memory. // if (!(hmodule = MapFileIntoMemory(wstrAFMFile, &pAFM, NULL))) { dwLastErr = GetLastError(); ERR(("makentf - main: MapFileIntoMemory (%ld)\n", dwLastErr)); goto CLEAN_UP; } pAFMFileName = argv[i]; bIs90mspFont = FALSE; bIsKSCmsHWFont = FALSE; // // Initialization of pAFMCharacterSet must be done here // *before* CREATE_OCF_DATA_FROM_CID_DATA tag. The cheif // purpose of the initialization here is to support // OCF/83pv font. // pAFMCharacterSetString = FindAFMToken(pAFM, PS_CHARSET_TOK); CREATE_OCF_DATA_FROM_CID_DATA: // // Determine which charsets this font supports. To find that, // we use the following variables. // // flCsupFont: Combination of charset of the target font // flCsupGlyphSet: Charset of the target font's glyphset // lMatch: Index corresponding to CHSETSUPPORT, or -1 // flCsupMatch: Combination of charset of a closest font, or 0 // flCsupFont = GetAFMCharSetSupport(pAFM, &flCsupGlyphSet); CREATE_90MSP_RKSJ_NTM: CREATE_KSCMS_HW_NTM: lMatch = -1; flCsupMatch = 0; if (flCsupGlyphSet == CS_NOCHARSET) { // // Determine if the current font matches any of the codepages // we have created so far. // lMatch = FindClosestCodePage(aWinCodePages, cNumGlyphSets, flCsupFont, &flCsupMatch); } else { if (flCsupGlyphSet == CS_228) lMatch = 0; else if (flCsupGlyphSet == CS_314) lMatch = 1; flCsupMatch = flCsupFont; } if ((flCsupGlyphSet == CS_NOCHARSET) && ((lMatch == -1) || ((flCsupMatch & flCsupFont) != flCsupFont))) { // // Either: // We haven't created a charset which could be used to represent // this font so far. // -or- // We know this font supports at least 1 of the charsets we have // created, but there might be a better match in the list of all // possible charsets. // lMatchAll = FindClosestCodePage(pAllWinCodePages, CS_MAX, flCsupFont, &flCsupAll); if ((flCsupAll == flCsupFont) || (flCsupAll & flCsupFont) > (flCsupMatch & flCsupFont)) { // // Found a better match in a codepage which has not yet // been created. // lMatch = lMatchAll; // // Create a GLYPHSETDATA struct for this codepage and add // it to the list of those we've created so far. // aWinCodePages[cNumGlyphSets] = &aStdCPList[lMatch]; // // Determine if this is a CJK font. // if (lMatch < CS_WEST_MAX) { // // Western font. // CreateGlyphSets(&aGlyphSets[cNumGlyphSets], aWinCodePages[cNumGlyphSets], &aUniPsTbl[cNumGlyphSets]); cSizeGlyphSets += aGlyphSets[cNumGlyphSets]->dwSize; // // Glyphset for this font is the one we just created. // lMatch = cNumGlyphSets; cNumGlyphSets += 1; } else { // // CJK font. // // Map the CMap files on memory first. // j = (ULONG)lMatch - CS_WEST_MAX; for (c = 0; c < CMAPS_PER_COL; c++) { hModCMaps[c] = MapFileIntoMemory(CjkFnameTbl[j][c], &pCMaps[c], NULL); if (hModCMaps[c] == NULL) { while (--c >= 0) { UnmapFileFromMemory(hModCMaps[c]); } dwLastErr = GetLastError(); ERR(("makentf - main: MapFileIntoMemory (%ld)\n", dwLastErr)); goto CLEAN_UP; } } // // Since we're creating 2 GLYPHSETs (H and V variants) // Create 2 codepage entries which point to the same // Win codepage. // aWinCodePages[cNumGlyphSets + 1] = &aStdCPList[lMatch]; // // Use the CMap files to create the new GLYPHSETs. // CreateCJKGlyphSets(&pCMaps[0], &pCMaps[2], &aGlyphSets[cNumGlyphSets], aWinCodePages[cNumGlyphSets], &aUniPsTbl[cNumGlyphSets]); // // Unmap the CMap files. // for (c = 0; c < CMAPS_PER_COL; c++) { UnmapFileFromMemory(hModCMaps[c]); } // // We've created both an H and V GLYPHSET. // cSizeGlyphSets += aGlyphSets[cNumGlyphSets]->dwSize; cSizeGlyphSets += aGlyphSets[cNumGlyphSets + 1]->dwSize; // // Glyphsets for this font are the ones we just created. // lMatch = cNumGlyphSets; cNumGlyphSets += 2; } } } // // Determine number of NTMs to be created for this font. // cNTMCurFont = (aWinCodePages[lMatch]->pCsetList[0] < CS_WEST_MAX) ? 1 : 2; do { // // Generate NTM from AFM. // aPNTM[cNumNTM] = AFMToNTM(pAFM, aGlyphSets[lMatch], aUniPsTbl[lMatch], ((flCsupGlyphSet != CS_NOCHARSET) ? &flCsupFont : NULL), ((flCsupFont & CS_CJK) ? TRUE : FALSE), bIs90mspFont | bIsKSCmsHWFont); if (aPNTM[cNumNTM] != NULL) { // // Put the NTMs into a data array for WriteNTF. // cSizeNTM += NTM_GET_SIZE(aPNTM[cNumNTM]); cNumNTM++; } else { ERR(("makentf - main: AFMToNTM failed to create NTM:%s\n", argv[i])); } cNTMCurFont--; lMatch++; } while (cNTMCurFont); // // 90msp font support. jjia 3/16/2000 // if (flCsupFont == CSUP(CS_SHIFTJIS)) { if (NeedBuildMoreNTM(pAFM)) { flCsupFont = CSUP(CS_SHIFTJISP); bIs90mspFont = TRUE; goto CREATE_90MSP_RKSJ_NTM; // here we go again! } } bIs90mspFont = FALSE; if (flCsupFont == CSUP(CS_HANGEUL)) { if (NeedBuildMoreNTM(pAFM)) { flCsupFont = CSUP(CS_HANGEULHW); bIsKSCmsHWFont = TRUE; goto CREATE_KSCMS_HW_NTM; // here we go again! } } bIsKSCmsHWFont = FALSE; // // OCF/83pv font support. Create OCF glyphset and NTM data from // CID AFM file. // if ((flCsupFont == CSUP(CS_SHIFTJIS)) || (flCsupFont == CSUP(CS_SHIFTJISP))) { pAFMCharacterSetString = Adobe_Japan1_0; goto CREATE_OCF_DATA_FROM_CID_DATA; // here we go again! } UnmapFileFromMemory(hmodule); } if (bVerbose) printf("%%%%[End Convert AFM to NTM]%%%%\n\n"); // // Create Unicode GLYPHSET. This glyphset is created here since we don't // want any NTMs to reference this glyphset. // if (bVerbose && !bOptimize) printf("%%%%[Begin Create Unicode glyphset]%%%%\n\n"); CreateGlyphSets(&aGlyphSets[cNumGlyphSets], &UnicodePage, &aUniPsTbl[cNumGlyphSets]); cSizeGlyphSets += aGlyphSets[cNumGlyphSets]->dwSize; cNumGlyphSets++; if (bVerbose && !bOptimize) printf("%%%%[End Create Unicode glyphset]%%%%\n\n"); ////////////////////////////////////////////////////////////////////////// // // Step 3: Write GLYPHSETDATA(s) and NTM(s) to a .NTF file. // ////////////////////////////////////////////////////////////////////////// if (bVerbose) printf("%%%%[Begin Write NTF]%%%%\n\n"); ulLength = strlen(argv[1 + nArgcOffset]) + 1; MULTIBYTETOUNICODE( wstrNTFFile, ulLength*sizeof(WCHAR), NULL, argv[1 + nArgcOffset], ulLength); if (!WriteNTF(wstrNTFFile, cNumGlyphSets, cSizeGlyphSets, aGlyphSets, cNumNTM, cSizeNTM, aPNTM )) { ERR(("makentf: main - Can't write .NTF file\n")); } if (bVerbose) printf("%%%%[End Write NTF]%%%%\n\n"); ////////////////////////////////////////////////////////////////////////// // // Step 4: Clean up. // ////////////////////////////////////////////////////////////////////////// CLEAN_UP: for (i = 0; i < cNumNTM; i++) { MemFree(aPNTM[i]); } for (i = 0; i < cNumGlyphSets; i++) { MemFree(aGlyphSets[i]); if (aUniPsTbl[i] != NULL) { // // Could have a null ptr if this is a Pi Font. // MemFree(aUniPsTbl[i]); } } MemFree(aPNTM ? aPNTM : NULL); MemFree(aGlyphSets ? aGlyphSets : NULL); MemFree(pFamilyTbl ? pFamilyTbl : NULL); MemFree(UnicodetoPs ? UnicodetoPs : NULL); MemFree(aUniPsTbl ? aUniPsTbl : NULL); MemFree(aWinCodePages ? aWinCodePages : NULL); if (bVerbose) printf("%%%%[End MakeNTF]%%%%\n\n"); } // // Formating functions - copied from PScript\Output.c // INT OPVsprintf( OUT LPSTR buf, IN LPCSTR fmtstr, IN va_list arglist ) /*++ Routine Description: Takes a pointer to an argument list, then formats and writes the given data to the memory pointed to by buffer. Arguments: buf Storage location for output fmtstr Format specification arglist Pointer to list of arguments Return Value: Return the number of characters written, not including the terminating null character, or a negative value if an output error occurs. [Note:] This is NOT a full implementation of "vsprintf" as found in the C runtime library. Specifically, the only form of format specification allowed is %type, where "type" can be one of the following characters: d INT signed decimal integer l LONG signed decimal integer u ULONG unsigned decimal integer s CHAR* character string c CHAR character x,X DWORD hex number (emits at least two digits, uppercase) b BOOL boolean (true or false) f LONG 24.8 fixed-pointed number o CHAR octal number --*/ { LPSTR ptr = buf; ASSERT(buf && fmtstr); while (*fmtstr != NUL) { if (*fmtstr != '%') { // Normal character *ptr++ = *fmtstr++; } else { // Format specification switch (*++fmtstr) { case 'd': // signed decimal integer _ltoa((LONG) va_arg(arglist, INT), ptr, 10); ptr += strlen(ptr); break; case 'l': // signed decimal integer _ltoa(va_arg(arglist, LONG), ptr, 10); ptr += strlen(ptr); break; case 'u': // unsigned decimal integer _ultoa(va_arg(arglist, ULONG), ptr, 10); ptr += strlen(ptr); break; case 's': // character string { LPSTR s = va_arg(arglist, LPSTR); while (*s) *ptr++ = *s++; } break; case 'c': // character *ptr++ = va_arg(arglist, CHAR); break; case 'x': case 'X': // hexdecimal number { ULONG ul = va_arg(arglist, ULONG); INT ndigits = 8; while (ndigits > 2 && ((ul >> (ndigits-1)*4) & 0xf) == 0) ndigits--; while (ndigits-- > 0) *ptr++ = HexDigit(ul >> ndigits*4); } break; case 'o': { CHAR ch = va_arg(arglist, CHAR); *ptr++ = (char)((ch & 0xC0) >> 6) + (char)'0'; *ptr++ = (char)((ch & 0x38) >> 3) + (char)'0'; *ptr++ = (char)(ch & 0x07) + (char)'0'; } break; case 'b': // boolean StringCchCopyA(ptr, (size_t)((ptr - buf)/sizeof(CHAR)), (va_arg(arglist, BOOL)) ? "true" : "false"); ptr += strlen(ptr); break; case 'f': // 24.8 fixed-pointed number { LONG l = va_arg(arglist, LONG); ULONG ul, scale; // sign character if (l < 0) { *ptr++ = '-'; ul = -l; } else ul = l; // integer portion _ultoa(ul >> 8, ptr, 10); ptr += strlen(ptr); // fraction ul &= 0xff; if (ul != 0) { // We output a maximum of 3 digits after the // decimal point, but we'll compute to the 5th // decimal point and round it to 3rd. ul = ((ul*100000 >> 8) + 50) / 100; scale = 100; *ptr++ = '.'; do { *ptr++ = (CHAR) (ul/scale + '0'); ul %= scale; scale /= 10; } while (scale != 0 && ul != 0) ; } } break; default: if (*fmtstr != NUL) *ptr++ = *fmtstr; else { ERR(("Invalid format specification\n")); fmtstr--; } break; } // Skip the type characterr fmtstr++; } } *ptr = NUL; return (INT)(ptr - buf); } INT OPSprintf( OUT LPSTR buf, IN LPCSTR fmtstr, IN ... ) { va_list arglist; INT iRc; va_start(arglist, fmtstr); iRc = OPVsprintf(buf, fmtstr, arglist); va_end(arglist); return iRc; } int __cdecl compareWinCpt(const void *elem1, const void *elem2) { PWINCPT p1; PWINCPT p2; p1 = (PWINCPT)elem1; p2 = (PWINCPT)elem2; if (p1->usWinCpt == p2->usWinCpt) return(0); else if (p1->usWinCpt < p2->usWinCpt) return(-1); else return(1); } VOID SortWinCPT( IN OUT WINCPT *pSortedWinCpts, IN WINCPTOPS *pCPtoPS ) { // pSortedWinCpts must point to a buffer big enough sizeof(WINCPT)* MAX_CSET_CHARS) memcpy(pSortedWinCpts, &(pCPtoPS->aWinCpts), sizeof(WINCPT)* MAX_CSET_CHARS); qsort(pSortedWinCpts, pCPtoPS->ulChCnt, sizeof(WINCPT), compareWinCpt); } // // This function reads a list of CP to PS Name tables and writes an Text file // with the corresponding PostScript Encoding arrays // Need to run this whenever we changed the Mapping tables // // Format: // 10 20 30 40 // 1234567890123456789012345678901234567890 // CodePage = dddd (name) // /name_up_to_32 % XX // BOOL WritePSEncodings( IN PWSTR pwszFileName, IN WINCPTOPS *CPtoPSList, IN DWORD dwPages ) { HANDLE hFile; ULONG i, j, k, l; WINCPTOPS *pCPtoPS; WINCPT sortedWinCpts[MAX_CSET_CHARS]; // maxiaml 255 chars char buffer[256]; DWORD dwLen, ulByteWritten; hFile = CreateFile(pwszFileName, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) { ERR(("WritePSEncodings:CreateFile\n")); return(FALSE); } for (i = 0; i < dwPages; i++) { pCPtoPS = CPtoPSList + i; dwLen = OPSprintf(buffer, "\n\n CodePage = %d (%s)\n", pCPtoPS->usACP, pCPtoPS->pGSName); if (!WriteFile(hFile, buffer, dwLen, (LPDWORD)&ulByteWritten, (LPOVERLAPPED)NULL) || ulByteWritten != dwLen) { ERR(("WritePSEncodings:WriteFile\n")); CloseHandle(hFile); return(FALSE); } SortWinCPT(&(sortedWinCpts[0]), pCPtoPS); k = sortedWinCpts[0].usWinCpt; for (j = 0; j < pCPtoPS->ulChCnt; j++, k++) { while (k < sortedWinCpts[j].usWinCpt) { dwLen = OPSprintf(buffer, " %% %X\n", k); if (!WriteFile(hFile, buffer, dwLen, (LPDWORD)&ulByteWritten, (LPOVERLAPPED)NULL) || ulByteWritten != dwLen) { ERR(("WritePSEncodings:WriteFile\n")); CloseHandle(hFile); return(FALSE); } k++; } dwLen = OPSprintf(buffer, " %% %X\n", sortedWinCpts[j].usWinCpt); strncpy(buffer, "/", 1); l = strlen(sortedWinCpts[j].pPsName); strncpy(buffer + 1, sortedWinCpts[j].pPsName, l); if (!WriteFile(hFile, buffer, dwLen, (LPDWORD)&ulByteWritten, (LPOVERLAPPED)NULL) || ulByteWritten != dwLen) { ERR(("WritePSEncodings:WriteFile\n")); CloseHandle(hFile); return(FALSE); } } } CloseHandle(hFile); return(TRUE); } // // This causes the error message to show up in your command window // instead of the kernel debugger window. // ULONG _cdecl DbgPrint( PCSTR pstrFormat, ... ) { va_list ap; va_start(ap, pstrFormat); vprintf(pstrFormat, ap); va_end(ap); return 0; } VOID DbgBreakPoint( VOID ) { exit(-1); } BOOL NeedBuildMoreNTM( PBYTE pAFM ) { PPSFAMILYINFO pFamilyInfo; PSZ pszFontName; pFamilyInfo = NULL; pszFontName = FindAFMToken(pAFM, PS_FONT_NAME_TOK); if (NULL ==pszFontName) return FALSE; pFamilyInfo = (PPSFAMILYINFO) bsearch(pszFontName, (PBYTE) (((PPSFAMILYINFO) (pFamilyTbl->pTbl))[0].pFontName), pFamilyTbl->usNumEntries, sizeof(PSFAMILYINFO), StrCmp); if (pFamilyInfo) { if (pFamilyInfo->usPitch != DEFAULT_PITCH) return TRUE; if (pFamilyInfo > ((PPSFAMILYINFO) (pFamilyTbl->pTbl))) { pFamilyInfo = pFamilyInfo - 1; if (!StrCmp(pFamilyInfo->pFontName, pszFontName) && (pFamilyInfo->usPitch != DEFAULT_PITCH)) return TRUE; } pFamilyInfo = pFamilyInfo + 1; if (pFamilyInfo < (((PPSFAMILYINFO) (pFamilyTbl->pTbl)) + pFamilyTbl->usNumEntries)) { pFamilyInfo = pFamilyInfo + 1; if (!StrCmp(pFamilyInfo->pFontName, pszFontName) && (pFamilyInfo->usPitch != DEFAULT_PITCH)) return TRUE; } } return FALSE; }