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.

2846 lines
83 KiB

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