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.

1521 lines
44 KiB

  1. #include <pch.h>
  2. #include <tchar.h>
  3. #include "resource.h"
  4. #include "dibutil.h"
  5. #include "billbrd.h"
  6. #include "animate.h"
  7. #define MAX_ANIMSTRING MAX_STRING
  8. #define MyWait(c) {int __nCnt = (c); while(__nCnt) __nCnt--;}
  9. #define GetInvertRGB(rgb) (RGB(255 - GetRValue(rgb), 255 - GetGValue(rgb), 255 - GetBValue(rgb)))
  10. #define CX_MOVE 4
  11. #define CY_MOVE 4
  12. #define CX_SHADOW 4
  13. #define CY_SHADOW 4
  14. #define FONT_TITLE 0
  15. #define FONT_TEXT 1
  16. #define FONT_DELETE 10
  17. // AnimateBlt Index
  18. #define AB_HOR_POS 1
  19. #define AB_HOR_NEG 2
  20. #define AB_VER_POS 3
  21. #define AB_VER_NEG 4
  22. typedef struct _tagANISTRINGFORM {
  23. COLORREF col;
  24. BOOL bShadow;
  25. COLORREF colShadow;
  26. RECT rc;
  27. UINT uiLineHeightx2;
  28. HFONT hFont;
  29. } ANISTRINGFORM, FAR *LPANISTRINGFORM;
  30. HDC g_hdcCache = NULL;
  31. HBITMAP g_hbmp = NULL;
  32. HBITMAP g_hbmpOldCache = NULL;
  33. LOGFONT g_lfTemp = {0};
  34. BOOL g_fBullet = FALSE;
  35. UINT g_uiAnimateIndex = (UINT)-1;
  36. UINT g_uiLastAnimateIndex = (UINT)-1;
  37. void RestoreCachedRect()
  38. {
  39. HWND hwndBB;
  40. HDC hdcBB;
  41. int cxBB;
  42. int cyBB;
  43. RECT rcBB;
  44. hwndBB = GetBBHwnd();
  45. if (GetClientRect(hwndBB, &rcBB))
  46. {
  47. cxBB = rcBB.right - rcBB.left;
  48. cyBB = rcBB.bottom - rcBB.top;
  49. hdcBB = GetDC(hwndBB);
  50. if (hdcBB)
  51. {
  52. // Init cached bitmap
  53. BitBlt(hdcBB, 0, 0, cxBB, cyBB, g_hdcCache, 0, 0, SRCCOPY);
  54. ReleaseDC(hwndBB, hdcBB);
  55. }
  56. }
  57. }
  58. void AnimateBlt(HDC hdcDest, int x, int y, int w, int h, HDC hdcSrc, int xSrc, int ySrc, int nPattern)
  59. {
  60. int i;
  61. switch (nPattern)
  62. {
  63. case AB_HOR_POS:
  64. for (i = 0; i < w; i++)
  65. {
  66. BitBlt(hdcDest, x + i, y, 1, h,
  67. hdcSrc, xSrc + i, ySrc, SRCCOPY);
  68. MyWait(10000);
  69. }
  70. break;
  71. case AB_VER_POS:
  72. for (i = 0; i < h; i++)
  73. {
  74. BitBlt(hdcDest, x, y + 1, w, 1,
  75. hdcSrc, xSrc + i, ySrc, SRCCOPY);
  76. MyWait(10000);
  77. }
  78. break;
  79. }
  80. }
  81. void RestoreRect(HDC hdc, LPRECT lprc, int nPat)
  82. {
  83. int cx = lprc->right - lprc->left + 1;
  84. int cy = lprc->bottom - lprc->top + 1;
  85. if (hdc)
  86. {
  87. BitBlt(hdc, lprc->left, lprc->top, cx, cy,
  88. g_hdcCache, lprc->left, lprc->top, SRCCOPY);
  89. }
  90. }
  91. /**********************************************************************
  92. * CheckForBulletAndRemoveMarker()
  93. *
  94. * This function checks if the line of text has a bullet preceding it
  95. * if so it removes the bullet identifier from the string. This function
  96. * also sets the value of piWidth to the width of the bitmap.
  97. *
  98. * Returns: TRUE == Bullet needed
  99. * FALSE == No bullet
  100. *
  101. **********************************************************************/
  102. BOOL CheckForBulletAndRemoveMarker(LPTSTR lpstr, LPINT lpiWidth)
  103. {
  104. BOOL bRet = FALSE;
  105. LPTSTR p = NULL;
  106. HBITMAP hBmp = NULL;
  107. BITMAP bm;
  108. p = lpstr;
  109. *lpiWidth = 0;
  110. g_fBullet = FALSE;
  111. if(*p)
  112. {
  113. while(*p == TEXT(' '))
  114. p = CharNext(p);
  115. if(*p == '-')
  116. {
  117. lstrcpy(p, CharNext(p));
  118. bRet = TRUE;
  119. hBmp = LoadBitmap(g_hInstance, MAKEINTRESOURCE(IDB_BULLET_1));
  120. GetObject(hBmp, sizeof(BITMAP), (LPSTR)&bm);
  121. *lpiWidth = bm.bmWidth;
  122. DeleteObject(hBmp);
  123. g_fBullet = TRUE;
  124. }
  125. }
  126. return bRet;
  127. }
  128. /**********************************************************************
  129. * CheckForBulletAndReturnWidth()
  130. *
  131. * This function checks if the line of text has a bullet preceding it
  132. * if so figures out the bullet bitmaps width and returns it.
  133. *
  134. * Returns: TRUE == Bullet needed
  135. * FALSE == No bullet
  136. *
  137. **********************************************************************/
  138. int CheckForBulletAndReturnWidth(LPTSTR lpstr)
  139. {
  140. int iWidth = 0;
  141. LPTSTR p = NULL;
  142. HBITMAP hBmp = NULL;
  143. BITMAP bm;
  144. p = lpstr;
  145. if(*p)
  146. {
  147. while(*p == TEXT(' '))
  148. p = CharNext(p);
  149. if(*p == TEXT('-'))
  150. {
  151. hBmp = LoadBitmap(g_hInstance, MAKEINTRESOURCE(IDB_BULLET_1));
  152. GetObject(hBmp, sizeof(BITMAP), (LPSTR)&bm);
  153. iWidth = bm.bmWidth;
  154. DeleteObject(hBmp);
  155. }
  156. }
  157. return iWidth;
  158. }
  159. /**********************************************************************
  160. * PaintBulletIfNeeded()
  161. *
  162. * This function checks if the line of text needs a bullet to be painted
  163. * if so paints the bullet bitmap on the given coords on the given dc.
  164. *
  165. * Returns: None
  166. *
  167. **********************************************************************/
  168. void PaintBulletIfNeeded(HDC hdc, int x, int y , int iHeight)
  169. {
  170. HBITMAP hBmp = NULL;
  171. BITMAP bm;
  172. if(g_fBullet)
  173. {
  174. hBmp = LoadBitmap(g_hInstance, MAKEINTRESOURCE(IDB_BULLET_1));
  175. if(hBmp)
  176. {
  177. GetObject(hBmp, sizeof(BITMAP), &bm);
  178. DrawBitmap(hdc, hBmp, x, y + (iHeight - bm.bmHeight)/2);
  179. DeleteObject(hBmp);
  180. g_fBullet = FALSE;
  181. }
  182. }
  183. }
  184. void GetPanelSectionName(int nPanel, LPTSTR lpszKey)
  185. {
  186. wsprintf(lpszKey, TEXT("Panel%d"), nPanel);
  187. }
  188. int GetTextCount(int nPanel)
  189. {
  190. TCHAR szKey[80];
  191. GetPanelSectionName(nPanel, szKey);
  192. return GetPrivateProfileInt(szKey, TEXT("Count"), 0, g_szFileName);
  193. }
  194. int GetTitle(int nPanel, LPTSTR lpStr)
  195. {
  196. TCHAR szKey[80];
  197. GetPanelSectionName(nPanel, szKey);
  198. return GetPrivateProfileString(szKey, TEXT("Title"), TEXT(""),
  199. lpStr, MAX_ANIMSTRING, g_szFileName);
  200. }
  201. int GetPanelText(int nPanel, int nCnt, LPTSTR lpStr)
  202. {
  203. TCHAR szKey[16];
  204. TCHAR szSec[16];
  205. GetPanelSectionName(nPanel, szKey);
  206. wsprintf(szSec, TEXT("Text%d"), nCnt);
  207. return GetPrivateProfileString(szKey, szSec, TEXT(""),
  208. lpStr, MAX_ANIMSTRING, g_szFileName);
  209. }
  210. BOOL CALLBACK GetLogFontEnumProc(LPLOGFONT lplf, LPTEXTMETRIC lptm, int wType, LPARAM lpData)
  211. {
  212. g_lfTemp = *lplf;
  213. return 0;
  214. }
  215. BOOL GetLogFontFromFaceName(LPLOGFONT lplf, LPTSTR lpszFaceName)
  216. {
  217. HWND hwndBB = NULL;
  218. HDC hdcBB = NULL;
  219. FONTENUMPROC lpEnumFontsCallBack = NULL;
  220. hwndBB = GetBBHwnd();
  221. hdcBB = GetDC(hwndBB);
  222. lpEnumFontsCallBack = (FONTENUMPROC)MakeProcInstance((FARPROC)GetLogFontEnumProc, g_hInstance);
  223. EnumFonts((HDC)hdcBB, (LPCTSTR)lpszFaceName, (FONTENUMPROC)lpEnumFontsCallBack, 0L);
  224. FreeProcInstance((FARPROC)lpEnumFontsCallBack);
  225. *lplf = g_lfTemp;
  226. ReleaseDC(hwndBB, hdcBB);
  227. return TRUE;
  228. }
  229. /**********************************************************************
  230. * GetDeleteFontHandle()
  231. *
  232. * This function checks if the font specified by iFontnum exists already.
  233. * if so returns its handle if not it creates the font and return the
  234. * handle. returns NULL in error case. if Function is called with
  235. * iFontNum = FONT_DELETE then the existing fonts are deleted.
  236. *
  237. * INPUT: iFontNum
  238. * Returns: HFONT
  239. *
  240. * 10/08/97 hanumany created
  241. **********************************************************************/
  242. HFONT GetDeleteFontHandle(int iFontNum)
  243. {
  244. static HFONT hFontTitle = NULL;
  245. static HFONT hFontText = NULL;
  246. switch(iFontNum)
  247. {
  248. case FONT_TITLE:
  249. {
  250. if(hFontTitle)
  251. {
  252. return hFontTitle;
  253. }
  254. else
  255. {
  256. LOGFONT lf = {0};
  257. GetLogFontFromFaceName(&lf, g_szTFont);
  258. lf.lfHeight = -MulDiv(g_nTFontHeight, 96, 72);
  259. lf.lfWidth = g_nTFontWidth;
  260. lf.lfWeight = g_nTFontWeight;
  261. lf.lfQuality = ANTIALIASED_QUALITY;
  262. lf.lfCharSet = g_bCharSet;
  263. hFontTitle = CreateFontIndirect(&lf);
  264. return hFontTitle;
  265. }
  266. }
  267. case FONT_TEXT:
  268. {
  269. if(hFontText)
  270. {
  271. return hFontText;
  272. }
  273. else
  274. {
  275. LOGFONT lf = {0};
  276. GetLogFontFromFaceName(&lf, g_szBFont);
  277. lf.lfHeight = -MulDiv(g_nBFontHeight, 96, 72);
  278. lf.lfWidth = g_nBFontWidth;
  279. lf.lfWeight = g_nBFontWeight;
  280. lf.lfQuality = PROOF_QUALITY;
  281. lf.lfCharSet = g_bCharSet;
  282. hFontText = CreateFontIndirect(&lf);
  283. return hFontText;
  284. }
  285. }
  286. case FONT_DELETE:
  287. {
  288. if(hFontTitle)
  289. {
  290. DeleteObject(hFontTitle);
  291. hFontTitle = NULL;
  292. }
  293. if(hFontText)
  294. {
  295. DeleteObject(hFontText);
  296. hFontText = NULL;
  297. }
  298. break;
  299. }
  300. }
  301. return NULL;
  302. }
  303. /************************************************************************
  304. * RemoveLineBreakChar()
  305. *
  306. * This function copies lpszCurr to lpszFixed without the line break char's
  307. *
  308. ************************************************************************/
  309. void RemoveLineBreakChar(LPCTSTR lpszCurr, LPTSTR lpszFixed)
  310. {
  311. while (*lpszCurr != TEXT('\0'))
  312. {
  313. if(*lpszCurr != TEXT('|'))
  314. {
  315. *lpszFixed = *lpszCurr;
  316. #ifndef UNICODE
  317. if(IsDBCSLeadByte(*lpszFixed))
  318. {
  319. *(lpszFixed+1) = *(lpszCurr+1);
  320. }
  321. #endif
  322. lpszFixed = CharNext(lpszFixed);
  323. lpszCurr = CharNext(lpszCurr);
  324. }
  325. else
  326. {
  327. lpszCurr = CharNext(lpszCurr);
  328. }
  329. }
  330. *lpszFixed = '\0';
  331. return;
  332. }
  333. void MergeBlt(LPTSTR lpstr,
  334. HDC hdcDst, int x0, int y0, int cx0, int cy0,
  335. HDC hdcSrc, int x1, int y1, int cx1, int cy1,
  336. COLORREF rgb, COLORREF rgbShadow,
  337. BOOL fShadow, BOOL fStretch,
  338. TEXTMETRIC* lptm, int iLineSpace, RECT* lprc
  339. )
  340. {
  341. int nNumLines = 0;
  342. if (fShadow)
  343. {
  344. SetTextColor(hdcSrc, 0);
  345. DisplayString(hdcSrc, x1 + CX_SHADOW, y1 + CY_SHADOW, lptm, iLineSpace, lprc, &nNumLines, lpstr, LEFT);
  346. if (fStretch)
  347. {
  348. StretchBlt(hdcDst, x0, 0, cx0, cy0,
  349. hdcSrc, x1, y1, cx1, cy1, SRCAND);
  350. }
  351. else
  352. {
  353. BitBlt(hdcDst, x0, 0, cx0, cy0,
  354. hdcSrc, x1, y1, SRCAND);
  355. }
  356. SetTextColor(hdcSrc, GetInvertRGB(rgbShadow));
  357. DisplayString(hdcSrc, x1 + CX_SHADOW, y1 + CY_SHADOW, lptm, iLineSpace, lprc, &nNumLines, lpstr, LEFT);
  358. if (fStretch)
  359. {
  360. StretchBlt(hdcDst, y0, y0, cx0, cy0,
  361. hdcSrc, x1, y1, cx1, cy1, MERGEPAINT);
  362. }
  363. else
  364. {
  365. BitBlt(hdcDst, y0, y0, cx0, cy0,
  366. hdcSrc, x1, y1, MERGEPAINT);
  367. }
  368. }
  369. SetTextColor(hdcSrc, 0);
  370. DisplayString(hdcSrc, x1, y1, lptm, iLineSpace, lprc, &nNumLines, lpstr, LEFT);
  371. if (fStretch)
  372. {
  373. StretchBlt(hdcDst, x0, 0, cx0, cy0,
  374. hdcSrc, x1, y1, cx1, cy1, SRCAND);
  375. }
  376. else
  377. {
  378. BitBlt(hdcDst, x0, 0, cx0, cy0,
  379. hdcSrc, x1, y1, SRCAND);
  380. }
  381. SetTextColor(hdcSrc, GetInvertRGB(rgb));
  382. DisplayString(hdcSrc, x1, y1, lptm, iLineSpace, lprc, &nNumLines, lpstr, LEFT);
  383. if (fStretch)
  384. {
  385. StretchBlt(hdcDst, y0, y0, cx0, cy0,
  386. hdcSrc, x1, y1, cx1, cy1, MERGEPAINT);
  387. }
  388. else
  389. {
  390. BitBlt(hdcDst, y0, y0, cx0, cy0,
  391. hdcSrc, x1, y1, MERGEPAINT);
  392. }
  393. }
  394. int AnimateString(
  395. HDC hdc,
  396. LPTSTR lpstr,
  397. LPANISTRINGFORM lpani,
  398. int iLineSpace,
  399. int nPat
  400. )
  401. {
  402. HWND hwndBB = NULL;
  403. int cxBB;
  404. int cyBB;
  405. RECT rcBB;
  406. HDC hdcMem = NULL;
  407. HDC hdcText = NULL;
  408. HBITMAP hbmpMem = NULL;
  409. HBITMAP hbmpText = NULL;
  410. HBITMAP hbmpOld = NULL;
  411. HBITMAP hbmpOldText = NULL;
  412. HFONT hfont = NULL;
  413. HFONT hfontOld = NULL;
  414. HBRUSH hbrBlack = NULL;
  415. HBRUSH hbrWhite = NULL;
  416. HBRUSH hbrOldText = NULL;
  417. int cx;
  418. int cy;
  419. int i,j;
  420. TEXTMETRIC tm;
  421. int x0;
  422. int nLen;
  423. int nWait;
  424. int nDelta;
  425. RECT rc;
  426. int nNumLines = 0;
  427. int ibmWidth = 0;
  428. SIZE size;
  429. hwndBB = GetBBHwnd();
  430. if (!GetClientRect(hwndBB, &rcBB))
  431. {
  432. goto exit;
  433. }
  434. cxBB = rcBB.right - rcBB.left;
  435. cyBB = rcBB.bottom - rcBB.top;
  436. hbrWhite = GetStockObject(WHITE_BRUSH);
  437. if (hbrWhite == NULL)
  438. {
  439. goto exit;
  440. }
  441. hbrBlack = GetStockObject(BLACK_BRUSH);
  442. if (!hbrBlack)
  443. {
  444. goto exit;
  445. }
  446. hdcText = CreateCompatibleDC(hdc);
  447. if (!hdcText)
  448. {
  449. goto exit;
  450. }
  451. hbmpText = CreateCompatibleBitmap(hdc, cxBB, cyBB);
  452. if (!hbmpText)
  453. {
  454. goto exit;
  455. }
  456. hdcMem = CreateCompatibleDC(hdc);
  457. if (!hdcMem)
  458. {
  459. goto exit;
  460. }
  461. cx = lpani->rc.right - lpani->rc.left + 1;
  462. cy = lpani->rc.bottom - lpani->rc.top + 1;
  463. if (lpani->bShadow)
  464. {
  465. cx += CX_SHADOW;
  466. cy += CY_SHADOW;
  467. }
  468. hbmpMem = CreateCompatibleBitmap(hdc, cxBB, cyBB);
  469. if (!hbmpMem)
  470. {
  471. goto exit;
  472. }
  473. hbmpOld = SelectObject(hdcMem, hbmpMem);
  474. SetBkMode(hdcMem, TRANSPARENT);
  475. hfont = lpani->hFont;
  476. if (!hfont)
  477. {
  478. goto exit;
  479. }
  480. hfontOld = SelectObject(hdcMem, hfont);
  481. GetTextMetrics(hdcMem, &tm);
  482. nLen = lstrlen(lpstr);
  483. GetTextExtentPoint32(hdcMem, lpstr, nLen, &size);
  484. ibmWidth = CheckForBulletAndReturnWidth(lpstr);
  485. if (cx > (int)size.cx + ibmWidth + 10)
  486. {
  487. cx = (int)size.cx + ibmWidth + 10;
  488. }
  489. if (cy > (int)size.cy)
  490. {
  491. cy = (int)size.cy;
  492. }
  493. hfontOld = SelectObject(hdcText, hfont);
  494. hbmpOldText = SelectObject(hdcText, hbmpText);
  495. hbrOldText = SelectObject(hdcText, hbrWhite);
  496. rc.left = 0;
  497. rc.top = 0;
  498. rc.right = cx;
  499. rc.bottom = cy;
  500. FillRect(hdcText, &rc, hbrWhite);
  501. DisplayString(hdcText, 0, 0, &tm, iLineSpace, &rc, &nNumLines, lpstr, LEFT);
  502. if(nNumLines > 1)
  503. {
  504. cy = cy + (tm.tmHeight * lpani->uiLineHeightx2 * nNumLines / 2);
  505. rc.left = 0;
  506. rc.top = 0;
  507. rc.right = cx;
  508. rc.bottom = cy;
  509. FillRect(hdcText, &rc, hbrWhite);
  510. DisplayString(hdcText, 0, 0, &tm, iLineSpace, &rc, &nNumLines, lpstr, LEFT);
  511. }
  512. switch (nPat)
  513. {
  514. default:
  515. case 7:
  516. case 0:
  517. {
  518. COLORREF crOld = 0;
  519. if (g_bBiDi)
  520. {
  521. BitBlt(hdcMem, 0, 0, cx, cy,
  522. g_hdcCache, lpani->rc.right-cx, lpani->rc.top, SRCCOPY);
  523. }
  524. else
  525. {
  526. BitBlt(hdcMem, 0, 0, cx, cy,
  527. g_hdcCache, lpani->rc.left, lpani->rc.top, SRCCOPY);
  528. }
  529. if (lpani->bShadow)
  530. {
  531. CONST int SHADOW_OFFSET = 2;
  532. RECT rcShadow;
  533. if (SetRect(&rcShadow,
  534. rc.left,
  535. rc.top,
  536. rc.right + SHADOW_OFFSET,
  537. rc.bottom + SHADOW_OFFSET))
  538. {
  539. crOld = SetTextColor(hdcMem, lpani->colShadow);
  540. DisplayString(hdcMem,
  541. SHADOW_OFFSET,
  542. SHADOW_OFFSET,
  543. &tm,
  544. iLineSpace,
  545. &rcShadow,
  546. &nNumLines,
  547. lpstr, LEFT);
  548. SetTextColor(hdcMem, crOld);
  549. }
  550. }
  551. crOld = SetTextColor(hdcMem, lpani->col);
  552. DisplayString(hdcMem, 0, 0, &tm, iLineSpace, &rc, &nNumLines, lpstr, LEFT);
  553. PaintBulletIfNeeded(hdcMem, 0, 0, tm.tmHeight);
  554. if (g_bBiDi)
  555. {
  556. BitBlt(hdc,
  557. lpani->rc.right-cx,
  558. lpani->rc.top - tm.tmInternalLeading,
  559. cx,
  560. cy,
  561. hdcMem,
  562. 0,
  563. 0,
  564. SRCCOPY);
  565. }
  566. else
  567. {
  568. BitBlt(hdc,
  569. lpani->rc.left,
  570. lpani->rc.top - tm.tmInternalLeading,
  571. cx,
  572. cy,
  573. hdcMem,
  574. 0,
  575. 0,
  576. SRCCOPY);
  577. }
  578. SetTextColor(hdcMem, crOld);
  579. break;
  580. }
  581. case 1:
  582. if (g_bBiDi)
  583. BitBlt(hdcMem, 0, 0, cx, cy, g_hdcCache, lpani->rc.right-cx, lpani->rc.top, SRCCOPY);
  584. else
  585. BitBlt(hdcMem, 0, 0, cx, cy, g_hdcCache, lpani->rc.left, lpani->rc.top, SRCCOPY);
  586. for (i = 0; i < cy ; i+=4)
  587. {
  588. if (g_bBiDi)
  589. BitBlt(hdcMem, 0, 0, cx, cy, g_hdcCache, lpani->rc.right-cx, lpani->rc.top, SRCCOPY);
  590. else
  591. BitBlt(hdcMem, 0, 0, cx, cy, g_hdcCache, lpani->rc.left, lpani->rc.top, SRCCOPY);
  592. MergeBlt(lpstr, hdcMem, 0, 0, cx, i, hdcText, 0, 0, cx, cy,
  593. lpani->col, lpani->colShadow, lpani->bShadow, TRUE, &tm, iLineSpace, &rc);
  594. PaintBulletIfNeeded(hdcMem, 0, 0, tm.tmHeight);
  595. if (g_bBiDi)
  596. BitBlt(hdc, lpani->rc.right-cx, lpani->rc.top, cx, cy, hdcMem, 0, 0, SRCCOPY);
  597. else
  598. BitBlt(hdc, lpani->rc.left, lpani->rc.top, cx, cy, hdcMem, 0, 0, SRCCOPY);
  599. MyWait(10000);
  600. }
  601. if (g_bBiDi)
  602. BitBlt(hdcMem, 0, 0, cx, cy, g_hdcCache, lpani->rc.right-cx, lpani->rc.top, SRCCOPY);
  603. else
  604. BitBlt(hdcMem, 0, 0, cx, cy, g_hdcCache, lpani->rc.left, lpani->rc.top, SRCCOPY);
  605. MergeBlt(lpstr, hdcMem, 0, 0, cx, cy, hdcText, 0, 0, cx, cy,
  606. lpani->col, lpani->colShadow, lpani->bShadow, FALSE, &tm, iLineSpace, &rc);
  607. PaintBulletIfNeeded(hdcMem, 0, 0, tm.tmHeight);
  608. if (g_bBiDi)
  609. BitBlt(hdc, lpani->rc.right-cx, lpani->rc.top, cx, cy, hdcMem, 0, 0, SRCCOPY);
  610. else
  611. BitBlt(hdc, lpani->rc.left, lpani->rc.top, cx, cy, hdcMem, 0, 0, SRCCOPY);
  612. break;
  613. case 2:
  614. DisplayString(hdcText, 0, 0, &tm, iLineSpace, &rc, &nNumLines, lpstr, LEFT);
  615. BitBlt(hdcMem, 0, 0, cx, cy,
  616. g_hdcCache, lpani->rc.left, lpani->rc.top, SRCCOPY);
  617. for (i = 0; i < cx ; i+=4)
  618. {
  619. BitBlt(hdcMem, 0, 0, cx, cy,
  620. g_hdcCache, lpani->rc.left, lpani->rc.top, SRCCOPY);
  621. MergeBlt(lpstr, hdcMem, 0, 0, i, cy,
  622. hdcText, 0, 0, cx, cy,
  623. lpani->col, lpani->colShadow, lpani->bShadow, TRUE,
  624. &tm, iLineSpace, &rc);
  625. PaintBulletIfNeeded(hdcMem, 0, 0, tm.tmHeight);
  626. BitBlt(hdc, lpani->rc.left, lpani->rc.top, cx, cy,
  627. hdcMem, 0, 0, SRCCOPY);
  628. MyWait(10000);
  629. }
  630. BitBlt(hdcMem, 0, 0, cx, cy,
  631. g_hdcCache, lpani->rc.left, lpani->rc.top, SRCCOPY);
  632. MergeBlt(lpstr, hdcMem, 0, 0, cx, cy,
  633. hdcText, 0, 0, cx, cy,
  634. lpani->col, lpani->colShadow, lpani->bShadow, FALSE,
  635. &tm, iLineSpace, &rc);
  636. PaintBulletIfNeeded(hdcMem, 0, 0, tm.tmHeight);
  637. BitBlt(hdc, lpani->rc.left, lpani->rc.top, cx, cy,
  638. hdcMem, 0, 0, SRCCOPY);
  639. break;
  640. case 3:
  641. nWait = 100;
  642. for (i = cxBB; i > lpani->rc.left; i -= CX_MOVE)
  643. {
  644. int xCur = i;
  645. BitBlt(hdc, xCur + cx, lpani->rc.top, CX_MOVE, cy,
  646. g_hdcCache, xCur + cx, lpani->rc.top, SRCCOPY);
  647. BitBlt(hdcMem, 0, 0, cxBB - xCur, cy,
  648. g_hdcCache, xCur, lpani->rc.top, SRCCOPY);
  649. MergeBlt(lpstr, hdcMem, 0, 0, cx, cy,
  650. hdcText, 0, 0, cx, cy,
  651. lpani->col, lpani->colShadow, lpani->bShadow, FALSE,
  652. &tm, iLineSpace, &rc);
  653. PaintBulletIfNeeded(hdcMem, 0, 0, tm.tmHeight);
  654. BitBlt(hdc, xCur, lpani->rc.top, cx, cy,
  655. hdcMem, 0, 0, SRCCOPY);
  656. MyWait(nWait * nWait);
  657. nWait++;
  658. }
  659. BitBlt(hdcMem, 0, 0, cx, cy,
  660. g_hdcCache, lpani->rc.left, lpani->rc.top, SRCCOPY);
  661. MergeBlt(lpstr, hdcMem, 0, 0, cx, cy,
  662. hdcText, 0, 0, cx, cy,
  663. lpani->col, lpani->colShadow, lpani->bShadow, FALSE,
  664. &tm, iLineSpace, &rc);
  665. PaintBulletIfNeeded(hdcMem, 0, 0, tm.tmHeight);
  666. BitBlt(hdc, lpani->rc.left, lpani->rc.top, cx, cy,
  667. hdcMem, 0, 0, SRCCOPY);
  668. BitBlt(hdc, lpani->rc.left + cx, lpani->rc.top, CX_MOVE, cy,
  669. g_hdcCache, lpani->rc.left + cx, lpani->rc.top, SRCCOPY);
  670. break;
  671. case 4:
  672. nWait = 100;
  673. nDelta = (lpani->rc.right - lpani->rc.left) / 10;
  674. x0 = cxBB;
  675. while (abs(nDelta) > CX_MOVE)
  676. {
  677. for (i = x0;
  678. abs(i - (lpani->rc.left - nDelta)) > CX_MOVE;
  679. i -= (CX_MOVE * (nDelta/ abs(nDelta))))
  680. {
  681. int xCur = i;
  682. BitBlt(hdc, xCur + cx, lpani->rc.top, CX_MOVE, cy,
  683. g_hdcCache, xCur + cx, lpani->rc.top, SRCCOPY);
  684. BitBlt(hdc, xCur - CX_MOVE, lpani->rc.top, CX_MOVE, cy,
  685. g_hdcCache, xCur - CX_MOVE, lpani->rc.top, SRCCOPY);
  686. BitBlt(hdcMem, 0, 0, cxBB - xCur, cy,
  687. g_hdcCache, xCur, lpani->rc.top, SRCCOPY);
  688. MergeBlt(lpstr, hdcMem, 0, 0, cx, cy,
  689. hdcText, 0, 0, cx, cy,
  690. lpani->col, lpani->colShadow, lpani->bShadow, FALSE,
  691. &tm, iLineSpace, &rc);
  692. PaintBulletIfNeeded(hdcMem, 0, 0, tm.tmHeight);
  693. BitBlt(hdc, xCur, lpani->rc.top, cx, cy,
  694. hdcMem, 0, 0, SRCCOPY);
  695. MyWait(nWait * nWait);
  696. nWait++;
  697. }
  698. nDelta *= 2;
  699. nDelta /= 3;
  700. nDelta = 0 - nDelta;
  701. x0 = i;
  702. }
  703. BitBlt(hdcMem, 0, 0, cx, cy,
  704. g_hdcCache, lpani->rc.left, lpani->rc.top, SRCCOPY);
  705. MergeBlt(lpstr, hdcMem, 0, 0, cx, cy,
  706. hdcText, 0, 0, cx, cy,
  707. lpani->col, lpani->colShadow, lpani->bShadow, FALSE,
  708. &tm, iLineSpace, &rc);
  709. PaintBulletIfNeeded(hdcMem, 0, 0, tm.tmHeight);
  710. BitBlt(hdc, lpani->rc.left, lpani->rc.top, cx, cy,
  711. hdcMem, 0, 0, SRCCOPY);
  712. BitBlt(hdc, lpani->rc.left + cx, lpani->rc.top, CX_MOVE, cy,
  713. g_hdcCache, lpani->rc.left + cx, lpani->rc.top, SRCCOPY);
  714. break;
  715. case 5:
  716. BitBlt(hdcMem, 0, 0, cxBB - lpani->rc.left, cy,
  717. g_hdcCache, lpani->rc.left, lpani->rc.top, SRCCOPY);
  718. DisplayString(hdcMem, 0, 0, &tm, iLineSpace, &rc, &nNumLines, lpstr, LEFT);
  719. for (i = 0; i < nLen; i++)
  720. {
  721. int nSize;
  722. int nNextSize;
  723. SIZE size;
  724. GetTextExtentPoint32(hdcMem, lpstr, i, &size);
  725. nSize = size.cx;
  726. GetTextExtentPoint32(hdcMem, lpstr, i+1, &size);
  727. nNextSize = size.cx - nSize;
  728. if (nSize + nNextSize > cx)
  729. break;
  730. PaintBulletIfNeeded(hdcMem, 0, 0, tm.tmHeight);
  731. BitBlt(hdc, lpani->rc.left, lpani->rc.top, nSize, cy,
  732. hdcMem, 0, 0, SRCCOPY);
  733. BitBlt(hdc, lpani->rc.left + nSize, lpani->rc.top, CX_MOVE, cy,
  734. g_hdcCache, lpani->rc.left + nSize, lpani->rc.top, SRCCOPY);
  735. for (j = cxBB; j > lpani->rc.left+nSize ; j-=CX_MOVE)
  736. {
  737. int xCur = j;
  738. int xPrev = j + nNextSize;
  739. PaintBulletIfNeeded(hdcMem, 0, 0, tm.tmHeight);
  740. BitBlt(hdc, xPrev, lpani->rc.top, CX_MOVE, cy,
  741. g_hdcCache, xPrev, lpani->rc.top, SRCCOPY);
  742. BitBlt(hdc, xCur, lpani->rc.top, nNextSize, cy,
  743. hdcMem, nSize, 0, SRCCOPY);
  744. MyWait(20000);
  745. }
  746. }
  747. PaintBulletIfNeeded(hdcMem, 0, 0, tm.tmHeight);
  748. BitBlt(hdc, lpani->rc.left, lpani->rc.top, cx, cy,
  749. hdcMem, 0, 0, SRCCOPY);
  750. BitBlt(hdc, lpani->rc.left + cx, lpani->rc.top, CX_MOVE, cy,
  751. g_hdcCache, lpani->rc.left + cx, lpani->rc.top, SRCCOPY);
  752. break;
  753. case 6:
  754. BitBlt(hdcMem, 0, 0, cxBB - lpani->rc.left, cy,
  755. g_hdcCache, lpani->rc.left, lpani->rc.top, SRCCOPY);
  756. DisplayString(hdcMem, 0, 0, &tm, iLineSpace, &rc, &nNumLines, lpstr, LEFT);
  757. for (i = 0; i < nLen; i++)
  758. {
  759. int nSize;
  760. int nNextSize;
  761. SIZE size;
  762. GetTextExtentPoint32(hdcMem, lpstr, i, &size);
  763. nSize = size.cx;
  764. GetTextExtentPoint32(hdcMem, lpstr, i+1, &size);
  765. nNextSize = size.cx - nSize;
  766. if (nSize + nNextSize > cx)
  767. break;
  768. PaintBulletIfNeeded(hdcMem, 0, 0, tm.tmHeight);
  769. BitBlt(hdc, lpani->rc.left, lpani->rc.top, nSize, cy,
  770. hdcMem, 0, 0, SRCCOPY);
  771. BitBlt(hdc, lpani->rc.left, lpani->rc.top - CY_MOVE, nSize, CY_MOVE,
  772. g_hdcCache, lpani->rc.left, lpani->rc.top - CY_MOVE, SRCCOPY);
  773. for (j = cyBB; j > lpani->rc.top; j-=CY_MOVE)
  774. {
  775. int yCur = j;
  776. int yPrev = j + cy;
  777. PaintBulletIfNeeded(hdcMem, 0, 0, tm.tmHeight);
  778. BitBlt(hdc, lpani->rc.left+nSize, yPrev, nNextSize, CY_MOVE,
  779. g_hdcCache, lpani->rc.left+nSize, yPrev, SRCCOPY);
  780. BitBlt(hdc, lpani->rc.left+nSize, yCur, nNextSize, cy,
  781. hdcMem, nSize, 0, SRCCOPY);
  782. MyWait(20000);
  783. }
  784. }
  785. PaintBulletIfNeeded(hdcMem, 0, 0, tm.tmHeight);
  786. BitBlt(hdc, lpani->rc.left, lpani->rc.top, cx, cy,
  787. hdcMem, 0, 0, SRCCOPY);
  788. BitBlt(hdc, lpani->rc.left, lpani->rc.top + cy, cx, CY_MOVE,
  789. g_hdcCache, lpani->rc.left, lpani->rc.top + cy, SRCCOPY);
  790. break;
  791. }
  792. SelectObject(hdcMem, hbmpOld);
  793. SelectObject(hdcText, hbrOldText);
  794. SelectObject(hdcText, hbmpOldText);
  795. SelectObject(hdcText, hfontOld);
  796. SelectObject(hdcMem, hfontOld);
  797. exit:
  798. if (hbmpText)
  799. DeleteObject(hbmpText);
  800. if (hdcText)
  801. DeleteDC(hdcText);
  802. if (hbmpMem)
  803. DeleteObject(hbmpMem);
  804. if (hdcMem)
  805. DeleteDC(hdcMem);
  806. if (hbrWhite)
  807. {
  808. DeleteObject(hbrWhite);
  809. }
  810. if (hbrBlack)
  811. {
  812. DeleteObject(hbrBlack);
  813. }
  814. return nNumLines;
  815. }
  816. void AnimateNext()
  817. {
  818. if (g_uiAnimateIndex != (UINT)-1)
  819. {
  820. g_uiAnimateIndex++;
  821. if (bb_text[dwBBTextType][g_uiAnimateIndex].uiTitle == 0)
  822. g_uiAnimateIndex = 0;
  823. }
  824. }
  825. BOOL InitAnimate(HWND hwnd, HDC hdc)
  826. {
  827. int cxBB;
  828. int cyBB;
  829. RECT rcBB;
  830. HDC hdcMem;
  831. RECT rcBBToParent;
  832. BOOL retval = FALSE;
  833. if (GetClientRect(hwnd, &rcBB))
  834. {
  835. cxBB = rcBB.right - rcBB.left;
  836. cyBB = rcBB.bottom - rcBB.top;
  837. if (g_hbmp)
  838. {
  839. SelectObject(g_hdcCache, g_hbmpOldCache);
  840. DeleteObject(g_hbmp);
  841. g_hbmp = NULL;
  842. }
  843. if (g_hdcCache)
  844. {
  845. DeleteDC(g_hdcCache);
  846. g_hdcCache = NULL;
  847. }
  848. g_hdcCache = CreateCompatibleDC(hdc);
  849. g_hbmp = CreateCompatibleBitmap(hdc, cxBB, cyBB);
  850. if (g_hdcCache && g_hbmp)
  851. {
  852. g_hbmpOldCache = SelectObject(g_hdcCache, g_hbmp);
  853. hdcMem = GetBackgroundBuffer();
  854. GetRectInParent(hwnd, &rcBB, &rcBBToParent);
  855. retval = BitBlt(g_hdcCache,
  856. 0,
  857. 0,
  858. cxBB,
  859. cyBB,
  860. hdcMem,
  861. rcBBToParent.left,
  862. rcBBToParent.top,
  863. SRCCOPY);
  864. }
  865. }
  866. return retval;
  867. }
  868. void TerminateAnimate()
  869. {
  870. RestoreCachedRect();
  871. if (g_hbmp)
  872. {
  873. SelectObject(g_hdcCache, g_hbmpOldCache);
  874. DeleteObject(g_hbmp);
  875. g_hbmp = NULL;
  876. }
  877. if (g_hdcCache)
  878. {
  879. DeleteDC(g_hdcCache);
  880. g_hdcCache = NULL;
  881. }
  882. GetDeleteFontHandle(FONT_DELETE);
  883. }
  884. /*********************************************************************************
  885. *
  886. * Animate()
  887. *
  888. * Main animation function.
  889. *
  890. *********************************************************************************/
  891. void Animate(HDC hdc)
  892. {
  893. RECT rc;
  894. ANISTRINGFORM ani;
  895. int nPadBuffer, nLinePad, nWndHeight, nNumLines = 0;
  896. TCHAR sz[MAX_STRING];
  897. TCHAR szText[MAX_STRING];
  898. int iOldMapMode;
  899. if (g_uiAnimateIndex == (UINT)-1)
  900. return;
  901. if (!GetClientRect(GetBBHwnd(), &rc))
  902. {
  903. return;
  904. }
  905. iOldMapMode = SetMapMode(hdc, MM_TEXT);
  906. if(g_nAnimID != 7)
  907. {
  908. RestoreRect(hdc, &rc, AB_HOR_POS);
  909. }
  910. rc.left = g_cxBillBrdHMargin;
  911. rc.top = g_cyBillBrdTitleTop;
  912. rc.right = g_cxBillBrdTitleWidth;
  913. rc.bottom = g_cyBillBrdHeight;
  914. nWndHeight = GetSystemMetrics(SM_CYSCREEN);
  915. nPadBuffer = nWndHeight / 80; // 6 pixels @ 640x480
  916. nLinePad = nWndHeight / 80; // 6 pixels @ 640x480
  917. ani.col = g_colTitle;
  918. ani.colShadow = g_colTitleShadow;
  919. ani.bShadow = g_bTitleShadow;
  920. ani.uiLineHeightx2 = 2;
  921. ani.rc.top = rc.top;
  922. ani.rc.bottom = rc.bottom;
  923. ani.rc.left = rc.left;
  924. ani.rc.right = rc.right;
  925. ani.hFont = GetDeleteFontHandle(FONT_TITLE);
  926. if (LoadString(g_hInstance, bb_text[dwBBTextType][g_uiAnimateIndex].uiTitle, (LPTSTR)sz, sizeof(sz)/sizeof(TCHAR)))
  927. {
  928. nNumLines = AnimateString(hdc, sz, &ani, 0, g_nAnimID);
  929. }
  930. rc.top += (g_nTFontHeight * 2 + nLinePad) * nNumLines;
  931. rc.right = g_cxBillBrdBodyWidth;
  932. if (LoadString(g_hInstance, bb_text[dwBBTextType][g_uiAnimateIndex].uiText, (LPTSTR)sz, sizeof(sz)/sizeof(TCHAR)))
  933. {
  934. UINT i = 0;
  935. // Process the string so that we can have paragraphs.
  936. // /r/n marks end of line
  937. //
  938. while (sz[i] != TEXT('\0'))
  939. {
  940. UINT j = 0;
  941. // see if the author has a hard line break
  942. // If, just give the line until the line break to display
  943. // The rest is done hte next time around.
  944. while ((sz[i] != TEXT('\0')) && (sz[i] != TEXT('\r')) && (sz[i] != TEXT('\n')) )
  945. {
  946. szText[j] = sz[i];
  947. j++;
  948. i++;
  949. }
  950. // if there is a line break character, skip this one.
  951. if (sz[i] != TEXT('\0'))
  952. i++;
  953. szText[j] = TEXT('\0');
  954. ani.col = g_colText;
  955. ani.colShadow = g_colTextShadow;
  956. ani.bShadow = g_bTextShadow;
  957. ani.uiLineHeightx2 = 3;
  958. ani.rc.top = rc.top;
  959. ani.rc.bottom = rc.bottom;
  960. ani.rc.left = rc.left;
  961. ani.rc.right = rc.right;
  962. ani.hFont = GetDeleteFontHandle(FONT_TEXT);
  963. nNumLines = AnimateString(hdc, szText, &ani, g_nBLineSpace, g_nAnimID);
  964. if (*szText)
  965. {
  966. rc.top += (g_nBFontHeight * (100 + g_nBLineSpace) / 100 + nLinePad) * nNumLines;
  967. rc.bottom += (g_nBFontHeight * (100 + g_nBLineSpace) / 100 + nLinePad) * nNumLines;
  968. }
  969. else
  970. {
  971. rc.top += g_nBFontHeight * (100 + g_nBLineSpace) / 100 + nPadBuffer;
  972. rc.bottom += g_nBFontHeight * (100 + g_nBLineSpace) / 100 + nPadBuffer;
  973. }
  974. // assume that there are allways \r\n for one line break. Skip the other one
  975. if ((sz[i] != TEXT('\0')) && ((sz[i] == TEXT('\r')) || (sz[i] == TEXT('\n')) ) )
  976. i++;
  977. }
  978. }
  979. SetMapMode(hdc, iOldMapMode);
  980. }
  981. /*****************************************************************************************
  982. * This function displays a text string on the given coordinates. It figures
  983. * out word wraping and distance between lines based on the font. the pNumLines
  984. * param is set to indicate the num of lines output after wrapping text(NULL if failed).
  985. * Returns The result from TextOut.
  986. *****************************************************************************************/
  987. BOOL DisplayString(
  988. HDC hdc,
  989. int x,
  990. int y,
  991. TEXTMETRIC* lptm,
  992. int iLineSpace,
  993. RECT* lprc,
  994. LPINT pNumLines,
  995. LPTSTR szTextOut,
  996. WORD wfPlacement)
  997. {
  998. LPTSTR szWorkBuffer = NULL;
  999. BOOL ret = FALSE;
  1000. int newX = 0;
  1001. // The multiplication factor 2 handle the worst case scenario, in which
  1002. // every character can have a line break followed by it, but no '|'
  1003. // character is specified in the string.
  1004. szWorkBuffer = (LPTSTR)HeapAlloc(
  1005. GetProcessHeap(),
  1006. 0,
  1007. (lstrlen(szTextOut) + 1) * sizeof(TCHAR) * 2);
  1008. if (szWorkBuffer)
  1009. {
  1010. lstrcpy(szWorkBuffer, szTextOut);
  1011. if(CheckForBulletAndRemoveMarker(szWorkBuffer, &newX))
  1012. {
  1013. newX += (x + 10); //leave space for the bullet bitmap
  1014. }
  1015. else
  1016. {
  1017. newX = x;
  1018. }
  1019. *pNumLines = WrapText(hdc, newX, lprc, szWorkBuffer);
  1020. ret = DrawWrapText(hdc, lptm, iLineSpace, newX, y, lprc, wfPlacement, *pNumLines, szWorkBuffer);
  1021. HeapFree(GetProcessHeap(), 0, szWorkBuffer);
  1022. }
  1023. return ret;
  1024. }
  1025. int WrapText(
  1026. IN HDC hdc,
  1027. IN int x,
  1028. IN RECT* lprc,
  1029. IN OUT LPTSTR szBBResource)
  1030. {
  1031. BOOL bDoneText = FALSE;
  1032. int iNumLines = 0;
  1033. LPTSTR pBBResource = szBBResource;
  1034. LPTSTR szRemainedWords = NULL;
  1035. TCHAR szCurrentLine[MAX_STRING];
  1036. TCHAR szCurrentLineWords[MAX_STRING];
  1037. LPTSTR pRemainedWords = NULL;
  1038. LPTSTR pCurrentLineWords = NULL;
  1039. LPTSTR pCurrentLine = NULL;
  1040. SIZE sz;
  1041. LONG uiRCWidth;
  1042. szRemainedWords = (LPTSTR)HeapAlloc(
  1043. GetProcessHeap(),
  1044. 0,
  1045. (lstrlen(szBBResource) + 1) * sizeof(TCHAR));
  1046. if(szRemainedWords)
  1047. {
  1048. lstrcpy(szRemainedWords, szBBResource);
  1049. }
  1050. else
  1051. {
  1052. return 0;
  1053. }
  1054. uiRCWidth = lprc->right - lprc->left - x;
  1055. while(!bDoneText)
  1056. {
  1057. *szCurrentLine = TEXT('\0');
  1058. pCurrentLineWords = szCurrentLineWords;
  1059. pRemainedWords = szRemainedWords;
  1060. pCurrentLine = szCurrentLine;
  1061. RemoveLineBreakChar(pRemainedWords, pCurrentLine);
  1062. GetTextExtentPoint32(hdc, pCurrentLine, lstrlen(pCurrentLine), &sz);
  1063. ZeroMemory( szCurrentLine , sizeof(szCurrentLine));
  1064. ZeroMemory( szCurrentLineWords , sizeof(szCurrentLineWords));
  1065. if(uiRCWidth >= sz.cx)
  1066. {
  1067. RemoveLineBreakChar(pRemainedWords, pCurrentLine);
  1068. bDoneText = TRUE;
  1069. }
  1070. else
  1071. {
  1072. // break up string into displayable segment
  1073. BOOL bDoneLine = FALSE;
  1074. while(!bDoneLine)
  1075. {
  1076. BOOL bDoneWord = FALSE;
  1077. while(!bDoneWord)
  1078. {
  1079. *pCurrentLineWords = TEXT('\0'); //null terminate for GetTextExtent
  1080. GetTextExtentPoint32(hdc, szCurrentLineWords, lstrlen(szCurrentLineWords), &sz);
  1081. if(*pRemainedWords == TEXT('|')) //Line break char (potential line break)
  1082. {
  1083. pRemainedWords = CharNext(pRemainedWords);
  1084. bDoneWord = TRUE;
  1085. }
  1086. else if( *pRemainedWords == TEXT('\0')) //end of string
  1087. {
  1088. bDoneWord = TRUE;
  1089. bDoneLine = TRUE;
  1090. }
  1091. else if((sz.cx + 2 >= uiRCWidth ) && (lstrcmp(szCurrentLine, TEXT("") ) == 0))
  1092. //if the word is too big to fit on one line then break out. Code outside this
  1093. //loop will add a space in word and this will cause a line break.
  1094. {
  1095. bDoneWord = TRUE;
  1096. }
  1097. else
  1098. {
  1099. *pCurrentLineWords = *pRemainedWords;
  1100. #ifndef UNICODE
  1101. if(IsDBCSLeadByte(*pCurrentLineWords))
  1102. {
  1103. *(pCurrentLineWords+1) = *(pRemainedWords+1);
  1104. }
  1105. #endif
  1106. pCurrentLineWords = CharNext(pCurrentLineWords);
  1107. pRemainedWords = CharNext(pRemainedWords);
  1108. }
  1109. }
  1110. //Check if the current buffers extent is more than the width
  1111. GetTextExtentPoint32(hdc, szCurrentLineWords, lstrlen(szCurrentLineWords), &sz);
  1112. if((sz.cx >= uiRCWidth ) && (lstrcmp(szCurrentLine, TEXT("") ) != 0))
  1113. {
  1114. //string is too big && saved str is not empty(use previously saved str)
  1115. bDoneLine = TRUE;
  1116. }
  1117. else
  1118. {
  1119. *pCurrentLineWords = TEXT('\0'); //dont inc because we want to overwrite later
  1120. lstrcpy(szCurrentLine, szCurrentLineWords); //append next word to string
  1121. lstrcpy(szRemainedWords, pRemainedWords);
  1122. pRemainedWords = szRemainedWords;
  1123. }
  1124. }
  1125. }
  1126. lstrcpy(pBBResource, szCurrentLine);
  1127. pBBResource = &(pBBResource[lstrlen(szCurrentLine)+1]);
  1128. iNumLines++;
  1129. }
  1130. HeapFree(GetProcessHeap(), 0, szRemainedWords);
  1131. return iNumLines;
  1132. }
  1133. BOOL DrawWrapText(
  1134. IN HDC hdc,
  1135. IN TEXTMETRIC* lptm,
  1136. IN int iLineSpace,
  1137. IN int x,
  1138. IN int y,
  1139. IN RECT* lprc,
  1140. IN WORD wfPlacement,
  1141. IN int iLineCount,
  1142. IN LPTSTR szLines)
  1143. {
  1144. UINT uiTxtAlign = 0;
  1145. BOOL bRet = TRUE;
  1146. SIZE sz;
  1147. int Ly = 0;
  1148. int Lx = 0;
  1149. LPTSTR szText = szLines;
  1150. int i = 0;
  1151. if (g_bBiDi)
  1152. {
  1153. uiTxtAlign = GetTextAlign(hdc);
  1154. SetTextAlign(hdc, uiTxtAlign|TA_RIGHT|TA_RTLREADING);
  1155. }
  1156. while (TRUE)
  1157. {
  1158. if(wfPlacement == CENTER)
  1159. {
  1160. //Get the dimensions of current string
  1161. GetTextExtentPoint32(hdc, szText, lstrlen(szText), &sz);
  1162. //x co-ord for TextOut
  1163. if (g_bBiDi)
  1164. Lx = lprc->right - (((lprc->right - lprc->left) - sz.cx)/2);
  1165. else
  1166. Lx = lprc->left + (((lprc->right - lprc->left) - sz.cx)/2);
  1167. }
  1168. else
  1169. {
  1170. //x co-ord for TextOut
  1171. if (g_bBiDi)
  1172. Lx = lprc->right - x;
  1173. else
  1174. Lx = lprc->left + x;
  1175. }
  1176. //calculate (y co-ord) for TextOut
  1177. Ly = y + lptm->tmHeight * i + lptm->tmHeight * i * iLineSpace / 100;
  1178. if (g_bBiDi)
  1179. {
  1180. bRet = ExtTextOut(hdc, Lx, Ly, ETO_RTLREADING, NULL, szText, lstrlen(szText), NULL);
  1181. }
  1182. else
  1183. {
  1184. bRet = TextOut(hdc, Lx, Ly, szText, lstrlen(szText));
  1185. }
  1186. if (!bRet) break;
  1187. if (++i >= iLineCount) break;
  1188. szText = &(szText[lstrlen(szText)+1]);
  1189. }
  1190. if (g_bBiDi)
  1191. {
  1192. SetTextAlign(hdc, uiTxtAlign);
  1193. }
  1194. return bRet;
  1195. }
  1196. LPTSTR
  1197. StringReverseChar(
  1198. LPTSTR psz,
  1199. TCHAR ch)
  1200. {
  1201. PTCHAR pch;
  1202. pch = psz + lstrlen(psz);
  1203. while (pch != psz && *pch != ch)
  1204. {
  1205. pch = CharPrev(psz, pch);
  1206. }
  1207. if (*pch != ch)
  1208. {
  1209. pch = NULL;
  1210. }
  1211. return pch;
  1212. }
  1213. VOID ImproveWrap(
  1214. IN OUT LPTSTR szLines,
  1215. IN OUT PINT piNumLine,
  1216. IN LPTSTR szOrigText,
  1217. IN INT cchOrigText
  1218. )
  1219. /*++
  1220. Routine Description:
  1221. Force to wrap the last 'wrappable' part of the last line, if the last line
  1222. contains more than one 'wrappable' parts.
  1223. Arguments:
  1224. szLines - The result of WrapText, contains lines delimited by '\0'
  1225. iNumLine - Number of line in szLines
  1226. szOrigText - The original text that produces szLines, null-terminated
  1227. cchOrigText - Number of characters in szOrigText
  1228. Return Values:
  1229. szLines - if the last line contains more than one 'wrappable' parts,
  1230. szLines is modified.
  1231. --*/
  1232. {
  1233. #define NEAT_WRAPPING_RATIO 0.75
  1234. PTCHAR pLastLineStart;
  1235. int cchLastLine;
  1236. PTCHAR pLastWrapPartStart;
  1237. int cchLastWrapPart;
  1238. int iLineRemain;
  1239. pLastLineStart = szLines;
  1240. iLineRemain = *piNumLine;
  1241. while (iLineRemain > 1)
  1242. {
  1243. pLastLineStart += lstrlen(pLastLineStart) + 1;
  1244. iLineRemain--;
  1245. }
  1246. cchLastLine = lstrlen(pLastLineStart);
  1247. pLastWrapPartStart = StringReverseChar(szOrigText, (TCHAR)'|');
  1248. if (pLastWrapPartStart != NULL)
  1249. {
  1250. pLastWrapPartStart = CharNext(pLastWrapPartStart);
  1251. cchLastWrapPart = lstrlen(pLastWrapPartStart);
  1252. if ((cchLastLine * NEAT_WRAPPING_RATIO) > (double)cchLastWrapPart)
  1253. {
  1254. LPTSTR szTmp = pLastLineStart + (cchLastLine - cchLastWrapPart);
  1255. MoveMemory(szTmp + 1, szTmp, (cchLastWrapPart + 1) * sizeof(TCHAR));
  1256. szTmp[0] = (TCHAR)'\0';
  1257. (*piNumLine)++;
  1258. }
  1259. }
  1260. }