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

2828 lines
81 KiB

  1. /****************************************************************************/
  2. /* */
  3. /* RCTG.C - */
  4. /* */
  5. /* Windows 3.0 Resource Compiler - Resource generation functions */
  6. /* */
  7. /* */
  8. /****************************************************************************/
  9. #include "rc.h"
  10. #include "assert.h"
  11. #define MAXCODE 128000 //AFX uses > 65000
  12. #define DIBBITMAPFORMAT 0x4D42 /* 'BM' as in PM format */
  13. #undef min
  14. #define min(a,b) ((a<b)?(a):(b))
  15. PCHAR CodeArray; /* pointer to code buffer */
  16. int CodeSize; /* size of code buffer */
  17. int CCount; /* current code array address */
  18. PFILE fhCode; /* file handle for remaining data */
  19. static int ItemCountLoc; /* a patch location; this one for */
  20. static int ItemExtraLoc; /* a patch location; this one for */
  21. typedef struct {
  22. SHORT csHotX;
  23. SHORT csHotY;
  24. SHORT csWidth;
  25. SHORT csHeight;
  26. SHORT csWidthBytes;
  27. SHORT csColor;
  28. } IconHeader;
  29. typedef struct {
  30. UINT dfVersion; /* not in FONTINFO */
  31. DWORD dfSize; /* not in FONTINFO */
  32. CHAR dfCopyright[60]; /* not in FONTINFO */
  33. UINT dfType;
  34. UINT dfPoints;
  35. UINT dfVertRes;
  36. UINT dfHorizRes;
  37. UINT dfAscent;
  38. UINT dfInternalLeading;
  39. UINT dfExternalLeading;
  40. BYTE dfItalic;
  41. BYTE dfUnderline;
  42. BYTE dfStrikeOut;
  43. UINT dfWeight;
  44. BYTE dfCharSet;
  45. UINT dfPixWidth;
  46. UINT dfPixHeight;
  47. BYTE dfPitchAndFamily;
  48. UINT dfAvgWidth;
  49. UINT dfMaxWidth;
  50. BYTE dfFirstChar;
  51. BYTE dfLastChar;
  52. BYTE dfDefaultCHar;
  53. BYTE dfBreakChar;
  54. UINT dfWidthBytes;
  55. DWORD dfDevice; /* See Adaptation Guide 6.3.10 and 6.4 */
  56. DWORD dfFace; /* See Adaptation Guide 6.3.10 and 6.4 */
  57. DWORD dfReserved; /* See Adaptation Guide 6.3.10 and 6.4 */
  58. } ffh;
  59. #define FONT_FIXED sizeof(ffh)
  60. #define FONT_ALL sizeof(ffh) + 64
  61. struct MacCursor {
  62. char data[16];
  63. char mask[16];
  64. short hotSpotV;
  65. short hotSpotH;
  66. };
  67. typedef struct {
  68. unsigned short red;
  69. unsigned short green;
  70. unsigned short blue;
  71. } RGBColor;
  72. typedef struct {
  73. unsigned short value;
  74. RGBColor rgb;
  75. } ColorSpec;
  76. #define ccs2 2
  77. ColorSpec rgcs2[ccs2] = {
  78. {0, {0xffff,0xffff,0xffff}},
  79. {1, {0x0000,0x0000,0x0000}}
  80. };
  81. #define ccs16 16
  82. ColorSpec rgcs16[ccs16] = {
  83. {0x00, {0xffff,0xffff,0xffff}},
  84. {0x01, {0xfc00,0xf37d,0x052f}},
  85. {0x02, {0xffff,0x648a,0x028c}},
  86. {0x03, {0xdd6b,0x08c2,0x06a2}},
  87. {0x04, {0xf2d7,0x0856,0x84ec}},
  88. {0x05, {0x46e3,0x0000,0xa53e}},
  89. {0x06, {0x0000,0x0000,0xd400}},
  90. {0x07, {0x0241,0xab54,0xeaff}},
  91. {0x08, {0x1f21,0xb793,0x1431}},
  92. {0x09, {0x0000,0x64af,0x11b0}},
  93. {0x0a, {0x5600,0x2c9d,0x0524}},
  94. {0x0b, {0x90d7,0x7160,0x3a34}},
  95. {0x0c, {0xc000,0xc000,0xc000}},
  96. {0x0d, {0x8000,0x8000,0x8000}},
  97. {0x0e, {0x4000,0x4000,0x4000}},
  98. {0x0f, {0x0000,0x0000,0x0000}}
  99. };
  100. /*
  101. * the 34 legal icon colors
  102. */
  103. #define ccs256 34
  104. ColorSpec rgcs256[ccs256] = {
  105. {0x01, {0xFFFF, 0xFFFF, 0xCCCC}},
  106. {0x08, {0xFFFF, 0xCCCC, 0x9999}},
  107. {0x33, {0xCCCC, 0x9999, 0x6666}},
  108. {0x16, {0xFFFF, 0x6666, 0x3333}},
  109. {0x92, {0x3333, 0xFFFF, 0x9999}},
  110. {0xE3, {0x0000, 0xBBBB, 0x0000}},
  111. {0x9F, {0x3333, 0x9999, 0x6666}},
  112. {0xA5, {0x3333, 0x6666, 0x6666}},
  113. {0x48, {0x9999, 0xFFFF, 0xFFFF}},
  114. {0xC0, {0x0000, 0x9999, 0xFFFF}},
  115. {0xEC, {0x0000, 0x0000, 0xDDDD}},
  116. {0xB0, {0x3333, 0x0000, 0x9999}},
  117. {0x2A, {0xCCCC, 0xCCCC, 0xFFFF}},
  118. {0x54, {0x9999, 0x9999, 0xFFFF}},
  119. {0x7F, {0x6666, 0x6666, 0xCCCC}},
  120. {0xAB, {0x3333, 0x3333, 0x6666}},
  121. {0x13, {0xFFFF, 0x6666, 0xCCCC}},
  122. {0x69, {0x9999, 0x0000, 0x6666}},
  123. {0x5C, {0x9999, 0x6666, 0x9999}},
  124. {0x00, {0xFFFF, 0xFFFF, 0xFFFF}},
  125. {0xF5, {0xEEEE, 0xEEEE, 0xEEEE}},
  126. {0xF6, {0xDDDD, 0xDDDD, 0xDDDD}},
  127. {0x2B, {0xCCCC, 0xCCCC, 0xCCCC}},
  128. {0xF7, {0xBBBB, 0xBBBB, 0xBBBB}},
  129. {0xF8, {0xAAAA, 0xAAAA, 0xAAAA}},
  130. {0xF9, {0x8888, 0x8888, 0x8888}},
  131. {0xFA, {0x7777, 0x7777, 0x7777}},
  132. {0xFB, {0x5555, 0x5555, 0x5555}},
  133. {0xFC, {0x4444, 0x4444, 0x4444}},
  134. {0xFD, {0x2222, 0x2222, 0x2222}},
  135. {0xFE, {0x1111, 0x1111, 0x1111}},
  136. {0xFF, {0x0000, 0x0000, 0x0000}},
  137. {0x05, {0xFFFF, 0xFFFF, 0x0000}},
  138. {0xD8, {0xDDDD, 0x0000, 0x0000}}
  139. };
  140. void ProcessMacIcons(RESINFO* pRes, int itBase, int ib1, int ib4, int ib8);
  141. void ReadDIB(int ibDesc, struct tagDESCRIPTOR *pds, BITMAPINFOHEADER* pbmh, int* pcbWidth, void** ppBits, RGBQUAD** prgrgq, BOOL fIcon);
  142. void CompactAndFlipIcon(BYTE* pBits, int cbRowCur, int cbRowMask, int cbRowNew, int cbRowMaskNew, int Height);
  143. void WriteMacRsrc(void* pBits, int cbBits, RESINFO* pResBase, DWORD res);
  144. void LookupIconColor(ColorSpec* rgcs, int ccs, RGBQUAD* pq);
  145. long MungeResType(WCHAR *szType, short wOrd);
  146. int IdUnique(TYPEINFO *ptype, RESINFO* pres);
  147. RESINFO* LookupIconRes(TYPEINFO* ptypeIcon, RESINFO* pres);
  148. void TranslateString(char* sz);
  149. void TranslateBuffer(char* rgch, int cch);
  150. /*---------------------------------------------------------------------------*/
  151. /* */
  152. /* GenWarning2() - */
  153. /* */
  154. /*---------------------------------------------------------------------------*/
  155. VOID
  156. GenWarning2(
  157. int iMsg,
  158. PCHAR arg
  159. )
  160. {
  161. SET_MSG(Msg_Text, sizeof(Msg_Text), GET_MSG(iMsg), curFile, token.row, arg);
  162. SendWarning(Msg_Text);
  163. }
  164. /*---------------------------------------------------------------------------*/
  165. /* */
  166. /* GenWarning4() - */
  167. /* */
  168. /*---------------------------------------------------------------------------*/
  169. VOID
  170. GenWarning4(
  171. int iMsg,
  172. PCHAR arg1,
  173. PCHAR arg2,
  174. PCHAR arg3
  175. )
  176. {
  177. SET_MSG(Msg_Text,
  178. sizeof(Msg_Text),
  179. GET_MSG(iMsg),
  180. curFile,
  181. token.row,
  182. arg1,
  183. arg2,
  184. arg3);
  185. SendWarning(Msg_Text);
  186. }
  187. /*---------------------------------------------------------------------------*/
  188. /* */
  189. /* GenError2() - */
  190. /* */
  191. /*---------------------------------------------------------------------------*/
  192. void
  193. GenError2(
  194. int iMsg,
  195. PCHAR arg
  196. )
  197. {
  198. if (fhCode > 0)
  199. fclose(fhCode);
  200. SET_MSG(Msg_Text, sizeof(Msg_Text), GET_MSG(iMsg), curFile, token.row, arg);
  201. SendError(Msg_Text);
  202. quit("\n");
  203. }
  204. /*---------------------------------------------------------------------------*/
  205. /* */
  206. /* GenError1() - */
  207. /* */
  208. /*---------------------------------------------------------------------------*/
  209. void
  210. GenError1(
  211. int iMsg
  212. )
  213. {
  214. if (fhCode > 0)
  215. fclose(fhCode);
  216. SET_MSG(Msg_Text, sizeof(Msg_Text), GET_MSG(iMsg), curFile, token.row);
  217. SendError(Msg_Text);
  218. quit("\n");
  219. }
  220. /*---------------------------------------------------------------------------*/
  221. /* */
  222. /* CtlAlloc() - */
  223. /* */
  224. /*---------------------------------------------------------------------------*/
  225. VOID
  226. CtlAlloc(
  227. VOID
  228. )
  229. {
  230. CodeSize = MAXCODE;
  231. CodeArray = (PCHAR) MyAlloc(MAXCODE);
  232. }
  233. /*---------------------------------------------------------------------------*/
  234. /* */
  235. /* CtlInit() - */
  236. /* */
  237. /*---------------------------------------------------------------------------*/
  238. VOID
  239. CtlInit(
  240. VOID
  241. )
  242. {
  243. CCount = 0; /* absolute location in CodeArray */
  244. fhCode = NULL_FILE; /* don't copy file unless we need to */
  245. }
  246. /*---------------------------------------------------------------------------*/
  247. /* */
  248. /* CtlFile() - */
  249. /* */
  250. /*---------------------------------------------------------------------------*/
  251. PFILE
  252. CtlFile(
  253. PFILE fh
  254. )
  255. {
  256. if (fh != NULL_FILE)
  257. fhCode = fh; /* set file handle to read remaining resource from */
  258. return(fhCode);
  259. }
  260. /*---------------------------------------------------------------------------*/
  261. /* */
  262. /* CtlFree() - */
  263. /* */
  264. /*---------------------------------------------------------------------------*/
  265. VOID
  266. CtlFree(
  267. VOID
  268. )
  269. {
  270. CodeSize = 0;
  271. MyFree(CodeArray);
  272. }
  273. /*---------------------------------------------------------------------------*/
  274. /* */
  275. /* GetSpace() - */
  276. /* */
  277. /*---------------------------------------------------------------------------*/
  278. PCHAR
  279. GetSpace(
  280. WORD cb
  281. )
  282. {
  283. PCHAR pch;
  284. if (CCount > (int) (CodeSize - cb)) {
  285. PVOID pv;
  286. if ((pv = HeapReAlloc(hHeap, HEAP_NO_SERIALIZE|HEAP_ZERO_MEMORY, ((PCHAR)CodeArray)-8, CodeSize+0x00010000+8)) == NULL) {
  287. GenError1(2168); //"Resource too large"
  288. /* GenError1 calls quit() and doesn't return! */
  289. }
  290. CodeArray = ((PCHAR)pv)+8;
  291. CodeSize += 0x00010000;
  292. }
  293. pch = CodeArray + CCount;
  294. CCount += cb;
  295. return(pch);
  296. }
  297. /*---------------------------------------------------------------------------*/
  298. /* */
  299. /* WriteString() - */
  300. /* */
  301. /*---------------------------------------------------------------------------*/
  302. VOID
  303. WriteString(
  304. PWCHAR sz,
  305. BOOL fMacCP
  306. )
  307. {
  308. /* add a string to the resource buffer */
  309. if (fMacRsrcs) {
  310. WriteMacString(sz, fMacCP, FALSE);
  311. } else {
  312. do {
  313. WriteWord(*sz);
  314. } while (*sz++ != 0);
  315. }
  316. }
  317. /*---------------------------------------------------------------------------*/
  318. /* */
  319. /* WriteMacString() - */
  320. /* */
  321. /*---------------------------------------------------------------------------*/
  322. VOID
  323. WriteMacString(
  324. PWCHAR sz,
  325. BOOL fMacCP,
  326. BOOL fPascal
  327. )
  328. {
  329. BYTE rgb[256];
  330. BYTE rgbExpand[256];
  331. BYTE* pb = rgb;
  332. BYTE* pbExpand = rgbExpand;
  333. int cch = 0;
  334. int cb = 0;
  335. if (sz != NULL)
  336. {
  337. UINT iCP;
  338. UINT nCP = uiCodePage;
  339. BOOL fAttemptTranslate = FALSE;
  340. static UINT rgnCP[] = {10029, 10007, 10000, 10006, 10081}; // Mac codepages
  341. static BOOL rgfCP[5];
  342. // If the codepage for the current resource text is one of the Windows
  343. // Latin 1, Greek, Cyrillic, Turkish, or Eastern European codepages, then
  344. // there exists a corresponding Macintosh codepage in Win32 and it is valid
  345. // to use WCToMB to map the Windows text to the Macintosh character set. If
  346. // the Windows text is in a different code page, we don't try to do any
  347. // mapping.
  348. iCP = uiCodePage - 1250;
  349. if (fMacCP && uiCodePage >= 1250 && uiCodePage <= 1254) {
  350. nCP = rgnCP[iCP];
  351. // unfortunately the Mac code pages are not supported under Windows 95.
  352. // To handle this, we check to see if the Mac code page we came up
  353. // with is actually available, and if it isn't, revert back to uiCodePage.
  354. if ((rgfCP[iCP] & 0x01) == 0) { // is this fCP still uninitialized?
  355. rgfCP[iCP] |= 0x01; // bit 0 set: has been initialized
  356. if (IsValidCodePage(nCP))
  357. rgfCP[iCP] |= 0x02; // bit 1 set: this CP is available
  358. }
  359. if ((rgfCP[iCP] & 0x02) == 0) {
  360. nCP = uiCodePage;
  361. fAttemptTranslate = TRUE;
  362. }
  363. }
  364. cch = wcslen(sz);
  365. cb = WideCharToMultiByte(nCP, 0, sz, cch, NULL, 0, NULL, NULL);
  366. if (cb > sizeof(rgb))
  367. pb = (BYTE *) MyAlloc(cb);
  368. WideCharToMultiByte(nCP, 0, sz, cch, (LPSTR) pb, cb, NULL, NULL);
  369. // if the Mac code page we wanted isn't available, try using our hard-coded tables
  370. if (fAttemptTranslate)
  371. TranslateBuffer((LPSTR) pb, cb);
  372. }
  373. if (fPascal) {
  374. WriteByte((char)cb);
  375. WriteBuffer((LPSTR) rgb, (USHORT)cb);
  376. } else {
  377. // at worst, we'll need one wide char for every single-byte char, plus a null terminator
  378. if (((cb + 1) * sizeof(WCHAR)) > sizeof(rgbExpand))
  379. pbExpand = (BYTE *) MyAlloc((cb + 1) * sizeof(WCHAR));
  380. cb = ExpandString(pb, cb, pbExpand);
  381. WriteBuffer((LPSTR) pbExpand, (USHORT)cb);
  382. if (pbExpand != rgbExpand)
  383. MyFree(pbExpand);
  384. }
  385. if (pb != rgb)
  386. MyFree(pb);
  387. }
  388. unsigned char* mpchchCodePage;
  389. unsigned char mpchchLatin1ToMac[128] = {
  390. 0x3f, /* 0x80 */
  391. 0x3f, /* 0x81 */
  392. 0xe2, /* 0x82 */
  393. 0xc4, /* 0x83 */
  394. 0xe3, /* 0x84 */
  395. 0xc9, /* 0x85 */
  396. 0xa0, /* 0x86 */
  397. 0xe0, /* 0x87 */
  398. 0xf6, /* 0x88 */
  399. 0xe4, /* 0x89 */
  400. 0x3f, /* 0x8a */
  401. 0xdc, /* 0x8b */
  402. 0xce, /* 0x8c */
  403. 0x3f, /* 0x8d */
  404. 0x3f, /* 0x8e */
  405. 0x3f, /* 0x8f */
  406. 0x3f, /* 0x90 */
  407. 0xd4, /* 0x91 */
  408. 0xd5, /* 0x92 */
  409. 0xd2, /* 0x93 */
  410. 0xd3, /* 0x94 */
  411. 0xa5, /* 0x95 */
  412. 0xd0, /* 0x96 */
  413. 0xd1, /* 0x97 */
  414. 0xf7, /* 0x98 */
  415. 0x84, /* 0x99 */
  416. 0x3f, /* 0x9a */
  417. 0xdd, /* 0x9b */
  418. 0xcf, /* 0x9c */
  419. 0x3f, /* 0x9d */
  420. 0x3f, /* 0x9e */
  421. 0xd9, /* 0x9f */
  422. 0xca, /* 0xa0 */
  423. 0xc1, /* 0xa1 */
  424. 0xa2, /* 0xa2 */
  425. 0xa3, /* 0xa3 */
  426. 0xdb, /* 0xa4 */
  427. 0xb4, /* 0xa5 */
  428. 0x3f, /* 0xa6 */
  429. 0xa4, /* 0xa7 */
  430. 0xac, /* 0xa8 */
  431. 0xa9, /* 0xa9 */
  432. 0xbb, /* 0xaa */
  433. 0xc7, /* 0xab */
  434. 0xc2, /* 0xac */
  435. 0x3f, /* 0xad */
  436. 0xa8, /* 0xae */
  437. 0x3f, /* 0xaf */
  438. 0xa1, /* 0xb0 */
  439. 0xb1, /* 0xb1 */
  440. 0x3f, /* 0xb2 */
  441. 0x3f, /* 0xb3 */
  442. 0xab, /* 0xb4 */
  443. 0xb5, /* 0xb5 */
  444. 0xa6, /* 0xb6 */
  445. 0xe1, /* 0xb7 */
  446. 0xfc, /* 0xb8 */
  447. 0x3f, /* 0xb9 */
  448. 0xbc, /* 0xba */
  449. 0xc8, /* 0xbb */
  450. 0x3f, /* 0xbc */
  451. 0x3f, /* 0xbd */
  452. 0x3f, /* 0xbe */
  453. 0xc0, /* 0xbf */
  454. 0xcb, /* 0xc0 */
  455. 0xe7, /* 0xc1 */
  456. 0xe5, /* 0xc2 */
  457. 0xcc, /* 0xc3 */
  458. 0x80, /* 0xc4 */
  459. 0x81, /* 0xc5 */
  460. 0xae, /* 0xc6 */
  461. 0x82, /* 0xc7 */
  462. 0xe9, /* 0xc8 */
  463. 0x83, /* 0xc9 */
  464. 0xe6, /* 0x3f */
  465. 0xe8, /* 0xcb */
  466. 0xed, /* 0xcc */
  467. 0xea, /* 0xcd */
  468. 0xeb, /* 0xce */
  469. 0xec, /* 0xcf */
  470. 0x3f, /* 0xd0 */
  471. 0x84, /* 0xd1 */
  472. 0xf1, /* 0xd2 */
  473. 0xee, /* 0xd3 */
  474. 0xef, /* 0xd4 */
  475. 0xcd, /* 0xd5 */
  476. 0x85, /* 0xd6 */
  477. 0x3f, /* 0xd7 */
  478. 0xaf, /* 0xd8 */
  479. 0x84, /* 0xd9 */
  480. 0xf2, /* 0xda */
  481. 0xf3, /* 0xdb */
  482. 0x86, /* 0xdc */
  483. 0x3f, /* 0xdd */
  484. 0x3f, /* 0xde */
  485. 0xa7, /* 0xdf */
  486. 0x88, /* 0xe0 */
  487. 0x87, /* 0xe1 */
  488. 0x89, /* 0xe2 */
  489. 0x8b, /* 0xe3 */
  490. 0x8a, /* 0xe4 */
  491. 0x8c, /* 0xe5 */
  492. 0xbe, /* 0xe6 */
  493. 0x8d, /* 0xe7 */
  494. 0x8f, /* 0xe8 */
  495. 0x8e, /* 0xe9 */
  496. 0x90, /* 0xea */
  497. 0x91, /* 0xeb */
  498. 0x93, /* 0xec */
  499. 0x92, /* 0xed */
  500. 0x94, /* 0xee */
  501. 0x95, /* 0xef */
  502. 0x3f, /* 0xf0 */
  503. 0x96, /* 0xf1 */
  504. 0x98, /* 0xf2 */
  505. 0x97, /* 0xf3 */
  506. 0x99, /* 0xf4 */
  507. 0x9b, /* 0xf5 */
  508. 0x9a, /* 0xf6 */
  509. 0xd6, /* 0xf7 */
  510. 0xbf, /* 0xf8 */
  511. 0x9d, /* 0xf9 */
  512. 0x9c, /* 0xfa */
  513. 0x9e, /* 0xfb */
  514. 0x9f, /* 0xfc */
  515. 0x3f, /* 0xfd */
  516. 0x3f, /* 0xfe */
  517. 0xd8, /* 0xff */
  518. };
  519. /*---------------------------------------------------------------------------*/
  520. /* */
  521. /* BuildCodePage() - */
  522. /* */
  523. /*---------------------------------------------------------------------------*/
  524. void
  525. BuildCodePage(
  526. int cp
  527. )
  528. {
  529. mpchchCodePage = cp == 1252 ? mpchchLatin1ToMac : NULL;
  530. }
  531. /*---------------------------------------------------------------------------*/
  532. /* */
  533. /* TranslateString() - */
  534. /* */
  535. /*---------------------------------------------------------------------------*/
  536. void
  537. TranslateString(
  538. char* sz
  539. )
  540. {
  541. TranslateBuffer(sz, strlen(sz)+1);
  542. }
  543. /*---------------------------------------------------------------------------*/
  544. /* */
  545. /* TranslateBuffer() - */
  546. /* */
  547. /*---------------------------------------------------------------------------*/
  548. void
  549. TranslateBuffer(
  550. char* rgch,
  551. int cch
  552. )
  553. {
  554. if (mpchchCodePage == NULL)
  555. BuildCodePage(uiCodePage);
  556. if (mpchchCodePage == NULL)
  557. return;
  558. for (NULL; cch > 0; rgch++, cch--)
  559. if (*rgch & 0x80)
  560. *rgch = (char)mpchchCodePage[(unsigned char)(*rgch-0x80)];
  561. }
  562. /*---------------------------------------------------------------------------*/
  563. /* */
  564. /* ExpandString() - */
  565. /* */
  566. /*---------------------------------------------------------------------------*/
  567. int
  568. ExpandString(
  569. BYTE* pb,
  570. int cb,
  571. BYTE* pbExpand
  572. )
  573. {
  574. int cbWide = 2; // for null terminator
  575. while (cb > 0) {
  576. if (IsDBCSLeadByteEx(uiCodePage, *pb)) {
  577. *pbExpand++ = *pb++;
  578. cb--;
  579. } else {
  580. *pbExpand++ = 0;
  581. }
  582. *pbExpand++ = *pb++;
  583. cbWide += 2;
  584. cb--;
  585. }
  586. *(WORD*) pbExpand++ = L'\0';
  587. return cbWide;
  588. }
  589. /*---------------------------------------------------------------------------*/
  590. /* */
  591. /* AppendString() - */
  592. /* */
  593. /*---------------------------------------------------------------------------*/
  594. VOID
  595. AppendString(
  596. PWCHAR sz,
  597. BOOL fMacCP
  598. )
  599. {
  600. PWCHAR psz;
  601. /* add a string to the resource buffer */
  602. psz = (PWCHAR) (&CodeArray[CCount]);
  603. if (*(psz-1) == L'\0')
  604. CCount -= sizeof(WCHAR);
  605. WriteString(sz, fMacCP);
  606. }
  607. /*---------------------------------------------------------------------------*/
  608. /* */
  609. /* WriteAlign() - */
  610. /* */
  611. /*---------------------------------------------------------------------------*/
  612. VOID
  613. WriteAlign(
  614. VOID
  615. )
  616. {
  617. WORD i = CCount % 4;
  618. while (i--)
  619. WriteByte(0);
  620. }
  621. /*---------------------------------------------------------------------------*/
  622. /* */
  623. /* WriteBuffer() - */
  624. /* */
  625. /*---------------------------------------------------------------------------*/
  626. VOID
  627. WriteBuffer(
  628. PCHAR pb,
  629. USHORT cb
  630. )
  631. {
  632. while (cb--) {
  633. WriteByte(*pb++);
  634. }
  635. }
  636. /*--------------------------------------------------------------------------*/
  637. /* */
  638. /* WriteControl() - */
  639. /* */
  640. /* Parameters: */
  641. /* outfh : The handle of the RES file. */
  642. /* Array : Pointer to array from which some data is to be copied into */
  643. /* the .RES file. */
  644. /* This is ignored if ArrayCount is zero. */
  645. /* ArrayCount : This is the number of bytes to be copied from "Array" */
  646. /* into the .RES file. This is zero if no copy is required*/
  647. /* FileCount : This specifies the number of bytes to be copied from */
  648. /* fhCode into fhOut. If this is -1, the complete input */
  649. /* file is to be copied into fhOut. */
  650. /**/
  651. /**/
  652. int
  653. WriteControl(
  654. PFILE outfh,
  655. PCHAR Array,
  656. int ArrayCount,
  657. LONG FileCount
  658. )
  659. {
  660. /* Check if the Array is to be written to .RES file */
  661. if (ArrayCount > 0)
  662. /* write the array (resource) to .RES file */
  663. MyWrite(outfh, Array, ArrayCount);
  664. /* copy the extra input file - opened by generator functions */
  665. if (fhCode != NULL_FILE) {
  666. /* Check if the complete input file is to be copied or not */
  667. if (FileCount == -1) {
  668. MyCopyAll(fhCode, outfh);
  669. fclose(fhCode);
  670. } else {
  671. /* Only a part of the input file is to be copied */
  672. MyCopy(fhCode, outfh, FileCount);
  673. /* Note that the fhCode is NOT closed in this case */
  674. }
  675. }
  676. return(ArrayCount);
  677. }
  678. /*---------------------------------------------------------------------------*/
  679. /* */
  680. /* ResourceSize() - */
  681. /* */
  682. /*---------------------------------------------------------------------------*/
  683. LONG
  684. ResourceSize (
  685. VOID
  686. )
  687. {
  688. if (fhCode == NULL_FILE)
  689. return (LONG)CCount; /* return size of array */
  690. else {
  691. /* note: currently all resources that use the fhCode file
  692. * compute their own resource sizes, and this shouldn't get
  693. * executed, but it is here in case of future modifications
  694. * which require it.
  695. */
  696. LONG lFPos = MySeek(fhCode, 0L, SEEK_CUR);
  697. LONG lcb = (LONG)CCount + MySeek(fhCode, 0L, SEEK_END) - lFPos;
  698. MySeek(fhCode, lFPos, SEEK_SET);
  699. return lcb;
  700. }
  701. }
  702. /*---------------------------------------------------------------------------*/
  703. /* */
  704. /* GetIcon() - */
  705. /* */
  706. /*---------------------------------------------------------------------------*/
  707. DWORD
  708. GetIcon(
  709. LONG nbyFile
  710. )
  711. {
  712. PFILE infh = CtlFile(NULL_FILE);
  713. IconHeader header;
  714. LONG nbyIconSize, nSeekLoc;
  715. LONG nbyTransferred = 0;
  716. SHORT IconID;
  717. int bHeaderWritten = FALSE;
  718. if (infh == NULL)
  719. return FALSE;
  720. /* read the header and find its size */
  721. if (!MyRead( infh, (PCHAR)&IconID, sizeof(SHORT))) {
  722. GenError2(2169, (PCHAR)tokenbuf); //"Resource file %ws is not in 2.03 format."
  723. return FALSE;
  724. }
  725. /* Check if the input file is in correct format */
  726. if (((CHAR)IconID != 1) && ((CHAR)IconID != 3))
  727. GenError2(2169, (PCHAR)tokenbuf); //"Resource file %ws is not in 2.03 format."
  728. if (!MyRead( infh, (PCHAR)(IconHeader *) &header, sizeof(IconHeader))) {
  729. GenError2(2169, (PCHAR)tokenbuf); //"Resource file %ws is not in 2.03 format."
  730. return FALSE;
  731. }
  732. nbyIconSize = (header.csWidthBytes * 2) * header.csHeight;
  733. /* if pre-shrunk version exists at eof */
  734. if ((nSeekLoc = ( sizeof (SHORT) + nbyIconSize + sizeof(IconHeader))) < nbyFile) {
  735. /* mark as device dependant */
  736. *(((PCHAR)&IconID) + 1) = 0;
  737. MySeek(infh, (LONG)nSeekLoc, SEEK_SET);
  738. WriteWord(IconID);
  739. } else { /* only canonical version exists */
  740. *(((PCHAR)&IconID) + 1) = 1; /* mark as device independent */
  741. WriteWord(IconID);
  742. WriteBuffer((PCHAR)&header, sizeof(IconHeader));
  743. bHeaderWritten = TRUE;
  744. }
  745. nbyTransferred = nbyFile - MySeek(infh, 0L, SEEK_CUR);
  746. /* return number of bytes in the temporary file */
  747. return (nbyTransferred + (bHeaderWritten ? sizeof(IconHeader) : 0)
  748. + sizeof(SHORT));
  749. }
  750. /*--------------------------------------------------------------------------*/
  751. /* */
  752. /* GetNewBitmap() - */
  753. /* */
  754. /* This loads the new bitmaps in DIB format (PM format) */
  755. /*--------------------------------------------------------------------------*/
  756. DWORD
  757. GetNewBitmap(
  758. VOID
  759. )
  760. {
  761. PFILE infh = CtlFile(NULL_FILE);
  762. BITMAPFILEHEADER bf;
  763. BITMAPCOREHEADER bc;
  764. BITMAPINFOHEADER *pBitMapInfo;
  765. int cbColorTable;
  766. PCHAR pColorTable;
  767. LONG cbImage;
  768. int nbits;
  769. DWORD BitmapSize;
  770. if (infh == NULL)
  771. return FALSE;
  772. MyRead(infh, (PCHAR)&bf, sizeof(bf));
  773. /* Check if it is in correct format */
  774. if (bf.bfType != DIBBITMAPFORMAT)
  775. GenError2(2170, (PCHAR)tokenbuf); //"Bitmap file %ws is not in 3.00 format."
  776. /* get the header -- assume old format */
  777. MyRead(infh, (PCHAR)&bc, sizeof(bc));
  778. BitmapSize = bc.bcSize;
  779. if (BitmapSize >= sizeof(BITMAPINFOHEADER)) {
  780. /* V3 or better format */
  781. pBitMapInfo = (BITMAPINFOHEADER *) MyAlloc(BitmapSize);
  782. memcpy(pBitMapInfo, &bc, sizeof(bc));
  783. MyRead(infh, ((PCHAR)pBitMapInfo) + sizeof(bc), BitmapSize - sizeof(bc));
  784. nbits = pBitMapInfo->biPlanes * pBitMapInfo->biBitCount;
  785. if ( pBitMapInfo->biCompression == BI_BITFIELDS ) {
  786. if( (pBitMapInfo->biBitCount <= 8) ||
  787. (pBitMapInfo->biBitCount == 24) )
  788. {
  789. GenError2(2170, (PCHAR)tokenbuf); //"Bitmap file %ws is not in 3.00 format."
  790. }
  791. cbColorTable = 3 * sizeof(DWORD);
  792. } else {
  793. // Only pBitMapInfo->biBitCount 1,4,8,24. biBitCount 16 and 32 MUST have BI_BITFIELD specified
  794. cbColorTable = (int)pBitMapInfo->biClrUsed * sizeof(RGBQUAD);
  795. if ((cbColorTable == 0) && (pBitMapInfo->biBitCount<=8))
  796. cbColorTable = (1 << nbits) * sizeof(RGBQUAD);
  797. }
  798. if (fMacRsrcs) {
  799. pBitMapInfo->biSize = SwapLong(pBitMapInfo->biSize);
  800. pBitMapInfo->biWidth = SwapLong(pBitMapInfo->biWidth);
  801. pBitMapInfo->biHeight = SwapLong(pBitMapInfo->biHeight);
  802. pBitMapInfo->biPlanes = SwapWord(pBitMapInfo->biPlanes);
  803. pBitMapInfo->biBitCount = SwapWord(pBitMapInfo->biBitCount);
  804. pBitMapInfo->biCompression = SwapLong(pBitMapInfo->biCompression);
  805. pBitMapInfo->biSizeImage = SwapLong(pBitMapInfo->biSizeImage);
  806. pBitMapInfo->biXPelsPerMeter = SwapLong(pBitMapInfo->biXPelsPerMeter);
  807. pBitMapInfo->biYPelsPerMeter = SwapLong(pBitMapInfo->biYPelsPerMeter);
  808. pBitMapInfo->biClrUsed = SwapLong(pBitMapInfo->biClrUsed);
  809. pBitMapInfo->biClrImportant = SwapLong(pBitMapInfo->biClrImportant);
  810. }
  811. WriteBuffer((PCHAR)pBitMapInfo, (USHORT)BitmapSize);
  812. MyFree(pBitMapInfo);
  813. } else if (BitmapSize == sizeof(BITMAPCOREHEADER)) {
  814. nbits = bc.bcPlanes * bc.bcBitCount;
  815. /* old format */
  816. if (nbits == 24)
  817. cbColorTable = 0;
  818. else
  819. cbColorTable = (1 << nbits) * sizeof(RGBTRIPLE);
  820. if (fMacRsrcs) {
  821. bc.bcSize = SwapLong(bc.bcSize);
  822. bc.bcWidth = SwapWord(bc.bcWidth);
  823. bc.bcHeight = SwapWord(bc.bcHeight);
  824. bc.bcPlanes = SwapWord(bc.bcPlanes);
  825. bc.bcBitCount = SwapWord(bc.bcBitCount);
  826. }
  827. WriteBuffer((PCHAR)&bc, (USHORT)BitmapSize);
  828. } else {
  829. GenError1(2171); //"Unknown DIB header format"
  830. }
  831. if (cbColorTable) {
  832. pColorTable = (PCHAR) MyAlloc(cbColorTable);
  833. MyRead(infh, pColorTable, cbColorTable);
  834. WriteBuffer(pColorTable, (USHORT)cbColorTable);
  835. MyFree(pColorTable);
  836. }
  837. /* get the length of the bits */
  838. cbImage = MySeek(infh, 0L, SEEK_END) - BFOFFBITS(&bf) + BitmapSize + cbColorTable;
  839. /* seek to the beginning of the bits... */
  840. MySeek(infh, BFOFFBITS(&bf), SEEK_SET);
  841. return cbImage;
  842. }
  843. VOID
  844. WriteOrdCode(
  845. void
  846. )
  847. {
  848. WriteWord(0xFFFF);
  849. }
  850. /*---------------------------------------------------------------------------*/
  851. /* */
  852. /* SetUpDlg() - */
  853. /* */
  854. /*---------------------------------------------------------------------------*/
  855. VOID
  856. SetUpDlg(
  857. PDLGHDR pDlg,
  858. BOOL fDlgEx
  859. )
  860. {
  861. if (fDlgEx) {
  862. // Hack -- this is how we version switch the dialog
  863. WriteWord(0x0001); // store wDlgVer
  864. WriteWord(0xFFFF); // store wSignature
  865. WriteLong(pDlg->dwHelpID);
  866. WriteLong(pDlg->dwExStyle); // store exstyle
  867. }
  868. /* write the style bits to the resource buffer */
  869. WriteLong(pDlg->dwStyle); /* store style */
  870. if (!fDlgEx)
  871. WriteLong(pDlg->dwExStyle); /* store exstyle */
  872. ItemCountLoc = CCount; /* global marker for location of item cnt. */
  873. /* skip place for num of items */
  874. WriteWord(0);
  875. /* output the dialog position and size */
  876. WriteWord(pDlg->x);
  877. WriteWord(pDlg->y);
  878. WriteWord(pDlg->cx);
  879. WriteWord(pDlg->cy);
  880. /* output the menu identifier */
  881. if (pDlg->fOrdinalMenu) {
  882. WriteOrdCode();
  883. WriteWord((USHORT)wcsatoi(pDlg->MenuName));
  884. } else {
  885. WriteString(pDlg->MenuName, FALSE);
  886. }
  887. /* output the class identifier */
  888. if (pDlg->fClassOrdinal) {
  889. WriteOrdCode();
  890. WriteWord((USHORT)wcsatoi(pDlg->Class));
  891. } else {
  892. WriteString(pDlg->Class, FALSE);
  893. }
  894. /* output the title */
  895. WriteString(pDlg->Title, TRUE);
  896. /* add the font information */
  897. if (pDlg->pointsize) {
  898. WriteWord(pDlg->pointsize);
  899. if (fDlgEx) {
  900. WriteWord(pDlg->wWeight);
  901. WriteByte(pDlg->bItalic);
  902. WriteByte(pDlg->bCharSet);
  903. }
  904. WriteString(pDlg->Font, FALSE);
  905. }
  906. }
  907. /*---------------------------------------------------------------------------*/
  908. /* */
  909. /* SetUpItem() - */
  910. /* */
  911. /*---------------------------------------------------------------------------*/
  912. VOID
  913. SetUpItem(
  914. PCTRL LocCtl,
  915. BOOL fDlgEx
  916. )
  917. {
  918. PWCHAR tempptr;
  919. /* control dimensions, id, and style bits */
  920. WriteAlign();
  921. // control dimensions, id, and style bits
  922. if (fDlgEx) {
  923. WriteLong(LocCtl->dwHelpID);
  924. WriteLong(LocCtl->dwExStyle);
  925. WriteLong(LocCtl->dwStyle);
  926. } else {
  927. WriteLong(LocCtl->dwStyle);
  928. WriteLong(LocCtl->dwExStyle);
  929. }
  930. WriteWord(LocCtl->x);
  931. WriteWord(LocCtl->y);
  932. WriteWord(LocCtl->cx);
  933. WriteWord(LocCtl->cy);
  934. if (fDlgEx)
  935. WriteLong(LocCtl->id);
  936. else
  937. WriteWord(LOWORD(LocCtl->id));
  938. /* control class */
  939. tempptr = LocCtl->Class;
  940. if (*tempptr == 0xFFFF) {
  941. /* special class code follows */
  942. WriteWord(*tempptr++);
  943. WriteWord(*tempptr++);
  944. } else {
  945. WriteString(tempptr, FALSE);
  946. }
  947. /* text */
  948. if (LocCtl->fOrdinalText) {
  949. WriteOrdCode();
  950. WriteWord((USHORT)wcsatoi(LocCtl->text));
  951. } else {
  952. WriteString(LocCtl->text, TRUE);
  953. }
  954. if (fDlgEx)
  955. ItemExtraLoc = CCount;
  956. WriteWord(0); /* zero CreateParams count */
  957. IncItemCount();
  958. }
  959. void
  960. SetItemExtraCount(
  961. WORD wCount,
  962. BOOL fDlgEx
  963. )
  964. {
  965. if (fDlgEx)
  966. *((WORD *) (CodeArray + ItemExtraLoc)) = wCount;
  967. }
  968. /*---------------------------------------------------------------------------*/
  969. /* */
  970. /* IncItemCount() - */
  971. /* */
  972. /*---------------------------------------------------------------------------*/
  973. /* seemingly obscure way to increment # of items in a dialog */
  974. /* ItemCountLoc indexes where we put the item count in the resource buffer, */
  975. /* so we increment that counter when we add a control */
  976. VOID
  977. IncItemCount(
  978. VOID
  979. )
  980. {
  981. PUSHORT pus;
  982. pus = (PUSHORT)&CodeArray[ItemCountLoc];
  983. (*pus)++;
  984. }
  985. /*---------------------------------------------------------------------------*/
  986. /* */
  987. /* SwapItemCount() - */
  988. /* */
  989. /*---------------------------------------------------------------------------*/
  990. /* when writing a Mac resource fork, we need to swap this count before writing */
  991. VOID
  992. SwapItemCount(
  993. VOID
  994. )
  995. {
  996. PUSHORT pus;
  997. pus = (PUSHORT)&CodeArray[ItemCountLoc];
  998. *pus = SwapWord(*pus);
  999. }
  1000. /*---------------------------------------------------------------------------*/
  1001. /* */
  1002. /* FixMenuPatch() - */
  1003. /* */
  1004. /*---------------------------------------------------------------------------*/
  1005. VOID
  1006. FixMenuPatch(
  1007. WORD wEndFlagLoc
  1008. )
  1009. {
  1010. if (fMacRsrcs)
  1011. CodeArray[wEndFlagLoc + 1] |= MFR_END;
  1012. else
  1013. *((PWORD) (CodeArray + wEndFlagLoc)) |= MFR_END;
  1014. // mark last menu item
  1015. // CodeArray[wEndFlagLoc] |= MFR_END;
  1016. }
  1017. VOID
  1018. FixOldMenuPatch(
  1019. WORD wEndFlagLoc
  1020. )
  1021. {
  1022. // mark last menu item
  1023. if (fMacRsrcs)
  1024. CodeArray[wEndFlagLoc + 1] |= OPENDMENU;
  1025. else
  1026. CodeArray[wEndFlagLoc] |= OPENDMENU;
  1027. }
  1028. /*---------------------------------------------------------------------------*/
  1029. /* */
  1030. /* MarkAccelFlagsByte() - */
  1031. /* */
  1032. /*---------------------------------------------------------------------------*/
  1033. /* set the place where the accel end bit is going to be set */
  1034. VOID
  1035. MarkAccelFlagsByte (
  1036. VOID
  1037. )
  1038. {
  1039. /* set the location to the current position in the resource buffer */
  1040. mnEndFlagLoc = CCount;
  1041. }
  1042. /*---------------------------------------------------------------------------*/
  1043. /* */
  1044. /* PatchAccelEnd() - */
  1045. /* */
  1046. /*---------------------------------------------------------------------------*/
  1047. VOID
  1048. PatchAccelEnd (
  1049. VOID
  1050. )
  1051. {
  1052. if (fMacRsrcs)
  1053. CodeArray[mnEndFlagLoc + 1] |= 0x80;
  1054. else
  1055. CodeArray[mnEndFlagLoc] |= 0x80;
  1056. }
  1057. // ----------------------------------------------------------------------------
  1058. //
  1059. // SetUpMenu() -
  1060. //
  1061. // ----------------------------------------------------------------------------
  1062. WORD
  1063. SetUpMenu(
  1064. PMENU pmn
  1065. )
  1066. {
  1067. WORD wRes;
  1068. WriteLong(pmn->dwType);
  1069. WriteLong(pmn->dwState);
  1070. WriteLong(pmn->dwID);
  1071. // mark the last item added to the menu
  1072. wRes = (WORD)CCount;
  1073. WriteWord(pmn->wResInfo);
  1074. WriteString(pmn->szText, TRUE);
  1075. if (32)
  1076. WriteAlign();
  1077. if (pmn->wResInfo & MFR_POPUP)
  1078. WriteLong(pmn->dwHelpID);
  1079. return(wRes);
  1080. }
  1081. // ----------------------------------------------------------------------------
  1082. //
  1083. // SetUpOldMenu() -
  1084. //
  1085. // ----------------------------------------------------------------------------
  1086. WORD
  1087. SetUpOldMenu(
  1088. PMENUITEM mnTemp
  1089. )
  1090. {
  1091. WORD wRes;
  1092. /* mark the last item added to the menu */
  1093. wRes = (WORD)CCount;
  1094. /* write the menu flags */
  1095. WriteWord(mnTemp->OptFlags);
  1096. /* popup menus don't have id values */
  1097. /* write ids of menuitems */
  1098. if (!((mnTemp->OptFlags) & OPPOPUP))
  1099. WriteWord(mnTemp->id);
  1100. /* write text of selection */
  1101. WriteString(mnTemp->szText, TRUE);
  1102. return(wRes);
  1103. }
  1104. /*---------------------------------------------------------------------------*/
  1105. /* */
  1106. /* GetRCData() - */
  1107. /* */
  1108. /*---------------------------------------------------------------------------*/
  1109. WORD
  1110. GetRCData (
  1111. PRESINFO pRes
  1112. )
  1113. {
  1114. PCHAR pch, pchT;
  1115. PWCHAR pwch;
  1116. WORD nBytes = 0;
  1117. ULONG cb = 0;
  1118. /* look for BEGIN (after id RCDATA memflags) */
  1119. // 2134 -- "BEGIN expected in RCData"
  1120. PreBeginParse(pRes, 2134);
  1121. /* add the users data to the resource buffer until we see an END */
  1122. while (token.type != END) {
  1123. /* see explanation in rcl.c in GetStr() */
  1124. if (token.type == LSTRLIT)
  1125. token.type = token.realtype;
  1126. switch (token.type) {
  1127. case LSTRLIT:
  1128. pwch = tokenbuf;
  1129. while (token.val--) {
  1130. WriteWord(*pwch++);
  1131. nBytes += sizeof(WCHAR);
  1132. }
  1133. break;
  1134. case STRLIT:
  1135. cb = WideCharToMultiByte(uiCodePage, 0, tokenbuf,
  1136. token.val, NULL, 0, NULL, NULL);
  1137. pchT = pch = (PCHAR) MyAlloc(cb);
  1138. WideCharToMultiByte(uiCodePage, 0, tokenbuf,
  1139. token.val, pch, cb, NULL, NULL);
  1140. while (cb--) {
  1141. WriteByte(*pch++);
  1142. nBytes += sizeof(CHAR);
  1143. }
  1144. MyFree(pchT);
  1145. break;
  1146. case NUMLIT:
  1147. if (token.flongval) {
  1148. WriteLong(token.longval);
  1149. nBytes += sizeof(LONG);
  1150. } else {
  1151. WriteWord(token.val);
  1152. nBytes += sizeof(WORD);
  1153. }
  1154. break;
  1155. default:
  1156. ParseError1(2164);
  1157. return 0;
  1158. }
  1159. ICGetTok();
  1160. }
  1161. return(nBytes);
  1162. }
  1163. /*---------------------------------------------------------------------------*/
  1164. /* */
  1165. /* AddFontRes() - */
  1166. /* */
  1167. /*---------------------------------------------------------------------------*/
  1168. BOOL
  1169. AddFontRes(
  1170. PRESINFO pRes
  1171. )
  1172. {
  1173. PFILE fpFont;
  1174. BYTE font[FONT_ALL];
  1175. PCHAR pEnd, pDev, pFace;
  1176. DWORD offset;
  1177. SHORT nbyFont;
  1178. PFONTDIR pFont;
  1179. PFONTDIR pFontSearch;
  1180. /* get handle to font file */
  1181. fpFont = CtlFile(NULL_FILE);
  1182. if (fpFont == NULL)
  1183. return FALSE;
  1184. MySeek(fpFont, 0L, SEEK_SET);
  1185. /* copy font information to the font directory */
  1186. /* name strings are ANSI (8-bit) */
  1187. MyRead(fpFont, (PCHAR)&font[0], sizeof(ffh));
  1188. pEnd = (PCHAR) (&font[0] + sizeof(ffh)); /* pointer to end of font buffer */
  1189. offset = ((ffh * )(&font[0]))->dfDevice;
  1190. if (offset != (LONG)0) {
  1191. MySeek(fpFont, (LONG)offset, SEEK_SET); /* seek to device name */
  1192. pDev = pEnd;
  1193. do {
  1194. MyRead( fpFont, pEnd, 1); /* copy device name */
  1195. } while (*pEnd++);
  1196. } else {
  1197. (*pEnd++ = '\0');
  1198. }
  1199. offset = ((ffh * )(&font[0]))->dfFace;
  1200. MySeek(fpFont, (LONG)offset, SEEK_SET); /* seek to face name */
  1201. pFace = pEnd;
  1202. do { /* copy face name */
  1203. MyRead( fpFont, pEnd, 1);
  1204. } while (*pEnd++);
  1205. nbyFont = (SHORT)(pEnd - (PCHAR) &font[0]);
  1206. pFont = (FONTDIR * )MyAlloc(sizeof(FONTDIR) + nbyFont);
  1207. pFont->nbyFont = nbyFont;
  1208. pFont->ordinal = pRes->nameord;
  1209. pFont->next = NULL;
  1210. memcpy((PCHAR)(pFont + 1), (PCHAR)font, nbyFont);
  1211. if (!nFontsRead) {
  1212. pFontList = pFontLast = pFont;
  1213. } else {
  1214. for (pFontSearch=pFontList ; pFontSearch!=NULL ; pFontSearch=pFontSearch->next) {
  1215. if (pFont->ordinal == pFontSearch->ordinal) {
  1216. SET_MSG(Msg_Text, sizeof(Msg_Text), GET_MSG(2181), curFile, token.row, pFont->ordinal);
  1217. SendError(Msg_Text);
  1218. MyFree(pFont);
  1219. return FALSE;
  1220. }
  1221. }
  1222. pFontLast = pFontLast->next = pFont;
  1223. }
  1224. /* rewind font file for SaveResFile() */
  1225. MySeek(fpFont, 0L, SEEK_SET);
  1226. return TRUE;
  1227. }
  1228. /*--------------------------------------------------------------------------*/
  1229. /* */
  1230. /* SaveResFile() - */
  1231. /* */
  1232. /*--------------------------------------------------------------------------*/
  1233. VOID
  1234. SaveResFile(
  1235. PTYPEINFO pType,
  1236. PRESINFO pRes
  1237. )
  1238. {
  1239. if (!fMacRsrcs)
  1240. MyAlign(fhBin);
  1241. AddResToResFile(pType, pRes, CodeArray, CCount, -1L);
  1242. }
  1243. /*--------------------------------------------------------------------------*/
  1244. /* */
  1245. /* GetNewIconsCursors(ResType) */
  1246. /* */
  1247. /* This reads all the different forms of icons/cursors in 3.00 format */
  1248. /* in the input file */
  1249. /* */
  1250. /*--------------------------------------------------------------------------*/
  1251. VOID
  1252. GetNewIconsCursors(
  1253. PTYPEINFO pGroupType,
  1254. PRESINFO pGroupRes,
  1255. LPWSTR ResType
  1256. )
  1257. {
  1258. static SHORT idIconUnique = 1;
  1259. UINT i;
  1260. LONG DescOffset;
  1261. PTYPEINFO pType;
  1262. PRESINFO pRes;
  1263. NEWHEADER NewHeader;
  1264. DESCRIPTOR Descriptor;
  1265. BITMAPHEADER BitMapHeader;
  1266. RESDIR ResDir;
  1267. int ArrayCount = 0;
  1268. LOCALHEADER LocHeader;
  1269. /* Read the header of the bitmap file */
  1270. MyRead(fhCode, (PCHAR)&NewHeader, sizeof(NEWHEADER));
  1271. /* Check if the file is in correct format */
  1272. if ((NewHeader.Reserved != 0) || ((NewHeader.ResType != 1) && (NewHeader.ResType != 2)))
  1273. GenError2(2175, (PCHAR)tokenbuf); //"Resource file %ws is not in 3.00 format."
  1274. /* Write the header into the Code array */
  1275. WriteBuffer((PCHAR)&NewHeader, sizeof(NEWHEADER));
  1276. /* Process all the forms one by one */
  1277. for (i = 0; i < NewHeader.ResCount; i++) {
  1278. /* Readin the Descriptor */
  1279. MyRead(fhCode, (PCHAR)&Descriptor, sizeof(DESCRIPTOR));
  1280. /* Save the current offset */
  1281. DescOffset = MySeek(fhCode, 0L, SEEK_CUR);
  1282. /* Seek to the Data */
  1283. MySeek(fhCode, Descriptor.OffsetToBits, SEEK_SET);
  1284. /* Get the bitcount and Planes data */
  1285. MyRead(fhCode, (PCHAR)&BitMapHeader, sizeof(BITMAPHEADER));
  1286. if (BitMapHeader.biSize != sizeof(BITMAPHEADER))
  1287. GenError2(2176, (PCHAR)tokenbuf); //"Old DIB in %ws. Pass it through SDKPAINT."
  1288. ResDir.BitCount = BitMapHeader.biBitCount;
  1289. ResDir.Planes = BitMapHeader.biPlanes;
  1290. /* Seek to the Data */
  1291. MySeek(fhCode, Descriptor.OffsetToBits, SEEK_SET);
  1292. ArrayCount = 0;
  1293. /* fill the fields of ResDir and LocHeader */
  1294. switch (NewHeader.ResType) {
  1295. case CURSORTYPE:
  1296. LocHeader.xHotSpot = Descriptor.xHotSpot;
  1297. LocHeader.yHotSpot = Descriptor.yHotSpot;
  1298. ArrayCount = sizeof(LOCALHEADER);
  1299. ResDir.ResInfo.Cursor.Width = (USHORT)BitMapHeader.biWidth;
  1300. ResDir.ResInfo.Cursor.Height = (USHORT)BitMapHeader.biHeight;
  1301. break;
  1302. case ICONTYPE:
  1303. ResDir.ResInfo.Icon.Width = Descriptor.Width;
  1304. ResDir.ResInfo.Icon.Height = Descriptor.Height;
  1305. ResDir.ResInfo.Icon.ColorCount = Descriptor.ColorCount;
  1306. /* The following line is added to initialise the unused
  1307. * field "reserved".
  1308. * Fix for Bug #10382 --SANKAR-- 03-14-90
  1309. */
  1310. ResDir.ResInfo.Icon.reserved = Descriptor.reserved;
  1311. break;
  1312. }
  1313. ResDir.BytesInRes = Descriptor.BytesInRes + ArrayCount;
  1314. /* Create a pRes with New name */
  1315. pRes = (PRESINFO) MyAlloc(sizeof(RESINFO));
  1316. pRes->language = language;
  1317. pRes->version = version;
  1318. pRes->characteristics = characteristics;
  1319. pRes ->name = NULL;
  1320. pRes ->nameord = idIconUnique++;
  1321. /* The individual resources must have the same memory flags as the
  1322. ** group.
  1323. */
  1324. pRes ->flags = pGroupRes ->flags;
  1325. pRes ->size = Descriptor.BytesInRes + ArrayCount;
  1326. /* Create a new pType, or find existing one */
  1327. pType = AddResType(NULL, ResType);
  1328. /* Put Resource Directory entry in CodeArray */
  1329. WriteBuffer((PCHAR)&ResDir, sizeof(RESDIR));
  1330. /*
  1331. * Write the resource name ordinal.
  1332. */
  1333. WriteWord(pRes->nameord);
  1334. MyAlign(fhBin);
  1335. AddResToResFile(pType, pRes, (PCHAR)&LocHeader, ArrayCount,
  1336. Descriptor.BytesInRes);
  1337. /* Seek to the Next Descriptor */
  1338. MySeek(fhCode, DescOffset, SEEK_SET);
  1339. }
  1340. pGroupRes ->size = sizeof(NEWHEADER) + NewHeader.ResCount * (sizeof(RESDIR) + sizeof(SHORT));
  1341. /* If the group resource is marked as PRELOAD, then we should use
  1342. ** the same flags. Otherwise, mark it as DISCARDABLE
  1343. */
  1344. if (!(pGroupRes ->flags & NSPRELOAD))
  1345. pGroupRes ->flags = NSMOVE | NSPURE | NSDISCARD;
  1346. /* Close the input file, nothing more to read */
  1347. fclose(fhCode);
  1348. fhCode = NULL_FILE;
  1349. /* Copy the code array into RES file for Group items */
  1350. SaveResFile(pGroupType, pGroupRes);
  1351. }
  1352. /*--------------------------------------------------------------------------*/
  1353. /* */
  1354. /* FileIsAnimated(LONG nbyFile) */
  1355. /* */
  1356. /* This function checks to see if the file we have is 3.0 icon/cursor file */
  1357. /* or an animated icon/cursor. */
  1358. /* */
  1359. /* Returns RT_* of filetype. */
  1360. /*--------------------------------------------------------------------------*/
  1361. DWORD
  1362. FileIsAnimated(
  1363. LONG nbyFile
  1364. )
  1365. {
  1366. RTAG tag;
  1367. LONG lRead;
  1368. lRead = MyRead(fhCode, (PRTAG)&tag, sizeof(RTAG));
  1369. MySeek(fhCode, 0L, SEEK_SET); /* return to start of file */
  1370. if (lRead != sizeof(RTAG))
  1371. return FALSE;
  1372. return tag.ckID == FOURCC_RIFF;
  1373. }
  1374. /*--------------------------------------------------------------------------*/
  1375. /* */
  1376. /* GetAniIconsAniCursors(ResType) */
  1377. /* */
  1378. /* This function check if the file we have is a valid animated icon. */
  1379. /* All the work performed here is purelly optional and is done to make */
  1380. /* sure that the image we write in the res file is in the proper format. */
  1381. /* Just returning the nbyFile would be enough to copy the file in the res */
  1382. /* file. */
  1383. /* */
  1384. /*--------------------------------------------------------------------------*/
  1385. DWORD
  1386. GetAniIconsAniCursors(
  1387. LONG nbyFile
  1388. )
  1389. {
  1390. RTAG tag;
  1391. LONG lRead = nbyFile;
  1392. /* Check if we have a RIFF file */
  1393. lRead -= MyRead(fhCode, (PRTAG)&tag, sizeof(RTAG));
  1394. if( tag.ckID!=FOURCC_RIFF )
  1395. GenError2(2173, (PCHAR)tokenbuf);
  1396. /* Read the next chunk */
  1397. lRead -= MyRead(fhCode, (LPDWORD)&tag.ckID, sizeof(tag.ckID));
  1398. if( tag.ckID!=FOURCC_ACON )
  1399. GenError2(2173, (PCHAR)tokenbuf);
  1400. /* so we have an animated icon file, make sure all the blocks are there */
  1401. while( MyRead(fhCode, (PRTAG)&tag, sizeof(RTAG)) ) {
  1402. lRead -= sizeof(RTAG)+tag.ckSize;
  1403. MySeek(fhCode, tag.ckSize, SEEK_CUR);
  1404. }
  1405. if( lRead!=0 )
  1406. GenError2(2173, (PCHAR)tokenbuf);
  1407. /*
  1408. * Now that we are sure this is a valid file, move the
  1409. * file pointer back at the begining of the file.
  1410. */
  1411. MySeek(fhCode, 0L, SEEK_SET);
  1412. return nbyFile;
  1413. }
  1414. /* GetBufferLen
  1415. * Returns the current length of the buffer
  1416. */
  1417. WORD
  1418. GetBufferLen(
  1419. VOID
  1420. )
  1421. {
  1422. return (WORD)CCount;
  1423. }
  1424. USHORT
  1425. GetItemCount(
  1426. int Index
  1427. )
  1428. {
  1429. return *((USHORT UNALIGNED*)(CodeArray + Index));
  1430. }
  1431. void
  1432. SetItemCount(
  1433. int Index,
  1434. USHORT wCount
  1435. )
  1436. {
  1437. *((USHORT UNALIGNED*)(CodeArray + Index)) = wCount;
  1438. }
  1439. DWORD
  1440. SwapLong(
  1441. DWORD dw
  1442. )
  1443. {
  1444. return ((dw << 24) & 0xff000000L) |
  1445. ((dw << 8) & 0x00ff0000L) |
  1446. ((dw >> 8) & 0x0000ff00L) |
  1447. ((dw >> 24) & 0x000000ffL);
  1448. }
  1449. WORD
  1450. SwapWord(
  1451. WORD w
  1452. )
  1453. {
  1454. return ((w << 8) & 0xff00) |
  1455. ((w >> 8) & 0x00ff);
  1456. }
  1457. enum {
  1458. itNone = -1,
  1459. itIcn_ = 0,
  1460. itIcl4 = 1,
  1461. itIcl8 = 2,
  1462. itIcs_ = 3,
  1463. itIcs4 = 4,
  1464. itIcs8 = 5,
  1465. itIcm_ = 6,
  1466. itIcm4 = 7,
  1467. itIcm8 = 8,
  1468. itMax = 9
  1469. };
  1470. static DWORD mpitres[itMax] = {
  1471. 'ICN#',
  1472. 'icl4',
  1473. 'icl8',
  1474. 'ics#',
  1475. 'ics4',
  1476. 'ics8',
  1477. 'icm#',
  1478. 'icm4',
  1479. 'icm8'
  1480. };
  1481. enum {
  1482. fitIcn_ = 1 << itIcn_,
  1483. fitIcl4 = 1 << itIcl4,
  1484. fitIcl8 = 1 << itIcl8,
  1485. fitIcs_ = 1 << itIcs_,
  1486. fitIcs4 = 1 << itIcs4,
  1487. fitIcs8 = 1 << itIcs8,
  1488. fitIcm_ = 1 << itIcm_,
  1489. fitIcm4 = 1 << itIcm4,
  1490. fitIcm8 = 1 << itIcm8
  1491. };
  1492. void
  1493. GetMacIcon(
  1494. TYPEINFO *pType,
  1495. RESINFO *pRes
  1496. )
  1497. {
  1498. struct tagNEWHEADER gh;
  1499. struct tagDESCRIPTOR ds;
  1500. BITMAPINFOHEADER bmh;
  1501. int ibDescNext;
  1502. int mpitib[itMax];
  1503. int it;
  1504. int ires;
  1505. int fitFound;
  1506. /* The input file has already been opened; read in the bitmap file header */
  1507. MyRead(fhCode, (char*)&gh, sizeof(struct tagNEWHEADER));
  1508. if (gh.Reserved != 0 || gh.ResType != 1)
  1509. GenError2(2175, (PCHAR)tokenbuf);
  1510. /* run through all the icons, keeping track of the useful ones */
  1511. memset(mpitib, 0, sizeof(mpitib));
  1512. ibDescNext = MySeek(fhCode, 0L, SEEK_CUR);
  1513. fitFound = 0;
  1514. for (ires = 0; ires < gh.ResCount; ires++) {
  1515. /* Read in the descriptor */
  1516. MySeek(fhCode, ibDescNext, SEEK_SET);
  1517. MyRead(fhCode, (char*)&ds, sizeof(struct tagDESCRIPTOR));
  1518. ibDescNext = MySeek(fhCode, 0L, SEEK_CUR);
  1519. /* get bitmap header */
  1520. MySeek(fhCode, ds.OffsetToBits, SEEK_SET);
  1521. MyRead(fhCode, (char*)&bmh, sizeof(BITMAPINFOHEADER));
  1522. if (bmh.biSize != sizeof(BITMAPINFOHEADER))
  1523. GenError2(2176, (PCHAR)tokenbuf);
  1524. /* find valid color cases */
  1525. if (bmh.biPlanes != 1)
  1526. continue;
  1527. if (bmh.biBitCount == 1)
  1528. it = itIcn_;
  1529. else if (bmh.biBitCount == 4)
  1530. it = itIcl4;
  1531. else if (bmh.biBitCount == 8)
  1532. it = itIcl8;
  1533. else
  1534. continue;
  1535. /* find valid sizes */
  1536. if (bmh.biWidth == 16 && bmh.biHeight == 24)
  1537. it += itIcm_ - itIcn_;
  1538. else if (bmh.biWidth == 16 && bmh.biHeight == 32)
  1539. it += itIcs_ - itIcn_;
  1540. else if (bmh.biWidth == 32 && bmh.biHeight == 64)
  1541. it += itIcn_ - itIcn_;
  1542. else
  1543. continue;
  1544. /* mark sizes we found */
  1545. fitFound |= 1 << it;
  1546. mpitib[it] = ibDescNext - sizeof(struct tagDESCRIPTOR);
  1547. }
  1548. /* if no usable icon found, bail out */
  1549. if (fitFound == 0) {
  1550. GenWarning2(4508, (PCHAR)tokenbuf);
  1551. } else {
  1552. if (fitFound & (fitIcn_|fitIcl4|fitIcl8))
  1553. ProcessMacIcons(pRes, itIcn_, mpitib[itIcn_], mpitib[itIcl4], mpitib[itIcl8]);
  1554. if (fitFound & (fitIcs_|fitIcs4|fitIcs8))
  1555. ProcessMacIcons(pRes, itIcs_, mpitib[itIcs_], mpitib[itIcs4], mpitib[itIcs8]);
  1556. if (fitFound & (fitIcm_|fitIcm4|fitIcm8))
  1557. ProcessMacIcons(pRes, itIcm_, mpitib[itIcs_], mpitib[itIcs4], mpitib[itIcs8]);
  1558. }
  1559. fclose(fhCode);
  1560. fhCode = NULL_FILE;
  1561. }
  1562. int
  1563. Luminance(
  1564. RGBColor* prgb
  1565. )
  1566. {
  1567. return prgb->red/256*30 + prgb->green/256*59 + prgb->blue/256*11;
  1568. }
  1569. /* threshold = middle gray */
  1570. #define rThreshold 128
  1571. #define gThreshold 128
  1572. #define bThreshold 128
  1573. int lumThreshold = rThreshold*30 + gThreshold*59 + bThreshold*11;
  1574. void
  1575. ProcessMacIcons(
  1576. RESINFO* pResBase,
  1577. int itBase,
  1578. int ib1,
  1579. int ib4,
  1580. int ib8
  1581. )
  1582. {
  1583. BITMAPINFOHEADER bmh;
  1584. RGBQUAD* rgq;
  1585. struct tagDESCRIPTOR ds;
  1586. BYTE* pBits;
  1587. int cbWidth, cbMask;
  1588. int cbBits;
  1589. int ib, iq;
  1590. int y;
  1591. BYTE *pbIn;
  1592. BYTE* pbOut;
  1593. BYTE bIn, bOut;
  1594. /* create monochrome icon out of the best-looking icon */
  1595. if (ib1 != 0) {
  1596. /* read the DIB */
  1597. ReadDIB(ib1, &ds, &bmh, &cbWidth, (void **) &pBits, &rgq, TRUE);
  1598. /* invert bits, if color table is backwards */
  1599. if (rgq[0].rgbReserved != 0)
  1600. for (ib = cbWidth*bmh.biHeight/2; --ib >= 0; )
  1601. pBits[ib] ^= 0xff;
  1602. } else if (ib4 != 0) {
  1603. /* read the DIB and create color-to-mono color mapping */
  1604. ReadDIB(ib4, &ds, &bmh, &cbWidth, (void **) &pBits, &rgq, TRUE);
  1605. for (iq = 0; iq < (int)bmh.biClrUsed; iq++)
  1606. rgq[iq].rgbReserved =
  1607. Luminance(&rgcs16[rgq[iq].rgbReserved].rgb) < lumThreshold;
  1608. /* map colors to black and white and convert to 1-bit/pixel */
  1609. for (y = 0; y < (int)(bmh.biHeight/2); y++) {
  1610. pbIn = pBits + y*cbWidth;
  1611. pbOut = pbIn;
  1612. assert(cbWidth % 4 == 0); // we know it's 8 or 16 bytes wide
  1613. for (ib = 0; ib < cbWidth; ) {
  1614. bIn = *pbIn++;
  1615. bOut = (bOut<<1) | rgq[bIn>>4].rgbReserved;
  1616. bOut = (bOut<<1) | rgq[bIn&0xf].rgbReserved;
  1617. ib++;
  1618. if (ib % 4 == 0)
  1619. *pbOut++ = bOut;
  1620. }
  1621. }
  1622. } else {
  1623. /* read the DIB and create color-to-mono color mapping */
  1624. ReadDIB(ib8, &ds, &bmh, &cbWidth, (void **) &pBits, &rgq, TRUE);
  1625. for (iq = 0; iq < (int)bmh.biClrUsed; iq++)
  1626. rgq[iq].rgbReserved =
  1627. Luminance(&rgcs256[rgq[iq].rgbReserved].rgb) < lumThreshold;
  1628. /* map colors to black and white and convert to 1-bit/pixel */
  1629. for (y = 0; y < (int)(bmh.biHeight/2); y++) {
  1630. pbIn = pBits + y*cbWidth;
  1631. pbOut = pbIn;
  1632. assert(cbWidth % 8 == 0); // we know it's 16 or 32 bytes wide
  1633. for (ib = 0; ib < cbWidth; ) {
  1634. bIn = *pbIn++;
  1635. bOut = (bOut<<1) | rgq[bIn].rgbReserved;
  1636. ib++;
  1637. if (ib % 8 == 0)
  1638. *pbOut++ = bOut;
  1639. }
  1640. }
  1641. }
  1642. cbMask = (bmh.biWidth+31)/32*4;
  1643. CompactAndFlipIcon(pBits, cbWidth, cbMask, bmh.biWidth/8, bmh.biWidth/8, bmh.biHeight/2);
  1644. cbBits = bmh.biHeight * (bmh.biWidth/8);
  1645. /* "xor" the mask back into image */
  1646. pbOut = pBits; pbIn = pBits + cbBits/2;
  1647. for (ib = cbBits/2; ib > 0; ib--)
  1648. *pbOut++ ^= ~*pbIn++;
  1649. /* and write out base icon */
  1650. WriteMacRsrc(pBits, cbBits, pResBase, mpitres[itBase]);
  1651. MyFree(pBits);
  1652. MyFree(rgq);
  1653. /* move over 16-color icon */
  1654. if (ib4 != 0) {
  1655. ReadDIB(ib4, &ds, &bmh, &cbWidth, (void **) &pBits, &rgq, TRUE);
  1656. /* convert color table to mac standard palette */
  1657. for (pbIn = pBits, ib = cbWidth*bmh.biHeight/2; ib > 0; pbIn++, ib--) {
  1658. bIn = *pbIn;
  1659. *pbIn = (rgq[bIn>>4].rgbReserved << 4) |
  1660. rgq[bIn&0x0f].rgbReserved;
  1661. }
  1662. /* compact and flip the image */
  1663. cbMask = (bmh.biWidth+31)/32*4;
  1664. CompactAndFlipIcon(pBits, cbWidth, cbMask, bmh.biWidth/2, bmh.biWidth/8, bmh.biHeight/2);
  1665. cbBits = (bmh.biHeight/2) * (bmh.biWidth/2);
  1666. /* "xor" the mask back into the image */
  1667. pbOut = pBits; pbIn = pBits + cbBits;
  1668. for (ib = 0; ib < cbBits; ib++, pbOut++) {
  1669. if (ib % 4 == 0)
  1670. bIn = *pbIn++;
  1671. if ((bIn & 0x80) == 0)
  1672. *pbOut ^= 0xf0;
  1673. if ((bIn & 0x40) == 0)
  1674. *pbOut ^= 0x0f;
  1675. bIn <<= 2;
  1676. }
  1677. /* and write out the resource */
  1678. WriteMacRsrc(pBits, cbBits, pResBase, mpitres[itBase+itIcs4-itIcs_]);
  1679. MyFree(pBits);
  1680. MyFree(rgq);
  1681. }
  1682. /* move over 256-color icon */
  1683. if (ib8 != 0) {
  1684. ReadDIB(ib8, &ds, &bmh, &cbWidth, (void **) &pBits, &rgq, TRUE);
  1685. /* convert color table to mac standard palette */
  1686. for (pbIn = pBits, ib = cbWidth*bmh.biHeight/2; ib > 0; pbIn++, ib--)
  1687. *pbIn = rgq[*pbIn].rgbReserved;
  1688. /* compact and flip the image */
  1689. cbMask = (bmh.biWidth+31)/32*4;
  1690. CompactAndFlipIcon(pBits, cbWidth, cbMask, bmh.biWidth, bmh.biWidth/8, bmh.biHeight/2);
  1691. cbBits = (bmh.biHeight/2) * (bmh.biWidth);
  1692. /* "xor" the mask back into the image */
  1693. pbOut = pBits; pbIn = pBits + cbBits;
  1694. for (ib = 0; ib < cbBits; ib++, pbOut++) {
  1695. if (ib % 8 == 0)
  1696. bIn = *pbIn++;
  1697. if ((bIn & 0x80) == 0)
  1698. *pbOut ^= 0xff;
  1699. bIn <<= 1;
  1700. }
  1701. /* and write out the resource */
  1702. WriteMacRsrc(pBits, cbBits, pResBase, mpitres[itBase+itIcs8-itIcs_]);
  1703. MyFree(pBits);
  1704. MyFree(rgq);
  1705. }
  1706. }
  1707. void
  1708. WriteMacRsrc(
  1709. void* pBits,
  1710. int cbBits,
  1711. RESINFO* pResBase,
  1712. DWORD res
  1713. )
  1714. {
  1715. WCHAR sz[8];
  1716. TYPEINFO* pType;
  1717. RESINFO* pRes;
  1718. sz[0] = (char)(res >> 24);
  1719. sz[1] = (char)(res >> 16);
  1720. sz[2] = (char)(res >> 8);
  1721. sz[3] = (char)res;
  1722. sz[4] = 0;
  1723. pType = AddResType(sz, 0);
  1724. pRes = (RESINFO *)MyAlloc(sizeof(RESINFO));
  1725. *pRes = *pResBase;
  1726. pRes->size = cbBits;
  1727. AddResToResFile(pType, pRes, (PCHAR) pBits, (WORD)cbBits, 0);
  1728. }
  1729. void
  1730. CompactAndFlipIcon(
  1731. BYTE* pBits,
  1732. int cbRowCur,
  1733. int cbRowMaskCur,
  1734. int cbRowNew,
  1735. int cbRowMaskNew,
  1736. int Height
  1737. )
  1738. {
  1739. BYTE* pBitsNew;
  1740. int y;
  1741. BYTE* pbFrom, *pbTo;
  1742. int cb;
  1743. assert(cbRowCur >= cbRowNew);
  1744. pBitsNew = (BYTE *) MyAlloc((WORD)(Height*(cbRowNew+cbRowMaskCur)));
  1745. /* copy the bits over into the scratch space, compacting and
  1746. flipping as we go */
  1747. for (y = 0; y < Height; y++)
  1748. memcpy(pBitsNew+y*cbRowNew, pBits+(Height-y-1)*cbRowCur, cbRowNew);
  1749. /* copy over the mask, flipping and inverting as we go */
  1750. for (y = 0; y < Height; y++) {
  1751. pbTo = pBitsNew + cbRowNew*Height + y*cbRowMaskNew;
  1752. pbFrom = pBits + cbRowCur*Height + (Height-y-1)*cbRowMaskCur;
  1753. for (cb = cbRowMaskNew; cb > 0; cb--)
  1754. *pbTo++ = ~*pbFrom++;
  1755. }
  1756. /* and move the result back to pBits */
  1757. memcpy(pBits, pBitsNew, (cbRowNew+cbRowMaskCur)*Height);
  1758. MyFree(pBitsNew);
  1759. }
  1760. void CrunchY(unsigned char* pbSrc, unsigned char* pbDst, int WidthBytes, int dySrc, int scale);
  1761. void CrunchX2(unsigned char* pbSrc, unsigned char* pbDst, int cbWidth, int dy);
  1762. void
  1763. GetMacCursor(
  1764. TYPEINFO *pType,
  1765. RESINFO *pRes
  1766. )
  1767. {
  1768. struct tagNEWHEADER gh;
  1769. struct tagDESCRIPTOR ds;
  1770. BITMAPINFOHEADER bmh;
  1771. RGBQUAD *rgbq;
  1772. short rgwMask[16];
  1773. short rgwData[16];
  1774. int xyBest;
  1775. int xScale, yScale;
  1776. char* pbBits;
  1777. int ibDescNext, ibDescBest;
  1778. int ires;
  1779. int y, dy;
  1780. int cbWidth;
  1781. /* The input file has already been opened; read in the bitmap file header */
  1782. MyRead(fhCode, (char*)&gh, sizeof(struct tagNEWHEADER));
  1783. if (gh.Reserved != 0 || gh.ResType != 2)
  1784. GenError2(2175, (PCHAR)tokenbuf);
  1785. /* find the best-looking cursor */
  1786. xyBest = 32767;
  1787. ibDescBest = -1;
  1788. ibDescNext = MySeek(fhCode, 0L, SEEK_CUR);
  1789. for (ires = 0; ires < gh.ResCount; ires++) {
  1790. /* Read in the descriptor */
  1791. MySeek(fhCode, ibDescNext, SEEK_SET);
  1792. MyRead(fhCode, (char*)&ds, sizeof(struct tagDESCRIPTOR));
  1793. ibDescNext = MySeek(fhCode, 0L, SEEK_CUR);
  1794. /* get bitmap header */
  1795. MySeek(fhCode, ds.OffsetToBits, SEEK_SET);
  1796. MyRead(fhCode, (char*)&bmh, sizeof(BITMAPINFOHEADER));
  1797. if (bmh.biSize != sizeof(BITMAPINFOHEADER))
  1798. GenError2(2176, (PCHAR)tokenbuf);
  1799. /* !!! could we be smarter here about smaller cursors? */
  1800. if (bmh.biBitCount != 1 || bmh.biPlanes != 1 ||
  1801. bmh.biWidth % 16 != 0 || bmh.biHeight % 32 != 0)
  1802. continue;
  1803. xScale = bmh.biWidth / 16;
  1804. yScale = bmh.biHeight / 32;
  1805. if (xScale > 2)
  1806. continue;
  1807. if (xScale * yScale < xyBest) {
  1808. xyBest = xScale * yScale;
  1809. ibDescBest = ibDescNext - sizeof(struct tagDESCRIPTOR);
  1810. }
  1811. }
  1812. /* if no usable cursor found, bail out */
  1813. if (ibDescBest == -1) {
  1814. GenWarning2(4507, (PCHAR)tokenbuf);
  1815. return;
  1816. }
  1817. /* go back and get the best descriptor and bitmap header */
  1818. ReadDIB(ibDescBest, &ds, &bmh, &cbWidth, (void **) &pbBits, &rgbq, FALSE);
  1819. /* if our color table is backwards, invert the bits */
  1820. if ((rgbq[0].rgbRed == 0xff) &&
  1821. (rgbq[0].rgbGreen == 0xff) &&
  1822. (rgbq[0].rgbBlue == 0xff))
  1823. {
  1824. int cb;
  1825. for (cb = cbWidth * bmh.biHeight; cb > 0; cb--)
  1826. pbBits[cb] = ~pbBits[cb];
  1827. }
  1828. /* if necessary, scale the bits down to 16x16 */
  1829. if (xyBest != 1) {
  1830. GenWarning2(4506, (PCHAR)tokenbuf);
  1831. if (bmh.biWidth > 16) {
  1832. assert(bmh.biWidth == 32);
  1833. ds.xHotSpot /= (int)(bmh.biWidth / 16);
  1834. CrunchX2((unsigned char *) pbBits, (unsigned char *) pbBits, cbWidth, bmh.biHeight);
  1835. cbWidth = 2;
  1836. }
  1837. if (bmh.biHeight > 32) {
  1838. ds.yHotSpot /= (int)(bmh.biHeight / 32);
  1839. CrunchY((unsigned char *) pbBits, (unsigned char *) pbBits, cbWidth, bmh.biHeight, bmh.biHeight/32);
  1840. bmh.biHeight = 32;
  1841. }
  1842. }
  1843. /* now build the CURS resource mask and data */
  1844. dy = bmh.biHeight/2;
  1845. if (cbWidth == 1) {
  1846. for (y = dy; y > 0; y--) {
  1847. rgwMask[dy-y] = pbBits[y-1];
  1848. rgwData[dy-y] = pbBits[dy+y-1] ^ ~rgwMask[dy-y];
  1849. }
  1850. } else {
  1851. for (y = dy; y > 0; y--) {
  1852. rgwMask[dy-y] = ~*(short*)&pbBits[(dy+y-1)*cbWidth];
  1853. rgwData[dy-y] = *(short*)&pbBits[(y-1)*cbWidth] ^ rgwMask[dy-y];
  1854. }
  1855. }
  1856. for (y = dy; y < 16; y++) {
  1857. rgwMask[y] = 0;
  1858. rgwData[y] = 0;
  1859. }
  1860. /* and write out the CURS resource data */
  1861. WriteBuffer((char*)rgwData, 32);
  1862. WriteBuffer((char*)rgwMask, 32);
  1863. WriteWord(ds.yHotSpot);
  1864. WriteWord(ds.xHotSpot);
  1865. pRes->size = 32 + 32 + 2 + 2;
  1866. /* and we're done - cleanup and return */
  1867. MyFree(pbBits);
  1868. MyFree(rgbq);
  1869. fclose(fhCode);
  1870. fhCode = NULL_FILE;
  1871. AddResToResFile(pType, pRes, CodeArray, CCount, 0);
  1872. }
  1873. void
  1874. ReadDIB(
  1875. int ibDesc,
  1876. struct tagDESCRIPTOR* pds,
  1877. BITMAPINFOHEADER* pbmh,
  1878. int* pcbWidth,
  1879. void** ppBits,
  1880. RGBQUAD** prgq,
  1881. BOOL fIcon
  1882. )
  1883. {
  1884. int cbBits;
  1885. int iq;
  1886. MySeek(fhCode, ibDesc, SEEK_SET);
  1887. MyRead(fhCode, (char*)pds, sizeof(struct tagDESCRIPTOR));
  1888. MySeek(fhCode, pds->OffsetToBits, SEEK_SET);
  1889. MyRead(fhCode, (char *)pbmh, sizeof(BITMAPINFOHEADER));
  1890. /* get the color table and map to macintosh color palette while we're
  1891. looking at it */
  1892. if (pbmh->biClrUsed == 0)
  1893. pbmh->biClrUsed = 1 << pbmh->biBitCount;
  1894. *prgq = (RGBQUAD*)MyAlloc((WORD)(pbmh->biClrUsed * sizeof(RGBQUAD)));
  1895. MyRead(fhCode, (char *)*prgq, (WORD)(pbmh->biClrUsed*sizeof(RGBQUAD)));
  1896. switch (pbmh->biBitCount) {
  1897. case 1:
  1898. for (iq = 0; iq < (int)pbmh->biClrUsed; iq++)
  1899. LookupIconColor(rgcs2, ccs2, &(*prgq)[iq]);
  1900. break;
  1901. case 4:
  1902. for (iq = 0; iq < (int)pbmh->biClrUsed; iq++)
  1903. LookupIconColor(rgcs16, ccs16, &(*prgq)[iq]);
  1904. break;
  1905. case 8:
  1906. // !!! should use 256-color palette
  1907. for (iq = 0; iq < (int)pbmh->biClrUsed; iq++)
  1908. LookupIconColor(rgcs256, ccs256, &(*prgq)[iq]);
  1909. break;
  1910. default:
  1911. break;
  1912. }
  1913. /* allocate space for the bits, and load them in */
  1914. *pcbWidth = (pbmh->biBitCount*pbmh->biWidth+31)/32*4;
  1915. if (fIcon)
  1916. cbBits = (*pcbWidth * pbmh->biHeight/2) + ((pbmh->biWidth+31)/32*4) * (pbmh->biHeight/2);
  1917. else
  1918. cbBits = *pcbWidth * pbmh->biHeight;
  1919. *ppBits = MyAlloc((WORD)cbBits);
  1920. MyRead(fhCode, *ppBits, (WORD)cbBits);
  1921. }
  1922. void
  1923. LookupIconColor(
  1924. ColorSpec* rgcs,
  1925. int ccs,
  1926. RGBQUAD* pq
  1927. )
  1928. {
  1929. int ics, icsBest;
  1930. int dred, dgreen, dblue;
  1931. int drgb, drgbBest;
  1932. drgbBest = 32767;
  1933. icsBest = -1;
  1934. for (ics = 0; ics < ccs; ics++) {
  1935. dred = pq->rgbRed - (rgcs[ics].rgb.red>>8);
  1936. dgreen = pq->rgbGreen - (rgcs[ics].rgb.green>>8);
  1937. dblue = pq->rgbBlue - (rgcs[ics].rgb.blue>>8);
  1938. drgb = abs(dred) + abs(dgreen) + abs(dblue);
  1939. if (drgb < drgbBest) {
  1940. drgbBest = drgb;
  1941. icsBest = ics;
  1942. if (drgbBest == 0)
  1943. break;
  1944. }
  1945. }
  1946. pq->rgbReserved = (BYTE)rgcs[icsBest].value;
  1947. }
  1948. BOOL
  1949. IsIcon(
  1950. TYPEINFO* ptype
  1951. )
  1952. {
  1953. unsigned long rt;
  1954. short it;
  1955. if (ptype->type == 0)
  1956. return FALSE;
  1957. rt = res_type(ptype->type[0], ptype->type[1], ptype->type[2], ptype->type[3]);
  1958. for (it = 0; it < itMax; it++)
  1959. if (rt == mpitres[it])
  1960. return TRUE;
  1961. return FALSE;
  1962. }
  1963. void
  1964. CrunchX2(
  1965. unsigned char* pbSrc,
  1966. unsigned char* pbDst,
  1967. int cbWidth,
  1968. int dy
  1969. )
  1970. {
  1971. unsigned short cw, cwWidth;
  1972. unsigned short w;
  1973. unsigned char b = 0;
  1974. short bit;
  1975. assert(dy > 0);
  1976. assert(cbWidth > 1);
  1977. cwWidth = cbWidth / 2;
  1978. do {
  1979. cw = cwWidth;
  1980. do {
  1981. w = (*pbSrc << 8)|(*(pbSrc+1));
  1982. pbSrc += 2;
  1983. bit = 8;
  1984. do {
  1985. b >>= 1;
  1986. if ((w & 3) == 3) /* if both are white, keep white */
  1987. b += 0x80;
  1988. w >>= 2;
  1989. } while (--bit != 0);
  1990. *pbDst++ = b;
  1991. } while (--cw > 0);
  1992. pbDst += cwWidth & 1;
  1993. } while (--dy > 0);
  1994. }
  1995. void
  1996. CrunchY(
  1997. unsigned char* pbSrc,
  1998. unsigned char* pbDst,
  1999. int WidthBytes,
  2000. int dySrc,
  2001. int scale
  2002. )
  2003. {
  2004. int cbGroup;
  2005. int cwRow;
  2006. int dyDst, dy;
  2007. unsigned short w;
  2008. unsigned char *pb;
  2009. if (scale <= 1) {
  2010. memcpy(pbDst, pbSrc, dySrc * WidthBytes);
  2011. return;
  2012. }
  2013. dyDst = dySrc / scale;
  2014. cbGroup = WidthBytes * (scale - 1);
  2015. do {
  2016. cwRow = WidthBytes / sizeof(unsigned short);
  2017. do {
  2018. pb = pbSrc;
  2019. w = *(unsigned short*)pb;
  2020. dy = scale - 1;
  2021. do {
  2022. pb += WidthBytes;
  2023. w &= *(unsigned short*)pb;
  2024. } while (--dy > 0);
  2025. *((unsigned short*)pbDst) = w;
  2026. pbDst += sizeof(unsigned short);
  2027. pbSrc += sizeof(unsigned short);
  2028. } while (--cwRow > 0);
  2029. pbSrc += cbGroup;
  2030. } while (--dyDst > 0);
  2031. }
  2032. /* WriteMacMap
  2033. *
  2034. * Writes out a macintosh resource map from the type and resource
  2035. * data stashed away in the type and resource lists
  2036. *
  2037. * See Inside Mac, Volume I, for a fine description of the
  2038. * format of a macintosh resource file
  2039. */
  2040. void
  2041. WriteMacMap(
  2042. void
  2043. )
  2044. {
  2045. TYPEINFO *ptype;
  2046. RESINFO *pres;
  2047. int i;
  2048. size_t cch;
  2049. int cbNameTbl, ctype, cref, ibName;
  2050. long cbData;
  2051. int offRef;
  2052. WCHAR *pch;
  2053. #define cbMacType 8
  2054. #define cbMacRef 12
  2055. /* alright, we're done reading all this stuff in, run through all
  2056. our type lists and see what we've accumulated */
  2057. cbData = MySeek(fhBin, 0L, 1) - MACDATAOFFSET;
  2058. ctype = 0;
  2059. cref = 0;
  2060. cbNameTbl = 0;
  2061. for (ptype = pTypInfo; ptype != 0; ptype = ptype->next) {
  2062. if (ptype->nres == 0)
  2063. continue;
  2064. ctype++;
  2065. cref += ptype->nres;
  2066. for (pres = ptype->pres; pres != 0; pres = pres->next) {
  2067. /* make sure each reference has a unique resource id */
  2068. if (pres->nameord == 0)
  2069. pres->nameord = (USHORT)IdUnique(ptype, pres);
  2070. if (pres->name != 0)
  2071. cbNameTbl += wcslen(pres->name)+1;
  2072. }
  2073. }
  2074. /* write out the resource header at offset 0 in the file */
  2075. MySeek(fhBin, 0L, 0);
  2076. CtlInit();
  2077. WriteLong((long)MACDATAOFFSET);
  2078. WriteLong((long)MACDATAOFFSET + cbData);
  2079. WriteLong(cbData);
  2080. WriteLong((long)(16+4+2+2+2+2+2 + ctype*cbMacType + cref*cbMacRef + cbNameTbl));
  2081. for (i = (MACDATAOFFSET - 16)/4; i-- > 0; )
  2082. WriteLong(0);
  2083. MyWrite(fhBin, (LPSTR)CodeArray, CCount);
  2084. /* we've already written out all the data, now write out the
  2085. beginning of the map part of the resource file */
  2086. MySeek(fhBin, (long)MACDATAOFFSET + cbData, 0);
  2087. CtlInit();
  2088. /* 24 bytes of 0s */
  2089. for (i = 6; i-- > 0; )
  2090. WriteLong(0);
  2091. /* offset to start of type list */
  2092. WriteWord(28);
  2093. /* offset to start of name list */
  2094. WriteWord((USHORT)(28 + 2 + ctype * cbMacType + cref * cbMacRef));
  2095. /* dump out type table of the resource map */
  2096. WriteWord((USHORT)(ctype - 1));
  2097. offRef = 2 + ctype * cbMacType;
  2098. for (ptype = pTypInfo; ptype != 0; ptype = ptype->next) {
  2099. long rt;
  2100. TYPEINFO *ptypeX;
  2101. if (ptype->nres == 0)
  2102. continue;
  2103. /* 32-bit resource name - verify name truncation didn't
  2104. cause conflicts */
  2105. rt = MungeResType(ptype->type, ptype->typeord);
  2106. for (ptypeX = ptype->next; ptypeX != 0; ptypeX = ptypeX->next) {
  2107. if (rt == MungeResType(ptypeX->type, ptypeX->typeord)) {
  2108. char szMac[8], szType1[128], szType2[128];
  2109. szMac[0] = (BYTE)(rt>>24);
  2110. szMac[1] = (BYTE)(rt>>16);
  2111. szMac[2] = (BYTE)(rt>>8);
  2112. szMac[3] = (BYTE)(rt);
  2113. szMac[4] = 0;
  2114. if (ptype->typeord)
  2115. wsprintfA(szType1, "%d", ptype->typeord);
  2116. else
  2117. wsprintfA(szType1, "%ws", ptype->type);
  2118. if (ptypeX->typeord)
  2119. wsprintfA(szType2, "%d", ptypeX->typeord);
  2120. else
  2121. wsprintfA(szType2, "%ws", ptypeX->type);
  2122. GenWarning4(4509, szType1, szType2, szMac);
  2123. }
  2124. }
  2125. WriteLong(rt);
  2126. /* number of references of this type */
  2127. WriteWord((USHORT)(ptype->nres-1));
  2128. /* offset to the reference list for this type */
  2129. WriteWord((USHORT)offRef);
  2130. offRef += ptype->nres * cbMacRef;
  2131. }
  2132. /* dump out reference table of the resource map */
  2133. ibName = 0;
  2134. for (ptype = pTypInfo; ptype != 0; ptype = ptype->next) {
  2135. if (ptype->nres == 0)
  2136. continue;
  2137. for (pres = ptype->pres; pres != 0; pres = pres->next) {
  2138. /* resource id */
  2139. WriteWord(pres->nameord);
  2140. /* offset to name in namelist */
  2141. if (pres->name == 0) {
  2142. WriteWord(0xffff); /* unnamed, use -1 */
  2143. } else {
  2144. WriteWord((USHORT)ibName);
  2145. ibName += wcslen(pres->name)+1;
  2146. }
  2147. /* attributes and resource data offset */
  2148. WriteLong(pres->BinOffset);
  2149. /* must be 0 */
  2150. WriteLong(0L);
  2151. }
  2152. }
  2153. /* and finally, dump out name table */
  2154. /* note that we've implemented the Unicode=>ASCII conversion here by
  2155. simply dumping out the low byte of each Unicode character. Effectively,
  2156. we're assuming that resource names will be ASCII. Changing this would
  2157. require changing the output code here and also changing a few places
  2158. where we use wcslen to calculate the number of bytes that the ASCII
  2159. resource name will require. If the resource name can contain 2-byte
  2160. characters we would need to convert the Unicode to multi-byte and
  2161. then count characters instead of just calling wcslen. */
  2162. for (ptype = pTypInfo; ptype != 0; ptype = ptype->next) {
  2163. if (ptype->nres == 0)
  2164. continue;
  2165. for (pres = ptype->pres; pres != 0; pres = pres->next) {
  2166. if (pres->name == 0)
  2167. continue;
  2168. WriteByte(cch = wcslen(pres->name));
  2169. for (pch = pres->name; cch--; )
  2170. WriteByte((BYTE)*pch++);
  2171. }
  2172. }
  2173. MyWrite(fhBin, (LPSTR)CodeArray, CCount);
  2174. }
  2175. long
  2176. MungeResType(
  2177. WCHAR *szType,
  2178. short wOrd
  2179. )
  2180. {
  2181. long rt;
  2182. int ich;
  2183. switch (wOrd) {
  2184. case 0:
  2185. assert(szType != NULL && *szType != 0);
  2186. rt = 0;
  2187. for (ich = 0; ich < 4; ich++) {
  2188. rt <<= 8;
  2189. if (*szType)
  2190. rt |= (BYTE) (*szType++);
  2191. else
  2192. rt |= ' ';
  2193. }
  2194. break;
  2195. case RT_CURSOR:
  2196. rt = 'CURS';
  2197. break;
  2198. case RT_BITMAP:
  2199. rt = 'WBMP';
  2200. break;
  2201. case RT_ICON:
  2202. rt = 'WICO';
  2203. break;
  2204. case RT_MENU:
  2205. rt = 'WMNU';
  2206. break;
  2207. case RT_DIALOG:
  2208. rt = 'WDLG';
  2209. break;
  2210. case RT_STRING:
  2211. rt = 'STR#';
  2212. break;
  2213. case RT_ACCELERATOR:
  2214. rt = 'WACC';
  2215. break;
  2216. case RT_RCDATA:
  2217. case RT_DLGINIT:
  2218. rt = 'HEXA';
  2219. break;
  2220. case RT_TOOLBAR:
  2221. rt = 'TLBR';
  2222. break;
  2223. case RT_GROUP_CURSOR:
  2224. rt = 'CURS';
  2225. break;
  2226. case RT_GROUP_ICON:
  2227. rt = 'WGIC';
  2228. break;
  2229. case RT_VERSION:
  2230. rt = 'WVER';
  2231. break;
  2232. case RT_FONTDIR:
  2233. case RT_FONT:
  2234. //case RT_ERRTABLE:
  2235. //case RT_NAMETABLE:
  2236. default: {
  2237. static char rgchHex[] = "0123456789ABCDEF";
  2238. char ch4 = rgchHex[wOrd & 0x0f];
  2239. char ch3 = rgchHex[(wOrd >> 4) & 0x0f];
  2240. char ch2 = rgchHex[(wOrd >> 8) & 0x0f];
  2241. char ch1 = 'M' + ((wOrd >> 12) & 0x0f);
  2242. rt = res_type(ch1,ch2,ch3,ch4);
  2243. break;
  2244. }
  2245. }
  2246. return rt;
  2247. }
  2248. /* IdUnique
  2249. *
  2250. * Searches through the items of the given type looking for
  2251. * an unused resource id. Returns the smallest resource id
  2252. * that is not currently used.
  2253. *
  2254. * This routine handles icon families in a particular annoying
  2255. * way, using a particularly inefficient algorithm. But it
  2256. * does keep icon ids synchronized if they have the same name.
  2257. *
  2258. * Entry:
  2259. * ptype - type to search
  2260. * pres - resource type needing the unique id
  2261. *
  2262. * Exit:
  2263. * retunrs - a unique resource id
  2264. */
  2265. int
  2266. IdUnique(
  2267. TYPEINFO *ptype,
  2268. RESINFO *pres
  2269. )
  2270. {
  2271. int id;
  2272. RESINFO *presScan;
  2273. TYPEINFO* ptypeIcon;
  2274. assert(ptype->pres != 0);
  2275. if (IsIcon(ptype)) {
  2276. /* see if we've already found an id for an icon with the same name */
  2277. assert(pres->name != NULL);
  2278. for (ptypeIcon = pTypInfo; ptypeIcon != NULL; ptypeIcon = ptypeIcon->next) {
  2279. if (!IsIcon(ptypeIcon))
  2280. continue;
  2281. for (presScan = ptypeIcon->pres; presScan != NULL; presScan = presScan->next) {
  2282. if (presScan->name == NULL || presScan->nameord == 0)
  2283. continue;
  2284. if (wcscmp(presScan->name, pres->name) == 0)
  2285. return presScan->nameord;
  2286. }
  2287. }
  2288. /* rats, didn't find it, gotta find one that's unique in *all* the
  2289. icon types */
  2290. for (id = idBase; ; ) {
  2291. for (ptypeIcon = pTypInfo; ptypeIcon != NULL; ptypeIcon = ptypeIcon->next) {
  2292. if (!IsIcon(ptypeIcon))
  2293. continue;
  2294. for (presScan = ptypeIcon->pres; presScan != NULL; presScan = presScan->next) {
  2295. if (presScan->nameord == id)
  2296. goto NextId;
  2297. }
  2298. }
  2299. return id;
  2300. NextId:
  2301. id = (id+1) & 0xffff;
  2302. if (id == 0)
  2303. id = 1;
  2304. }
  2305. } else {
  2306. for (id = idBase; ; ) {
  2307. for (presScan = ptype->pres; presScan->nameord != id; ) {
  2308. presScan = presScan->next;
  2309. if (presScan == 0)
  2310. return id;
  2311. }
  2312. id = (id+1) & 0xffff;
  2313. if (id == 0)
  2314. id = 1;
  2315. }
  2316. }
  2317. }
  2318. /*---------------------------------------------------------------------------*/
  2319. /* */
  2320. /* GetToolbar - */
  2321. /* */
  2322. /*---------------------------------------------------------------------------*/
  2323. SHORT
  2324. GetToolbarValue(
  2325. void
  2326. )
  2327. {
  2328. SHORT sVal;
  2329. if (!GetFullExpression(&sVal, GFE_ZEROINIT | GFE_SHORT))
  2330. ParseError1(2250); //"expected numerical toolbar constant"
  2331. return(sVal);
  2332. }
  2333. void
  2334. GetButtonSize(
  2335. PSHORT cx,
  2336. PSHORT cy
  2337. )
  2338. {
  2339. *cx= GetToolbarValue();
  2340. if (token.type == COMMA)
  2341. GetToken(TOKEN_NOEXPRESSION);
  2342. *cy= GetToolbarValue();
  2343. }
  2344. int
  2345. GetToolbar(
  2346. PRESINFO pRes
  2347. )
  2348. {
  2349. SHORT cx, cy;
  2350. BOOL bItemRead = FALSE;
  2351. WriteWord(0x0001); // Version 1 of this resource.
  2352. GetButtonSize(&cx, &cy);
  2353. WriteWord(cx);
  2354. WriteWord(cy);
  2355. ItemCountLoc = CCount; /* global marker for location of item cnt. */
  2356. /* skip place for num of items */
  2357. WriteWord(0);
  2358. PreBeginParse(pRes, 2251);
  2359. while (token.type != END) {
  2360. switch (token.type) {
  2361. case TKSEPARATOR:
  2362. bItemRead = TRUE;
  2363. GetToken(TOKEN_NOEXPRESSION);
  2364. WriteWord(0);
  2365. break;
  2366. case TKBUTTON:
  2367. bItemRead = TRUE;
  2368. GetToken(TRUE);
  2369. if (token.type != NUMLIT)
  2370. ParseError1(2250); //"expected numerical toolbar constant"
  2371. WriteSymbolUse(&token.sym);
  2372. WriteWord(GetToolbarValue());
  2373. break;
  2374. case EOFMARK:
  2375. ParseError1(2252); //"END expected in toolbar"
  2376. quit("\n");
  2377. break;
  2378. default:
  2379. ParseError1(2253); //"unknown toolbar item type"
  2380. GetToken(TOKEN_NOEXPRESSION); // try to continue
  2381. continue;
  2382. }
  2383. IncItemCount();
  2384. }
  2385. /* make sure we have a toolbar item */
  2386. if (!bItemRead)
  2387. ParseError1(2254); //"empty toolbars not allowed"
  2388. if (fMacRsrcs)
  2389. SwapItemCount();
  2390. return (TRUE);
  2391. }