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.

1287 lines
43 KiB

  1. /****************************************************************************
  2. * *
  3. * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY *
  4. * KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE *
  5. * IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR *
  6. * PURPOSE. *
  7. * *
  8. * Copyright (C) 1993-95 Microsoft Corporation. All Rights Reserved. *
  9. * *
  10. ****************************************************************************/
  11. //-----------------------------------------------------------------------------
  12. // This files contains the module name for this mini driver. Each mini driver
  13. // must have a unique module name. The module name is used to obtain the
  14. // module handle of this Mini Driver. The module handle is used by the
  15. // generic library to load in tables from the Mini Driver.
  16. // It also contains Install() for upgrading 3.0 driver to 3.1.
  17. //
  18. //-----------------------------------------------------------------------------
  19. #include "strings.h"
  20. char *rgchModuleName = "JP3500P";
  21. char szNone[]="";
  22. // The following are defined to ensure that we upgrade correctly from the
  23. // HPPCL5a, HPPCL5e and Win 3.11 HPPCL5MS drivers
  24. #define MAX_LJ4_MBMEMSETTING 68 // from HP tech specification
  25. #define KB_THRESHOLD 200 // kb range check,needed for conversion
  26. #define PRINTDRIVER
  27. #include <print.h>
  28. #include "gdidefs.inc"
  29. #include "mdevice.h"
  30. #include "unidrv.h"
  31. #include "minidriv.h"
  32. #ifndef _INC_WINDOWSX
  33. #include <windowsx.h>
  34. #endif
  35. #define MB_SETFOREGROUND 0x00010000
  36. #if (WINVER >= 0x0400)
  37. typedef void (CALLBACK *MSGBOXCALLBACK)(LPHELPINFO lpHelpInfo);
  38. typedef struct tagMSGBOXPARAMS
  39. {
  40. DWORD cbSize;
  41. #ifdef tagWND
  42. HWND_16 hwndOwner;
  43. #else
  44. HWND hwndOwner;
  45. #endif
  46. HINSTANCE hInstance;
  47. LPCSTR lpszText;
  48. LPCSTR lpszCaption;
  49. DWORD dwStyle;
  50. LPCSTR lpszIcon;
  51. DWORD dwContextHelpId;
  52. MSGBOXCALLBACK lpfnMsgBoxCallback;
  53. DWORD dwLanguageId;
  54. } MSGBOXPARAMS, FAR *LPMSGBOXPARAMS;
  55. int WINAPI MessageBoxIndirect(LPMSGBOXPARAMS);
  56. #endif /* WINVER >=0x0400 */
  57. short NEAR PASCAL MakeAppName(LPSTR,LPCSTR,short);
  58. // typedef for atom stuff--what a nuisance!
  59. typedef struct tagSFNODE
  60. {
  61. WORD wIndex;
  62. ATOM atom;
  63. } SFNODE, FAR *LPSFNODE;
  64. // Typedef for Font Installer procedure
  65. typedef int (FAR * PASCAL SOFTFONTPROC)(HWND,LPSTR,LPSTR,BOOL,int,int);
  66. HINSTANCE hInst;
  67. #define DEFAULT_INT 32767
  68. #define SOFT_FONT_THRES 25 // build font summary, if over this limit
  69. #define MAX_CART_INDEX 12
  70. #define TMPSIZE 256
  71. // Define these so they happily use the same values as the HPPCL5E driver.
  72. #define GS_PHOTO 0
  73. #define GS_LINEART 1
  74. #define GS_SCANJET 2
  75. // map old HPPCL5a's cartindex to unidrv's FONTCART index for newer cartridges.
  76. // This mapping table is created based on the old HPPCL5a .rc file.
  77. // Note that we do not have "International Collection" cartridge and we
  78. // map it to index 0 (arbitrarily).
  79. int rgNewCartMap[12] = {0, 8, 7, 2, 3, 0, 5, 6, 1, 4, 9, 10};
  80. // String to determine if we have a member of the LaserJet 4 family
  81. char szLJ4[]="HP LaserJet 4";
  82. // Stuff needed for mapping old facenames to new versions
  83. #ifndef NOFONTMAP
  84. typedef struct tagFACEMAP
  85. {
  86. char szOldFace[LF_FACESIZE];
  87. char szNewFace[LF_FACESIZE];
  88. } FACEMAP, NEAR * NPFACEMAP;
  89. typedef struct tagFACEINDEX
  90. {
  91. BYTE cFirstChar;
  92. BYTE bIndex;
  93. } FACEINDEX, NEAR * NPFACEINDEX;
  94. FACEMAP FaceMap[]={{"Albertus (W\x01)", "Albertus Medium"},
  95. {"Albertus Xb (W\x01)", "Albertus Extra Bold"},
  96. {"Antique Olv (W\x01)", "Antique Olive"},
  97. {"Antique Olv Cmpct (W\x01)","Antique Olive Compact"},
  98. {"CG Bodoni (W\x01)", "CG Bodoni"},
  99. {"CG Cent Schl (W\x01)", "CG Century Schoolbook"},
  100. {"CG Omega (W\x01)", "CG Omega"},
  101. {"CG Palacio (W\x01)", "CG Palacio"},
  102. {"CG Times (W\x01)", "CG Times"},
  103. {"Clarendon Cd (W\x01)", "Clarendon Condensed"},
  104. {"Cooper Blk (W\x01)", "Cooper Black"},
  105. {"Coronet (W\x01)", "Coronet"},
  106. {"Courier (W\x01)", "Courier"},
  107. {"Garmond (W\x01)", "Garamond"},
  108. {"ITC Benguat (W\x01)", "ITC Benguiat"},
  109. {"ITC Bookman Db (W\x01)", "ITC Bookman Demi"},
  110. {"ITC Bookman Lt (W\x01)", "ITC Bookman Light"},
  111. {"ITC Souvenir Db (W\x01)", "ITC Souvenir Demi"},
  112. {"ITC Souvenir Lt (W\x01)", "ITC Souvenir Light"},
  113. {"Letter Gothic (W\x01)", "Letter Gothic"},
  114. {"Marigold (W\x01)", "Marigold"},
  115. {"Revue Lt (W\x01)", "Revue Light"},
  116. {"Shannon (W\x01)", "Shannon"},
  117. {"Shannon Xb (W\x01)", "Shannon Extra Bold"},
  118. {"Stymie (W\x01)", "Stymie"},
  119. {"Univers (W\x01)", "Univers"},
  120. {"Univers Cd (W\x01)", "Univers Condensed"}};
  121. FACEINDEX FaceIndex[]={{'A',0},
  122. {'C',4},
  123. {'G',13},
  124. {'I',14},
  125. {'L',19},
  126. {'M',20},
  127. {'R',21},
  128. {'S',22},
  129. {'U',25},
  130. {(BYTE)'\xFF',27}}; // Provide an upper limit
  131. // to the search for 'U'.
  132. #endif
  133. //------------------------------------------------------------------------
  134. // Function: LibMain(hInstance,wDataSeg,cbHeapSize,lpszCmdLine)
  135. //
  136. // Action: Save the hInstance for this DLL
  137. //
  138. // Return: 1
  139. //------------------------------------------------------------------------
  140. int WINAPI LibMain (HANDLE hInstance,
  141. WORD wDataSeg,
  142. WORD cbHeapSize,
  143. LPSTR lpszCmdLine)
  144. {
  145. hInst=hInstance;
  146. return 1;
  147. }
  148. //--------------------------*MakeAppName*---------------------------------------
  149. // Action: compose the <printer,port> name for reading the profile data
  150. // Return the length of the actual application name. Return -1 if fails.
  151. //
  152. //------------------------------------------------------------------------------
  153. short NEAR PASCAL MakeAppName(LPSTR lpAppName,
  154. LPCSTR lpPortName,
  155. short max)
  156. {
  157. short length, count;
  158. LPCSTR lpTmp;
  159. LPCSTR lpLastColon = NULL;
  160. length = lstrlen(lpAppName);
  161. if (!lpPortName)
  162. return length;
  163. if (length == 0 || length > max - lstrlen(lpPortName))
  164. return -1;
  165. // insert the comma
  166. lpAppName[length++] = ',';
  167. // append the port name but do not want the last ':', if any.
  168. for (lpTmp = lpPortName ; *lpTmp; lpTmp++)
  169. if (*lpTmp == ':')
  170. lpLastColon = lpTmp;
  171. if (lpLastColon && lpLastColon == lpTmp - 1)
  172. count = lpLastColon - lpPortName;
  173. else
  174. count = lpTmp - lpPortName;
  175. lstrcpy((LPSTR)&lpAppName[length], lpPortName);
  176. length += count;
  177. lpAppName[length]='\0';
  178. return length;
  179. }
  180. #define KEY_BUF_SIZE 256
  181. //---------------------------------------------------------------------------
  182. // Function: GetInt(lpSection,lpKey,lpnValue,nDefault,bRemove)
  183. //
  184. // Action: Load the appropriate string from the resources, then get the
  185. // specified integer from the section. Remove the old entry if
  186. // it exists and it bRemove is TRUE.
  187. //
  188. // Return: TRUE if we actually found a value, FALSE if not.
  189. //---------------------------------------------------------------------------
  190. BOOL NEAR PASCAL GetInt(LPSTR lpSection,
  191. LPCSTR lpKey,
  192. LPINT lpnValue,
  193. int nDefault,
  194. BOOL bRemove)
  195. {
  196. char szKeyName[60];
  197. int nTest;
  198. if(!HIWORD(lpKey))
  199. {
  200. if(LoadString(hInst,LOWORD(lpKey),szKeyName,sizeof(szKeyName)))
  201. lpKey=szKeyName;
  202. else
  203. return FALSE;
  204. }
  205. nTest=GetProfileInt(lpSection,szKeyName,DEFAULT_INT);
  206. if(DEFAULT_INT != nTest)
  207. {
  208. *lpnValue=nTest;
  209. if(bRemove)
  210. WriteProfileString(lpSection,szKeyName,NULL);
  211. return TRUE;
  212. }
  213. // Section doesn't exist--use default
  214. *lpnValue=nDefault;
  215. return FALSE;
  216. }
  217. //-------------------------------------------------------------------------
  218. // Function: WriteInt(lpSection,lpKey,nValue)
  219. //
  220. // Action: Write an integer value to the specified section of win.ini.
  221. //
  222. // Return: TRUE if successful, FALSE if not.
  223. //-------------------------------------------------------------------------
  224. BOOL NEAR PASCAL WriteInt(LPSTR lpSection,
  225. LPCSTR lpKey,
  226. int nValue)
  227. {
  228. char szKeyName[60];
  229. char szValue[10];
  230. if(!HIWORD(lpKey))
  231. {
  232. if(LoadString(hInst,LOWORD(lpKey),szKeyName,sizeof(szKeyName)))
  233. lpKey=szKeyName;
  234. else
  235. return FALSE;
  236. }
  237. wsprintf(szValue,"%u",nValue);
  238. return WriteProfileString(lpSection,szKeyName,szValue);
  239. }
  240. //---------------------------*MergeFontLists*-----------------------------
  241. // Action: Merge the old and new soft fonts. In most cases when we get
  242. // called, we really don't do much of anything, because the
  243. // font lists are identical. However, we have to do some fun
  244. // stuff to merge the lists if they're different.
  245. // We know how many soft font entries exist in each section,
  246. // via the "SoftFonts" int, but the entries may be non-consecutive.
  247. //
  248. // Note: This stomps all over the passed in buffer
  249. //
  250. // Return: TRUE if successfully conpleted, FALSE if not
  251. //------------------------------------------------------------------------
  252. BOOL NEAR PASCAL MergeFontLists(LPSTR lpOldSec,
  253. LPSTR lpNewSec,
  254. LPSTR lpTmp)
  255. {
  256. WORD wOldFonts;
  257. WORD wNewFonts;
  258. LPSFNODE lpFonts;
  259. WORD wMergedFonts=0;
  260. WORD wLoop;
  261. WORD wFound;
  262. WORD wNewIndex;
  263. BYTE szKey[20];
  264. // Get these values outside of the if statement, otherwise the compiler
  265. // may optimize out the assignment of wNewFonts
  266. GetInt(lpOldSec,MAKEINTRESOURCE(IDS_SOFTFONTS),&wOldFonts,0,FALSE);
  267. GetInt(lpNewSec,MAKEINTRESOURCE(IDS_SOFTFONTS),&wNewFonts,0,FALSE);
  268. if(wOldFonts || wNewFonts)
  269. {
  270. char szFormat[30];
  271. // Get a block big enough for the worst case--no common fonts
  272. if(!(lpFonts=(LPSFNODE)GlobalAllocPtr(GHND,
  273. (DWORD)(wOldFonts+wNewFonts)*sizeof(SFNODE))))
  274. {
  275. return FALSE;
  276. }
  277. // We need a formatting string
  278. LoadString(hInst,IDS_SOFTFONTFORMAT,szFormat,sizeof(szFormat));
  279. // Put fonts from lpNew Sec first in the list. This way, if we have
  280. // already updated at least one driver from 5A to 5MS and the soft
  281. // fonts haven't changed, our old font summary file is still valid.
  282. // Unidrv will automatically recreate the font summary file if it
  283. // sees that the number of soft fonts has changed. Even though we
  284. // know how many soft font entries exist, we don't know that they
  285. // will be sequential. (They may not be if one was added, then
  286. // deleted). Keep track of the original offset. Even though the
  287. // font installer seems to be 1-based, start looking at 0, just
  288. // to be safe.
  289. for(wLoop=0,wFound=0;wFound<wNewFonts;wLoop++)
  290. {
  291. wsprintf(lpTmp,szFormat,wLoop);
  292. if(GetProfileString(lpNewSec,lpTmp,szNone,lpTmp,TMPSIZE))
  293. {
  294. lpFonts[wMergedFonts].wIndex=wLoop;
  295. lpFonts[wMergedFonts++].atom=GlobalAddAtom(lpTmp);
  296. wFound++;
  297. }
  298. }
  299. // Remember where we left off in numbering the entries
  300. wNewIndex=wLoop;
  301. // Read fonts from lpOldSec--create atoms for new entries
  302. for(wLoop=0,wFound=0;wFound<wOldFonts;wLoop++)
  303. {
  304. wsprintf(lpTmp,szFormat,wLoop);
  305. if(GetProfileString(lpOldSec,lpTmp,szNone,lpTmp,TMPSIZE))
  306. {
  307. wFound++;
  308. if(!GlobalFindAtom(lpTmp))
  309. {
  310. lpFonts[wMergedFonts].wIndex=wLoop;
  311. lpFonts[wMergedFonts++].atom=GlobalAddAtom(lpTmp);
  312. }
  313. }
  314. }
  315. // Write out the list of atoms--do the entries from lpNewSec first
  316. WriteInt(lpNewSec,MAKEINTRESOURCE(IDS_SOFTFONTS),wMergedFonts);
  317. for(wLoop=0;wLoop<wNewFonts;wLoop++)
  318. {
  319. GlobalGetAtomName(lpFonts[wLoop].atom,lpTmp,TMPSIZE);
  320. wsprintf(szKey,szFormat,lpFonts[wLoop].wIndex);
  321. WriteProfileString(lpNewSec,szKey,lpTmp);
  322. GlobalDeleteAtom(lpFonts[wLoop].atom);
  323. }
  324. // Now write out the entries that were in lpOldSec but not in lpNewSec.
  325. // Since the actual numbering of these entries is arbitrary, just
  326. // start numbering them at wNewIndex and increment each time.
  327. for(wLoop=wNewFonts;wLoop<wMergedFonts;wLoop++)
  328. {
  329. GlobalGetAtomName(lpFonts[wLoop].atom,lpTmp,TMPSIZE);
  330. wsprintf(szKey,szFormat,wNewIndex);
  331. WriteProfileString(lpNewSec,szKey,lpTmp);
  332. GlobalDeleteAtom(lpFonts[wLoop].atom);
  333. wNewIndex++;
  334. }
  335. GlobalFreePtr(lpFonts);
  336. }
  337. return TRUE;
  338. }
  339. //----------------------*AddMissingEntries*-----------------------------
  340. // Action: Copy any entries that appear in lpOldSec but not lpNewSec to
  341. // lpNewSec, but don't copy any entries relevant to soft fonts
  342. // (These entries will be copied in MergeFontSections).
  343. //
  344. // Return: TRUE if successful, FALSE if not
  345. //----------------------------------------------------------------------
  346. BOOL NEAR PASCAL AddMissingEntries(LPSTR lpOldSec,
  347. LPSTR lpNewSec,
  348. LPSTR lpTmp)
  349. {
  350. WORD wSize;
  351. LPSTR lpBuf;
  352. LPSTR lpWork;
  353. char szTest2[30];
  354. char szTest1[30];
  355. int nLength;
  356. // Get the key names into buffers
  357. wSize=KEY_BUF_SIZE;
  358. if(!(lpBuf=GlobalAllocPtr(GHND,(DWORD)wSize)))
  359. return FALSE;
  360. while((WORD)GetProfileString(lpOldSec,NULL,szNone,lpBuf,wSize)==wSize-2)
  361. {
  362. wSize*=2;
  363. if(lpWork=GlobalReAllocPtr(lpBuf,(DWORD)wSize,GHND))
  364. lpBuf=lpWork;
  365. else
  366. {
  367. GlobalFreePtr(lpBuf);
  368. return FALSE;
  369. }
  370. }
  371. // Load some strings
  372. LoadString(hInst,IDS_FONTSUMMARY,szTest1,sizeof(szTest1));
  373. nLength=LoadString(hInst,IDS_SOFTFONTTEST,szTest2,sizeof(szTest2));
  374. // Now examine each entry, copy it if we want to keep it, and return TRUE
  375. // There are two cases where we don't want to copy the file--the key
  376. // named FontSummary and all keys that begin with "SoftFont"
  377. lpWork=lpBuf;
  378. while(wSize=(WORD)lstrlen(lpWork))
  379. {
  380. // Font Summary?
  381. if(lstrcmpi(lpWork,szTest1))
  382. {
  383. // Soft Font Entry?
  384. lstrcpy(lpTmp,lpWork);
  385. lpTmp[nLength]='\0';
  386. if(lstrcmpi(lpTmp,szTest2))
  387. {
  388. // Add this entry if it doesn't already exist in the new section
  389. if(!GetProfileString(lpNewSec,lpWork,szNone,lpTmp,TMPSIZE))
  390. {
  391. GetProfileString(lpOldSec,lpWork,szNone,lpTmp,TMPSIZE);
  392. WriteProfileString(lpNewSec,lpWork,lpTmp);
  393. }
  394. }
  395. }
  396. lpWork+=(wSize+1);
  397. }
  398. GlobalFreePtr(lpBuf);
  399. return TRUE;
  400. }
  401. //---------------------------*HandleSoftFonts*---------------------------
  402. // Action: Transfer the soft fonts between old and new entries. First we
  403. // copy any entries that don't already exist in the new section,
  404. // with the exception of soft font information. Then we go ahead
  405. // and merge the soft fonts, so the end result in the new section
  406. // is the union of the old and new soft fonts.
  407. //
  408. // Return: TRUE if success, FALSE if not
  409. //-----------------------------------------------------------------------
  410. BOOL NEAR PASCAL HandleSoftFonts(LPSTR lpszOldSec,
  411. LPSTR lpszNewSec)
  412. {
  413. char szTmp[TMPSIZE];
  414. if(AddMissingEntries(lpszOldSec,lpszNewSec,szTmp))
  415. return MergeFontLists(lpszOldSec,lpszNewSec,szTmp);
  416. return FALSE;
  417. }
  418. //------------------------------------------------------------------------
  419. // Function: ConvertStraight(lpSection,nOldID,nNewID)
  420. //
  421. // Action: Convert a section setting without translation
  422. //
  423. // Return: TRUE if the old setting existed
  424. //------------------------------------------------------------------------
  425. BOOL NEAR PASCAL ConvertStraight(LPSTR lpSection,
  426. int nOldID,
  427. int nNewID)
  428. {
  429. int nValue;
  430. if(GetInt(lpSection,MAKEINTRESOURCE(nOldID),&nValue,0,TRUE))
  431. {
  432. WriteInt(lpSection,MAKEINTRESOURCE(nNewID),nValue);
  433. return TRUE;
  434. }
  435. return FALSE;
  436. }
  437. //------------------------------------------------------------------------
  438. // Function: ConvertBool(lpSection,nOldID,nNewID,nNewValue)
  439. //
  440. // Action: Convert a section with minimal translation. If the old section
  441. // existed and was non-zero, write nNewValue to the new section.
  442. // If the old section existed and was 0, write 0 to the new section.
  443. //
  444. // Return: TRUE if the old setting existed
  445. //------------------------------------------------------------------------
  446. BOOL NEAR PASCAL ConvertBool(LPSTR lpSection,
  447. int nOldID,
  448. int nNewID,
  449. int nNewValue)
  450. {
  451. int nOldValue;
  452. if(GetInt(lpSection,MAKEINTRESOURCE(nOldID),&nOldValue,0,TRUE))
  453. {
  454. WriteInt(lpSection,MAKEINTRESOURCE(nNewID),nOldValue?nNewValue:0);
  455. return TRUE;
  456. }
  457. return FALSE;
  458. }
  459. //------------------------------------------------------------------------
  460. // Function: ConvertVectorMode(lpSection)
  461. //
  462. // Action: Convert the graphics mode setting
  463. // Cannot do straight conversion as defaults dont match
  464. //
  465. // Return: TRUE if the old section existed
  466. //------------------------------------------------------------------------
  467. BOOL NEAR PASCAL ConvertVectorMode(LPSTR lpSection)
  468. {
  469. int nValue;
  470. GetInt(lpSection,MAKEINTRESOURCE(IDS_OLDVECTORMODE),&nValue,1,TRUE);
  471. WriteInt(lpSection,MAKEINTRESOURCE(IDS_NEWVECTORMODE),nValue);
  472. return TRUE;
  473. }
  474. //------------------------------------------------------------------------
  475. // Function: ConvertResolution(lpSection,lpModel)
  476. //
  477. // Action: Convert the old resolution section to the new one
  478. //
  479. // Return: TRUE if the old section existed
  480. //------------------------------------------------------------------------
  481. BOOL NEAR PASCAL ConvertResolution(LPSTR lpSection,
  482. LPSTR lpModel)
  483. {
  484. int nValue;
  485. if(GetInt(lpSection,MAKEINTRESOURCE(IDS_OLD_5A_RESOLUTION),&nValue,0,TRUE))
  486. {
  487. LPSTR lpLJ4=szLJ4;
  488. LPSTR lpCheck=lpModel;
  489. BOOL bLJ4=TRUE;
  490. nValue=300/(1<<nValue);
  491. // Compare the passed-in model to szLJ4. If lpModel begins with the
  492. // substring "HP LaserJet 4", then lpLJ4 will point to NULL when we
  493. // exit the loop.
  494. while(*lpLJ4 == *lpCheck)
  495. {
  496. lpLJ4++;
  497. lpCheck++;
  498. }
  499. if(!*lpLJ4)
  500. {
  501. // This is in the LJ4 family--check if it's a 4L or 4ML
  502. if(lstrcmp(lpCheck,"L") && lstrcmp(lpCheck,"ML"))
  503. {
  504. int nTest;
  505. // Device is capable of 600 dpi--check the value for
  506. // "printerres".
  507. GetInt(lpSection,MAKEINTRESOURCE(IDS_OLD_5E_RESOLUTION),
  508. &nTest,600,TRUE);
  509. if(600==nTest)
  510. nValue<<=1;
  511. }
  512. }
  513. WriteInt(lpSection,MAKEINTRESOURCE(IDS_NEWRESOLUTION),nValue);
  514. WriteInt(lpSection,MAKEINTRESOURCE(IDS_NEWYRESOLUTION),nValue);
  515. return TRUE;
  516. }
  517. return FALSE;
  518. }
  519. //-------------------------------------------------------------------------
  520. // Function: WriteHalfTone(lpSection,nIndex)
  521. //
  522. // Action: Write the halftoning data to win.ini
  523. //
  524. // Return: VOID
  525. //-------------------------------------------------------------------------
  526. VOID NEAR PASCAL WriteHalfTone(LPSTR lpSection,
  527. int nIndex)
  528. {
  529. int nBrush;
  530. int nIntensity;
  531. switch(nIndex)
  532. {
  533. case GS_LINEART:
  534. nBrush=RES_DB_LINEART;
  535. nIntensity=100;
  536. break;
  537. case GS_SCANJET:
  538. nBrush=RES_DB_COARSE;
  539. nIntensity=150;
  540. break;
  541. case GS_PHOTO:
  542. default:
  543. nBrush=RES_DB_COARSE;
  544. nIntensity=100;
  545. break;
  546. }
  547. WriteInt(lpSection,MAKEINTRESOURCE(IDS_NEWBRUSH),nBrush);
  548. WriteInt(lpSection,MAKEINTRESOURCE(IDS_NEWINTENSITY),nIntensity);
  549. }
  550. //-------------------------------------------------------------------------
  551. // Function: Convert5aHalfTone(lpSection)
  552. //
  553. // Action: Convert the 5A halftoning settings
  554. //
  555. // Return: TRUE if the old section existed, FALSE if not
  556. //-------------------------------------------------------------------------
  557. BOOL NEAR PASCAL Convert5aHalfTone(LPSTR lpSection)
  558. {
  559. int nIndex;
  560. int nGray;
  561. int nBright;
  562. BOOL bGrayScale;
  563. BOOL bBrightness;
  564. // See if either setting exists...
  565. bGrayScale=GetInt(lpSection,MAKEINTRESOURCE(IDS_OLDGRAYSCALE),&nGray,
  566. 1,TRUE);
  567. bBrightness=GetInt(lpSection,MAKEINTRESOURCE(IDS_OLDBRIGHTNESS),&nBright,
  568. 0,TRUE);
  569. if(bGrayScale || bBrightness)
  570. {
  571. if(1==nBright)
  572. nIndex=GS_SCANJET;
  573. else if(0==nGray)
  574. nIndex=GS_LINEART;
  575. else
  576. nIndex=GS_PHOTO;
  577. WriteHalfTone(lpSection,nIndex);
  578. return TRUE;
  579. }
  580. return FALSE;
  581. }
  582. //-----------------------------------------------------------------------
  583. // Function: Convert5eHalfTone(LPSTR lpSection)
  584. //
  585. // Action: Convert the 5E halftoning settings
  586. //
  587. // Return: TRUE if successful, FALSE if not
  588. //-----------------------------------------------------------------------
  589. BOOL NEAR PASCAL Convert5eHalfTone(LPSTR lpSection)
  590. {
  591. int nValue;
  592. if(GetInt(lpSection,MAKEINTRESOURCE(IDS_OLD_5E_HALFTONE),&nValue,
  593. 0,TRUE))
  594. {
  595. WriteHalfTone(lpSection,nValue);
  596. return TRUE;
  597. }
  598. return FALSE;
  599. }
  600. //-----------------------------------------------------------------------
  601. // Function: Convert5aMemory(lpSection)
  602. //
  603. // Action: Convert the memory settings from the old to the new values
  604. //
  605. // Return: TRUE if the old section existed, FALSE if not
  606. //-----------------------------------------------------------------------
  607. BOOL NEAR PASCAL Convert5aMemory(LPSTR lpSection)
  608. {
  609. int nValue;
  610. int nPrinterMB;
  611. // Get memory settings--extract from prtindex.
  612. // Values range from 0 to 28, where 0-4 are the LaserJet III,
  613. // 5-9 are the LaserJet IIID, 10-14 are the LaserJet IIIP, and
  614. // 15-28 are the LaserJet IIISi. For indices less than 20, the
  615. // total MB is the index mod 5, + 1. For indices 20 and above, the
  616. // total MB is the index - 14, except for 26, 27, and 28, which
  617. // require special handling because of the increments that memory
  618. // can be added to the IIISi.
  619. // The formula used to calculate the settings is derived directly
  620. // from the values used in the hppcl5a driver. Specifically,
  621. // AM = 945 * TM - 245, where TM is the total memory in MB, and
  622. // AM is the available printer memory.
  623. if(GetInt(lpSection,MAKEINTRESOURCE(IDS_OLDMEMORY),&nValue,1,TRUE))
  624. {
  625. if(nValue<20)
  626. nPrinterMB=nValue%5 + 1;
  627. else
  628. {
  629. nPrinterMB=nValue-14;
  630. if(nValue>25)
  631. {
  632. nPrinterMB++; // 25=11MB, 26=13MB, so add an extra MB.
  633. if(nValue==28)
  634. nPrinterMB+=2; // 27=14MB, 28=17MB, so add 2 extra MB.
  635. }
  636. }
  637. nValue=945*nPrinterMB-245;
  638. WriteInt(lpSection,MAKEINTRESOURCE(IDS_NEWMEMORY),nValue);
  639. return TRUE;
  640. }
  641. return FALSE;
  642. }
  643. //-----------------------------------------------------------------------
  644. // Function: Convert5eMemory(lpSection)
  645. //
  646. // Action: Convert the HPPCL5E memory settings from the old to the new values
  647. //
  648. // Conversion code has to check the win.ini mem setting so that we upgrade
  649. // mem setting correctly
  650. //
  651. // Return: TRUE if the old section existed, FALSE if not
  652. //-----------------------------------------------------------------------
  653. BOOL NEAR PASCAL Convert5eMemory(LPSTR lpSection)
  654. {
  655. unsigned nValue;
  656. if(GetInt(lpSection,MAKEINTRESOURCE(IDS_NEWMEMORY),&nValue,1,FALSE))
  657. {
  658. if (nValue <= KB_THRESHOLD )
  659. {
  660. if (nValue > MAX_LJ4_MBMEMSETTING)
  661. nValue = MAX_LJ4_MBMEMSETTING; // force it to max value
  662. nValue=900*nValue - 450; // convert to KB, using HP formula
  663. WriteInt(lpSection,MAKEINTRESOURCE(IDS_NEWMEMORY),nValue);
  664. return TRUE;
  665. }
  666. }
  667. return FALSE;
  668. }
  669. //-----------------------------------------------------------------------
  670. // Function: Convert5MSMemory(lpSection)
  671. //
  672. // Action: Convert the WFW HPPCL5MS memory settings from the old to the new
  673. // values
  674. //
  675. // Conversion code has to check the win.ini mem setting so that we upgrade
  676. // mem setting correctly
  677. //
  678. // Added for backward compatability
  679. //
  680. // Return: TRUE if the old section existed, FALSE if not
  681. //-----------------------------------------------------------------------
  682. BOOL NEAR PASCAL Convert5MSMemory(LPSTR lpSection)
  683. {
  684. unsigned nValue;
  685. if(GetInt(lpSection,MAKEINTRESOURCE(IDS_NEWMEMORY),&nValue,1,TRUE))
  686. {
  687. nValue = nValue / 900; // convert to MB value
  688. nValue = 945*nValue - 245; // formula used in hppcl5a driver
  689. // used to convert to available mem
  690. WriteInt(lpSection,MAKEINTRESOURCE(IDS_NEWMEMORY),nValue);
  691. return TRUE;
  692. }
  693. return FALSE;
  694. }
  695. //------------------------------------------------------------------------
  696. // Function: HandleFontCartridges(lpSection,lpOldDrvSec,lpNewDrvSec)
  697. //
  698. // Action: Handle font cartridge data
  699. //
  700. // Return: VOID
  701. //------------------------------------------------------------------------
  702. VOID NEAR PASCAL HandleFontCartridges(LPSTR lpSection,
  703. LPSTR lpOldDrvSec,
  704. LPSTR lpNewDrvSec)
  705. {
  706. int nCount;
  707. // Get the count of cartridges--if there are no cartridges, do nothing.
  708. if(GetInt(lpSection,MAKEINTRESOURCE(IDS_CARTRIDGECOUNT),&nCount,0,TRUE))
  709. {
  710. char szOldCartKey[16];
  711. char szNewCartKey[16];
  712. short nCart = 0;
  713. short i;
  714. short index;
  715. int nLength1;
  716. int nLength2;
  717. nLength1=LoadString(hInst,IDS_CARTINDEX,szOldCartKey,
  718. sizeof(szOldCartKey));
  719. nLength2=LoadString(hInst,IDS_CARTRIDGE,szNewCartKey,
  720. sizeof(szNewCartKey));
  721. for (i = 0; i < nCount; i++)
  722. {
  723. if (i > 0)
  724. wsprintf(szOldCartKey+nLength1,"%d",i);
  725. // compose cartridge keyname for current driver
  726. wsprintf(szNewCartKey+nLength2,"%d",i+1);
  727. if ((index = GetProfileInt(lpNewDrvSec, szOldCartKey, 0)) > 0)
  728. {
  729. WriteProfileString(lpNewDrvSec, szOldCartKey, NULL);
  730. nCart++;
  731. if (index <= MAX_CART_INDEX)
  732. WriteInt(lpSection,szNewCartKey,rgNewCartMap[index-1]);
  733. else
  734. // external cartridges. Simply copy the id over.
  735. WriteInt(lpSection,szNewCartKey,index);
  736. }
  737. }
  738. // Save the # of cartridges
  739. WriteInt(lpSection,MAKEINTRESOURCE(IDS_CARTRIDGECOUNT),nCart);
  740. }
  741. }
  742. //--------------------------------------------------------------------------
  743. // Function: HandleFonts(lpSection,lpDevName,lpPort)
  744. //
  745. // Action: Deal with soft fonts & font cartridges
  746. //
  747. // Return: VOID
  748. //--------------------------------------------------------------------------
  749. VOID NEAR PASCAL HandleFonts(LPSTR lpSection,
  750. LPSTR lpDevName,
  751. LPSTR lpPort)
  752. {
  753. char szOldDrvSec[64]; // HPPCL5A,<port> or HPPCL5E,<port>
  754. char szNewDrvSec[64]; // HPPCL5MS,<port>
  755. int nCount;
  756. BOOL bOldExists=FALSE; // Does old section exist?
  757. LoadString(hInst,IDS_OLD_5E_DRIVERNAME,szOldDrvSec,sizeof(szOldDrvSec));
  758. MakeAppName((LPSTR)szOldDrvSec,lpPort,sizeof(szOldDrvSec));
  759. // See if the old section exists at all. Temporarily borrow szNewDrvSec.
  760. if(GetProfileString(szOldDrvSec,NULL,szNone,szNewDrvSec,
  761. sizeof(szNewDrvSec)))
  762. {
  763. bOldExists=TRUE;
  764. }
  765. else
  766. {
  767. // Try the HPPCL5E driver...
  768. LoadString(hInst,IDS_OLD_5A_DRIVERNAME,szOldDrvSec,sizeof(szOldDrvSec));
  769. MakeAppName((LPSTR)szOldDrvSec,lpPort,sizeof(szOldDrvSec));
  770. if(GetProfileString(szOldDrvSec,NULL,szNone,szNewDrvSec,
  771. sizeof(szNewDrvSec)))
  772. {
  773. bOldExists=TRUE;
  774. }
  775. }
  776. lstrcpy(szNewDrvSec,rgchModuleName);
  777. MakeAppName((LPSTR)szNewDrvSec,lpPort,sizeof(szNewDrvSec));
  778. if(bOldExists)
  779. {
  780. HandleSoftFonts(szOldDrvSec,szNewDrvSec);
  781. HandleFontCartridges(lpSection,szOldDrvSec,szNewDrvSec);
  782. }
  783. // create UNIDRV's font summary file, if there are many soft fonts.
  784. GetInt(szNewDrvSec,MAKEINTRESOURCE(IDS_SOFTFONTS),&nCount,0,FALSE);
  785. if(nCount>SOFT_FONT_THRES)
  786. {
  787. HDC hIC;
  788. if(hIC=CreateIC(rgchModuleName,lpDevName,lpPort,NULL))
  789. DeleteDC(hIC);
  790. }
  791. }
  792. //-------------------------*DevInstall*---------------------------------------
  793. // Action: De-install, upgrade or install a device.
  794. //
  795. //----------------------------------------------------------------------------
  796. int FAR PASCAL DevInstall(HWND hWnd,
  797. LPSTR lpDevName,
  798. LPSTR lpOldPort,
  799. LPSTR lpNewPort)
  800. {
  801. char szDevSec[64]; // [<device>,<port>] section name
  802. if (!lpDevName)
  803. return -1;
  804. if (!lpOldPort)
  805. {
  806. char szBuf[10];
  807. if (!lpNewPort)
  808. return 0;
  809. // install a device for the first time. Convert old HPPCL5a settings,
  810. // which are still under [<device>,<port>], into equivalent new
  811. // UNIDRV settings under [<device>,<port>], if applicable.
  812. // Delete old settings that are linked to the device name, but don't
  813. // delete old settings that are liked to the driver and port (softfonts)
  814. lstrcpy(szDevSec,lpDevName);
  815. MakeAppName((LPSTR)szDevSec,lpNewPort,sizeof(szDevSec));
  816. // check if old settings exist at all
  817. if(GetProfileString(szDevSec,NULL,NULL,szBuf,sizeof(szBuf)))
  818. {
  819. // Do the straight conversions
  820. ConvertStraight(szDevSec,IDS_OLDPAPERSIZE,IDS_NEWPAPERSIZE);
  821. ConvertStraight(szDevSec,IDS_OLDPAPERSOURCE,IDS_NEWPAPERSOURCE);
  822. ConvertStraight(szDevSec,IDS_OLDORIENTATION,IDS_NEWORIENTATION);
  823. ConvertStraight(szDevSec,IDS_OLDTRUETYPE,IDS_NEWTRUETYPE);
  824. ConvertStraight(szDevSec,IDS_OLDSEPARATION,IDS_NEWSEPARATION);
  825. // Convert the simple translations
  826. ConvertBool(szDevSec,IDS_OLDPAGEPROTECT,IDS_NEWPAGEPROTECT,1);
  827. ConvertBool(szDevSec,IDS_OLDOUTPUT,IDS_NEWOUTPUT,259);
  828. // Do the stuff that requires more complicated conversion
  829. ConvertResolution(szDevSec,lpDevName);
  830. if(!Convert5eHalfTone(szDevSec))
  831. Convert5aHalfTone(szDevSec);
  832. if(!Convert5eMemory(szDevSec))
  833. {
  834. if(!Convert5MSMemory(szDevSec))
  835. Convert5aMemory(szDevSec);
  836. }
  837. ConvertVectorMode(szDevSec);
  838. // Handle soft fonts & cartridges
  839. HandleFonts(szDevSec,lpDevName,lpNewPort);
  840. }
  841. // Flush the cached settings from win.ini
  842. WriteProfileString(NULL,NULL,NULL);
  843. }
  844. else
  845. {
  846. int nCount;
  847. // move device settings from the old port to the new port, or
  848. // de-install a device, i.e. remove its device setttings in order
  849. // to compress the profile.
  850. // First, check if there is any soft font installed under the
  851. // old port. If so, warn the user to copy them over.
  852. lstrcpy(szDevSec,rgchModuleName);
  853. MakeAppName((LPSTR)szDevSec,lpOldPort,sizeof(szDevSec));
  854. if(GetInt(szDevSec,MAKEINTRESOURCE(IDS_SOFTFONTS),&nCount,0,FALSE)
  855. && nCount && lpNewPort)
  856. {
  857. NPSTR npTemp;
  858. if(npTemp=(NPSTR)LocalAlloc(LPTR,TMPSIZE))
  859. {
  860. if(LoadString(hInst,IDS_SOFTFONTWARNING,npTemp,TMPSIZE))
  861. {
  862. // Use this API so that the M Box is set to the Foreground
  863. MSGBOXPARAMS mbp;
  864. mbp.cbSize = sizeof(mbp);
  865. mbp.hwndOwner = hWnd;
  866. mbp.hInstance = hInst;
  867. mbp.lpszText = npTemp;
  868. mbp.lpszCaption = lpOldPort;
  869. mbp.dwStyle = MB_SETFOREGROUND | MB_OK | MB_ICONEXCLAMATION;
  870. mbp.lpszIcon = NULL;
  871. mbp.dwContextHelpId = 0L;
  872. mbp.lpfnMsgBoxCallback = NULL;
  873. MessageBoxIndirect(&mbp);
  874. }
  875. LocalFree((HLOCAL)npTemp);
  876. }
  877. }
  878. }
  879. return UniDevInstall(hWnd,lpDevName,lpOldPort,lpNewPort);
  880. }
  881. // the following 3 definitions MUST be compatible with the
  882. // HPPCL font installer
  883. #define CLASS_LASERJET 0
  884. #define CLASS_DESKJET 1
  885. #define CLASS_DESKJET_PLUS 2
  886. //---------------------------*InstallExtFonts*---------------------------------
  887. // Action: call the specific font installer to add/delete/modify soft fonts
  888. // and/or external cartridges.
  889. //
  890. // Parameters:
  891. // HWND hWnd; handle to the parent windows.
  892. // LPSTR lpDeviceName; long pointer to the printer name.
  893. // LPSTR lpPortName; long pointer to the associated port name.
  894. // BOOL bSoftFonts; flag if supporting soft fonts or not.
  895. //
  896. // Return Value:
  897. // > 0 : if the font information has changed;
  898. // == 0 : if nothing has changed;
  899. // == -1 : if intending to use the universal font installer
  900. // (not available now).
  901. //-------------------------------------------------------------------------
  902. int FAR PASCAL InstallExtFonts(HWND hWnd,
  903. LPSTR lpDeviceName,
  904. LPSTR lpPortName,
  905. BOOL bSoftFonts)
  906. {
  907. int fsVers;
  908. HANDLE hFIlib;
  909. SOFTFONTPROC lpFIns;
  910. if ((hFIlib = LoadLibrary((LPSTR)"FINSTALL.DLL")) < 32 ||
  911. !(lpFIns = (SOFTFONTPROC)GetProcAddress(hFIlib,"InstallSoftFont")))
  912. {
  913. if (hFIlib >= 32)
  914. FreeLibrary(hFIlib);
  915. #ifdef DEBUG
  916. MessageBox(0,
  917. "Can't load FINSTAL.DLL or can't get InstallSoftFont",
  918. NULL, MB_OK);
  919. #endif
  920. return TRUE;
  921. }
  922. // FINSTALL.DLL was loaded properly. Now call InstallSoftFont().
  923. // We choose to ignore the returned "fvers". No use of it.
  924. fsVers = (*lpFIns)(hWnd,rgchModuleName,lpPortName,
  925. (GetKeyState(VK_SHIFT)<0 && GetKeyState(VK_CONTROL)<0),
  926. 1, // dummy value for "fvers".
  927. bSoftFonts?CLASS_LASERJET:256);
  928. FreeLibrary(hFIlib);
  929. return fsVers;
  930. }
  931. // -------------------------------------------------------------------
  932. //
  933. // Special case control functions wrt SETCHARSET escape. This is necessary
  934. // to avoid breaking Winword and Pagemaker. (note that we don't actually
  935. // do anything with SETCHARSET, but apps break unless we say that we do)
  936. //
  937. // --------------------------------------------------------------------
  938. int FAR PASCAL Control(LPDV lpdv,
  939. short function,
  940. LPSTR lpInData,
  941. LPSTR lpOutData)
  942. {
  943. // Tell app that SETCHARSET is supported
  944. if(QUERYESCSUPPORT == function && *((LPWORD)lpInData) == SETCHARSET)
  945. return 1;
  946. // Special case SETCHARSET
  947. if(SETCHARSET == function)
  948. return 1;
  949. // General case
  950. return UniControl(lpdv, function, lpInData, lpOutData);
  951. }
  952. #ifndef NOFONTMAP
  953. //----------------------------------------------------------------------
  954. // Function: MapFaceName(lplfOld,lplfNew)
  955. //
  956. // Action: Map old face names to their new counterparts. Do as little
  957. // work as we possibly can, since this function gets called
  958. // often & we don't want to impact performance. Optimize
  959. // the whole search to the case where we don't find a match,
  960. // as this will be the most common scenario.
  961. //
  962. // Return: A pointer to the LOGFONT to actually hand to Unidrv. Cast
  963. // the return to a LPSTR, just so the compiler is happy.
  964. //----------------------------------------------------------------------
  965. LPSTR NEAR PASCAL MapFaceName(LPLOGFONT lplfOld,
  966. LPLOGFONT lplfNew)
  967. {
  968. LPLOGFONT lpReturn=lplfOld; // By default
  969. NPFACEINDEX pIndex;
  970. LPSTR lpFace=lplfOld->lfFaceName;
  971. BYTE cTest=*lpFace++;
  972. // Determine range of possible matches in the table. Since the
  973. // table is sorted alphabetically, we may be able to bail out
  974. // before we reach the end of the table.
  975. for(pIndex=FaceIndex;cTest > pIndex->cFirstChar;pIndex++)
  976. ;
  977. // Only proceed if the first character matches and this isn't the
  978. // firewall (cTest = \xFF).
  979. if(cTest==pIndex->cFirstChar && ('\xFF' != cTest))
  980. {
  981. WORD wStartIndex=(WORD)(pIndex->bIndex);
  982. WORD wStopIndex=(WORD)((pIndex+1)->bIndex);
  983. WORD wLoop=wStartIndex;
  984. NPSTR npMapFace=&(FaceMap[wStartIndex].szOldFace[1]);
  985. BYTE cMapFace;
  986. // Check the rest of the string against the table entries.
  987. // This search routine takes advantage of the fact that
  988. // the old face names in the table are fully sorted alphabetically.
  989. // This search routine takes advantage of the fact that our table
  990. // is fully sorted, and doesn't do a full string comparison until
  991. // we actually think we have a match. Once we think there's a match,
  992. // we'll double-check the entire string to prevent false triggering.
  993. while(wLoop < wStopIndex)
  994. {
  995. // Look for a match. At this point, match a wildcard to
  996. // anything--we'll do a more stringent check later on, if we
  997. // think we have a match. Stop if cTest is NULL.
  998. while((((cTest=*lpFace)==(cMapFace=*npMapFace)) ||
  999. ('\x01'==cMapFace)) && cTest)
  1000. {
  1001. npMapFace++;
  1002. lpFace++;
  1003. }
  1004. // We arrive here via two conditions: (1) we've reached the
  1005. // end of lpFace and cTest is NULL, or (2) cMapFace and cTest
  1006. // failed to compare. We should only continue searching if
  1007. // cMapFace is non-NULL and cTest is larger than cMapFace (take
  1008. // advantage of the fact that FaceMap is sorted alphabetically).
  1009. // For overall performance, check for the no match case first.
  1010. // Move to the next table entry as long as there's still a
  1011. // chance to find a match.
  1012. if(cTest > cMapFace)
  1013. {
  1014. npMapFace+=sizeof(FACEMAP);
  1015. wLoop++;
  1016. continue; // Go to the next iteration
  1017. }
  1018. // if cTest is non-NULL, then the sorting of the table guarantees
  1019. // that there are no matches. Bail out now.
  1020. if(cTest)
  1021. goto MFN_exit;
  1022. // cTest is NULL, so we will not make another iteration. The
  1023. // only thing left to decide is whether or not we have a match
  1024. // with the current string.
  1025. if(cMapFace)
  1026. goto MFN_exit;
  1027. // The guards above ensure that we only arrive here if both
  1028. // cTest and cMapFace are NULL, which means that if we're
  1029. // going to find a match, this string is it. We took shortcuts
  1030. // in the comparisons above, so do a stringent comparison now
  1031. // to be sure that this is really a match. The only characters
  1032. // to match wildcards are '1' and 'N', since these are the only
  1033. // ones used in previous versions of the driver.
  1034. for(lpFace=lplfOld->lfFaceName,npMapFace=FaceMap[wLoop].szOldFace;
  1035. (cMapFace=*npMapFace) && (cTest=*lpFace);
  1036. npMapFace++,lpFace++)
  1037. {
  1038. if(!((cTest==cMapFace) ||
  1039. (('\x01'==cMapFace)&&(('1'==cTest)||('N'==cTest)))))
  1040. {
  1041. // False trigger--bail out without changing facename
  1042. goto MFN_exit;
  1043. }
  1044. }
  1045. // We now know that this really is a match--keep the requested
  1046. // attributes & change just the face name.
  1047. *lplfNew=*lplfOld;
  1048. lstrcpy(lplfNew->lfFaceName,FaceMap[wLoop].szNewFace);
  1049. lpReturn=lplfNew;
  1050. goto MFN_exit;
  1051. }
  1052. }
  1053. MFN_exit:
  1054. return (LPSTR)lpReturn;
  1055. }
  1056. #endif
  1057. //----------------------------------------------------------------------
  1058. // Function: RealizeObject(lpdv,sStyle,lpInObj,lpOutObj,lpTextXForm)
  1059. //
  1060. // Action: Hook this out to enable font substitution. If the object isn't
  1061. // a font, do absolutely nothing.
  1062. //
  1063. // Return: Save as UniRealizeObject().
  1064. //----------------------------------------------------------------------
  1065. DWORD FAR PASCAL RealizeObject(LPDV lpdv,
  1066. short sStyle,
  1067. LPSTR lpInObj,
  1068. LPSTR lpOutObj,
  1069. LPTEXTXFORM lpTextXForm)
  1070. {
  1071. #ifndef NOFONTMAP
  1072. LOGFONT lfNew;
  1073. if(OBJ_FONT==sStyle)
  1074. lpInObj=MapFaceName((LPLOGFONT)lpInObj,&lfNew);
  1075. #endif
  1076. return UniRealizeObject(lpdv, sStyle, lpInObj, lpOutObj, lpTextXForm);
  1077. }
  1078.