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.

1562 lines
51 KiB

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