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

711 lines
18 KiB

  1. //---------------------------------------------------------------------------
  2. //
  3. // Copyright (c) Microsoft Corporation 1993-1994
  4. //
  5. // File: dobj.c
  6. //
  7. // This file contains support routines for the reconciliation-action
  8. // control class code
  9. //
  10. //
  11. // History:
  12. // 09-13-93 ScottH Extracted from recact.c
  13. //
  14. //---------------------------------------------------------------------------
  15. ///////////////////////////////////////////////////// INCLUDES
  16. #include "brfprv.h" // common headers
  17. #include "res.h"
  18. #include "recact.h"
  19. #include "dobj.h"
  20. ///////////////////////////////////////////////////// CONTROLLING DEFINES
  21. ///////////////////////////////////////////////////// DEFINES
  22. #define DT_CALCWRAP (DT_CALCRECT | DT_CENTER | DT_WORDBREAK | DT_NOPREFIX)
  23. #define DT_CALC (DT_CALCRECT | DT_CENTER | DT_SINGLELINE | DT_NOPREFIX)
  24. /*----------------------------------------------------------
  25. Purpose: Formats the given path to the correct location format
  26. Returns: --
  27. Cond: --
  28. */
  29. void PRIVATE FormatLocationPath(
  30. LPCTSTR pszPath,
  31. LPTSTR pszBuffer) // Must be MAX_PATH
  32. {
  33. UINT ids;
  34. TCHAR szBrfDir[MAX_PATH];
  35. LPCTSTR psz;
  36. LPTSTR pszMsg;
  37. // The format for the directory location is:
  38. //
  39. // Inside briefcase: "In Briefcase"
  40. // Below briefcase: "In Briefcase\FolderName"
  41. // Outside briefcase: "In FullPath"
  42. //
  43. // We assume that paths outside the current briefcase
  44. // never consist of a briefcase name of another.
  45. //
  46. if (PathGetLocality(pszPath, szBrfDir) != PL_FALSE)
  47. {
  48. // Inside the briefcase
  49. psz = &pszPath[lstrlen(szBrfDir)];
  50. ids = IDS_InBriefcase;
  51. }
  52. else
  53. {
  54. // Outside the briefcase
  55. psz = pszPath;
  56. ids = IDS_InLocation;
  57. }
  58. if (ConstructMessage(&pszMsg, g_hinst, MAKEINTRESOURCE(ids), psz))
  59. {
  60. lstrcpy(pszBuffer, pszMsg);
  61. GFree(pszMsg);
  62. }
  63. else
  64. *pszBuffer = 0;
  65. }
  66. /*----------------------------------------------------------
  67. Purpose: Return the string describing the status of this sideitem
  68. Returns: ptr to status string
  69. Cond: --
  70. */
  71. LPTSTR PRIVATE SideItem_GetStatus(
  72. LPSIDEITEM this,
  73. LPTSTR pszBuf,
  74. UINT cchBuf)
  75. {
  76. switch (this->uState)
  77. {
  78. case SI_CHANGED:
  79. return SzFromIDS(IDS_STATE_Changed, pszBuf, cchBuf);
  80. case SI_UNCHANGED:
  81. return SzFromIDS(IDS_STATE_Unchanged, pszBuf, cchBuf);
  82. case SI_NEW:
  83. return SzFromIDS(IDS_STATE_NewFile, pszBuf, cchBuf);
  84. case SI_UNAVAILABLE:
  85. return SzFromIDS(IDS_STATE_Unavailable, pszBuf, cchBuf);
  86. case SI_NOEXIST:
  87. return SzFromIDS(IDS_STATE_DoesNotExist, pszBuf, cchBuf);
  88. case SI_DELETED:
  89. return SzFromIDS(IDS_STATE_Deleted, pszBuf, cchBuf);
  90. default:
  91. ASSERT(0);
  92. return NULL;
  93. }
  94. }
  95. /*----------------------------------------------------------
  96. Purpose: Displays the 3-liner: location, status, and timestamp
  97. Returns: --
  98. Cond: --
  99. */
  100. void PRIVATE SideItem_Display(
  101. LPSIDEITEM this,
  102. HDC hdc,
  103. LPRECT prc,
  104. int cxEllipses,
  105. int cyText)
  106. {
  107. TCHAR sz[MAX_PATH];
  108. TCHAR szBuf[MAXBUFLEN];
  109. LPTSTR psz;
  110. RECT rc = *prc;
  111. // Directory location.
  112. FormatLocationPath(this->pszDir, sz);
  113. MyDrawText(hdc, sz, &rc, MDT_LEFT | MDT_TRANSPARENT | MDT_ELLIPSES,
  114. cyText, cxEllipses, CLR_DEFAULT, CLR_DEFAULT);
  115. // Status string
  116. psz = SideItem_GetStatus(this, szBuf, ARRAYSIZE(szBuf));
  117. if (psz)
  118. {
  119. // Only bother with these two lines if the file actually
  120. // exists.
  121. rc.top += cyText;
  122. MyDrawText(hdc, psz, &rc, MDT_LEFT | MDT_TRANSPARENT,
  123. cyText, cxEllipses, CLR_DEFAULT, CLR_DEFAULT);
  124. // Date stamp. Skip this if this is a folder or unavailable.
  125. //
  126. if (SI_DELETED != this->uState &&
  127. SI_NOEXIST != this->uState &&
  128. SI_UNAVAILABLE != this->uState &&
  129. FS_COND_UNAVAILABLE != this->fs.fscond) // hack for folders
  130. {
  131. FileTimeToDateTimeString(&this->fs.ftMod, sz, ARRAYSIZE(sz));
  132. rc.top += cyText;
  133. MyDrawText(hdc, sz, &rc, MDT_LEFT | MDT_TRANSPARENT,
  134. cyText, cxEllipses, CLR_DEFAULT, CLR_DEFAULT);
  135. }
  136. }
  137. }
  138. /*----------------------------------------------------------
  139. Purpose: Return the bounding rect for a labelled image.
  140. Returns: --
  141. Cond: --
  142. */
  143. void PUBLIC ComputeImageRects(
  144. LPCTSTR psz,
  145. HDC hdc,
  146. LPPOINT pptInOut,
  147. LPRECT prcWhole, // May be NULL
  148. LPRECT prcLabel, // May be NULL
  149. int cxIcon,
  150. int cyIcon,
  151. int cxIconSpacing,
  152. int cyText)
  153. {
  154. RECT rc;
  155. int yLabel;
  156. int cxLabel;
  157. int cyLabel;
  158. int cchLabel;
  159. POINT pt;
  160. ASSERT(psz);
  161. // Set our minimum rect size for icon spacing
  162. if (cxIconSpacing < cxIcon)
  163. cxIconSpacing = cxIcon + g_cxIconMargin * 2;
  164. // Upon entry, *pptInOut is expected to be the upper left corner of the
  165. // icon-spacing rect. This function will set it to the upper left
  166. // corner of the icon itself.
  167. pt.x = pptInOut->x + (cxIconSpacing - cxIcon) / 2;
  168. pt.y = pptInOut->y + g_cyIconMargin;
  169. // Determine rectangle of label with wrap
  170. rc.left = rc.top = rc.bottom = 0;
  171. rc.right = cxIconSpacing - g_cxLabelMargin * 2;
  172. cchLabel = lstrlen(psz);
  173. if (0 < cchLabel)
  174. {
  175. DrawText(hdc, psz, cchLabel, &rc, DT_CALCWRAP);
  176. }
  177. else
  178. {
  179. rc.bottom = rc.top + cyText;
  180. }
  181. yLabel = pptInOut->y + g_cyIconMargin + cyIcon + g_cyLabelSpace;
  182. cxLabel = (rc.right - rc.left) + 2 * g_cxLabelMargin;
  183. cyLabel = rc.bottom - rc.top;
  184. if (prcWhole)
  185. {
  186. prcWhole->left = pptInOut->x;
  187. prcWhole->right = prcWhole->left + cxIconSpacing;
  188. prcWhole->top = pptInOut->y;
  189. prcWhole->bottom = max(prcWhole->top + g_cyIconSpacing,
  190. yLabel + cyLabel + g_cyLabelSpace);
  191. }
  192. if (prcLabel)
  193. {
  194. prcLabel->left = pptInOut->x + ((cxIconSpacing - cxLabel) / 2);
  195. prcLabel->right = prcLabel->left + cxLabel;
  196. prcLabel->top = yLabel;
  197. prcLabel->bottom = prcLabel->top + cyLabel;
  198. }
  199. *pptInOut = pt;
  200. }
  201. /*----------------------------------------------------------
  202. Purpose: Set the colors for the given HDC. The previous colors
  203. are stored in pcrText and pcrBk.
  204. Returns: uStyle to pass to ImageList_Draw (specific to images only)
  205. Cond: --
  206. */
  207. UINT PRIVATE Dobj_SetColors(
  208. LPDOBJ this,
  209. HDC hdc,
  210. UINT uState,
  211. COLORREF clrBkgnd)
  212. {
  213. COLORREF clrText;
  214. COLORREF clrBk;
  215. UINT uStyleILD = ILD_NORMAL;
  216. BOOL bSetColors = FALSE;
  217. BOOL bDiffer;
  218. BOOL bMenu;
  219. BOOL bDisabled;
  220. // Determine selection colors
  221. //
  222. bDiffer = IsFlagSet(this->uFlags, DOF_DIFFER);
  223. bMenu = IsFlagSet(this->uFlags, DOF_MENU);
  224. bDisabled = IsFlagSet(this->uFlags, DOF_DISABLED);
  225. switch (this->uKind)
  226. {
  227. case DOK_STRING:
  228. case DOK_IDS:
  229. case DOK_SIDEITEM:
  230. bSetColors = TRUE;
  231. break;
  232. }
  233. // Set the text and background colors
  234. //
  235. if (bSetColors)
  236. {
  237. if (bDiffer)
  238. {
  239. // Make the colors differ based on selection state
  240. //
  241. if (bMenu)
  242. {
  243. if (bDisabled)
  244. clrText = GetSysColor(COLOR_GRAYTEXT);
  245. else
  246. clrText = GetSysColor(ColorMenuText(uState));
  247. clrBk = GetSysColor(ColorMenuBk(uState));
  248. }
  249. else
  250. {
  251. if (bDisabled)
  252. clrText = GetSysColor(COLOR_GRAYTEXT);
  253. else
  254. clrText = GetSysColor(ColorText(uState));
  255. clrBk = GetSysColor(ColorBk(uState));
  256. }
  257. }
  258. else
  259. {
  260. // Transparent colors
  261. //
  262. if (bMenu)
  263. {
  264. if (bDisabled)
  265. clrText = GetSysColor(COLOR_GRAYTEXT);
  266. else
  267. clrText = GetSysColor(COLOR_MENUTEXT);
  268. clrBk = GetSysColor(COLOR_MENU);
  269. }
  270. else
  271. {
  272. if (bDisabled)
  273. clrText = GetSysColor(COLOR_GRAYTEXT);
  274. else
  275. clrText = GetSysColor(COLOR_WINDOWTEXT);
  276. clrBk = clrBkgnd;
  277. }
  278. }
  279. SetTextColor(hdc, clrText);
  280. SetBkColor(hdc, clrBk);
  281. }
  282. return uStyleILD;
  283. }
  284. /*----------------------------------------------------------
  285. Purpose: Draw the menu image and text
  286. Returns: --
  287. Cond: --
  288. */
  289. void PRIVATE Dobj_DrawMenuImage(
  290. LPDOBJ this,
  291. HDC hdc,
  292. UINT uState,
  293. int cyText,
  294. COLORREF clrBkgnd)
  295. {
  296. UINT uStyleILD;
  297. UINT uFlagsETO;
  298. LPCTSTR psz;
  299. TCHAR szIDS[MAXBUFLEN];
  300. int cch;
  301. HIMAGELIST himl = this->himl;
  302. COLORREF clrText;
  303. COLORREF clrBk;
  304. int x;
  305. int y;
  306. int cxIcon;
  307. RECT rc;
  308. if (IsFlagSet(this->uFlags, DOF_USEIDS))
  309. psz = SzFromIDS(PtrToUlong(this->lpvObject), szIDS, ARRAYSIZE(szIDS));
  310. else
  311. psz = (LPCTSTR)this->lpvObject;
  312. ASSERT(psz);
  313. cch = lstrlen(psz);
  314. ImageList_GetImageRect(himl, this->iImage, &rc);
  315. cxIcon = rc.right-rc.left;
  316. // Draw the text first
  317. uFlagsETO = ETO_OPAQUE | ETO_CLIPPED;
  318. x = this->rcLabel.left + g_cxMargin + cxIcon + g_cxMargin;
  319. y = this->rcLabel.top + ((this->rcLabel.bottom - this->rcLabel.top - cyText) / 2);
  320. if (IsFlagSet(this->uFlags, DOF_DISABLED) &&
  321. IsFlagClear(uState, ODS_SELECTED))
  322. {
  323. int imodeOld;
  324. COLORREF crOld;
  325. // For disabled menu strings (not selected), we draw the string
  326. // twice. The first is offset down and to the right and drawn
  327. // in the 3D hilight color. The second time is the disabled text
  328. // color in the normal offset.
  329. //
  330. crOld = SetTextColor(hdc, GetSysColor(COLOR_3DHILIGHT));
  331. imodeOld = SetBkMode(hdc, TRANSPARENT);
  332. ExtTextOut(hdc, x+1, y+1, uFlagsETO, &this->rcLabel, psz, cch, NULL);
  333. // Reset back to original color. Also, turn off the opaqueness.
  334. //
  335. SetTextColor(hdc, crOld);
  336. uFlagsETO ^= ETO_OPAQUE;
  337. }
  338. if (IsFlagSet(this->uFlags, DOF_DISABLED))
  339. clrText = GetSysColor(COLOR_GRAYTEXT);
  340. else
  341. clrText = GetSysColor(ColorMenuText(uState));
  342. clrBk = GetSysColor(ColorMenuBk(uState));
  343. SetTextColor(hdc, clrText);
  344. SetBkColor(hdc, clrBk);
  345. ExtTextOut(hdc, x, y, uFlagsETO, &this->rcLabel, psz, cch, NULL);
  346. // Draw the image
  347. if (GetBkColor(hdc) == ImageList_GetBkColor(himl))
  348. uStyleILD = ILD_NORMAL; // Paint quicker
  349. else
  350. uStyleILD = ILD_TRANSPARENT;
  351. ImageList_Draw(himl, this->iImage, hdc, this->x, this->y, uStyleILD);
  352. }
  353. /*----------------------------------------------------------
  354. Purpose: Draw the icon image and label
  355. Returns: --
  356. Cond: --
  357. */
  358. void PRIVATE Dobj_DrawIconImage(
  359. LPDOBJ this,
  360. HDC hdc,
  361. UINT uState,
  362. int cxEllipses,
  363. int cyText,
  364. COLORREF clrBkgnd)
  365. {
  366. UINT uStyleILD;
  367. UINT uFlagsMDT;
  368. LPCTSTR psz;
  369. TCHAR szIDS[MAXBUFLEN];
  370. if (IsFlagSet(this->uFlags, DOF_USEIDS))
  371. psz = SzFromIDS(PtrToUlong(this->lpvObject), szIDS, ARRAYSIZE(szIDS));
  372. else
  373. psz = (LPCTSTR)this->lpvObject;
  374. ASSERT(psz);
  375. // Draw the image
  376. //
  377. if (IsFlagClear(this->uFlags, DOF_IGNORESEL))
  378. {
  379. uStyleILD = GetImageDrawStyle(uState);
  380. uFlagsMDT = IsFlagSet(uState, ODS_SELECTED) ? MDT_SELECTED : MDT_DESELECTED;
  381. }
  382. else
  383. {
  384. uStyleILD = ILD_NORMAL;
  385. uFlagsMDT = MDT_DESELECTED;
  386. ClearFlag(uState, ODS_FOCUS);
  387. }
  388. ImageList_Draw(this->himl, this->iImage, hdc, this->x, this->y, uStyleILD);
  389. // Draw the file label. Wrap if it is long.
  390. if (this->rcLabel.bottom - this->rcLabel.top > cyText)
  391. uFlagsMDT |= MDT_DRAWTEXT;
  392. MyDrawText(hdc, psz, &this->rcLabel, MDT_CENTER | uFlagsMDT, cyText,
  393. cxEllipses, CLR_DEFAULT, clrBkgnd);
  394. // (uState may have been changed above)
  395. if (IsFlagSet(uState, ODS_FOCUS))
  396. DrawFocusRect(hdc, &this->rcLabel);
  397. }
  398. #ifdef UNUSED
  399. /*----------------------------------------------------------
  400. Purpose: Draw a picture
  401. Returns: --
  402. Cond: --
  403. */
  404. void PRIVATE Dobj_DrawPicture(
  405. LPDOBJ this,
  406. HDC hdc,
  407. UINT uState,
  408. UINT uDrawStyle)
  409. {
  410. HIMAGELIST himl;
  411. HDC hdcMem;
  412. HBITMAP hbmp;
  413. BITMAP bm;
  414. RECT rc;
  415. int iImage;
  416. int cx;
  417. int x;
  418. int y;
  419. switch (this->uKind)
  420. {
  421. case DOK_BITMAP:
  422. hbmp = (HBITMAP)this->lpvObject;
  423. GetObject(hbmp, sizeof(BITMAP), &bm);
  424. cx = this->rcSrc.right - this->rcSrc.left;
  425. break;
  426. case DOK_ICON:
  427. cx = 32;
  428. break;
  429. }
  430. // We only align horizontally
  431. //
  432. y = this->y;
  433. if (IsFlagSet(this->uFlags, DOF_CENTER))
  434. x = this->x - (cx / 2);
  435. else if (IsFlagSet(this->uFlags, DOF_RIGHT))
  436. x = this->x - cx;
  437. else
  438. x = this->x;
  439. // Draw the object
  440. //
  441. switch (this->uKind)
  442. {
  443. case DOK_ICON:
  444. // FEATURE: we don't handle DOF_DIFFER for icons
  445. DrawIcon(hdc, x, y, (HICON)this->lpvObject);
  446. break;
  447. case DOK_BITMAP:
  448. hdcMem = CreateCompatibleDC(hdc);
  449. if (hdcMem)
  450. {
  451. SIZE size;
  452. SelectBitmap(hdcMem, hbmp);
  453. size.cx = this->rcSrc.right - this->rcSrc.left;
  454. size.cy = this->rcSrc.bottom - this->rcSrc.top;
  455. if (IsFlagSet(this->uFlags, DOF_MENU) &&
  456. IsFlagSet(this->uFlags, DOF_DISABLED) &&
  457. IsFlagClear(uState, ODS_SELECTED))
  458. {
  459. COLORREF crOld;
  460. // For disabled menu strings (not selected), we draw the bitmap
  461. // twice. The first is offset down and to the right and drawn
  462. // in the 3D hilight color. The second time is the disabled
  463. // color in the normal offset.
  464. //
  465. crOld = SetTextColor(hdc, GetSysColor(COLOR_3DHILIGHT));
  466. BitBlt(hdc, x+1, y+1, size.cx, size.cy, hdcMem, this->rcSrc.left,
  467. this->rcSrc.top, SRCCOPY);
  468. // Reset back to original color. Also, turn off the opaqueness.
  469. //
  470. SetTextColor(hdc, crOld);
  471. }
  472. BitBlt(hdc, x, y, size.cx, size.cy, hdcMem, this->rcSrc.left, this->rcSrc.top, SRCCOPY);
  473. DeleteDC(hdcMem);
  474. }
  475. break;
  476. }
  477. }
  478. #endif
  479. /*----------------------------------------------------------
  480. Purpose: Draw a string
  481. Returns: --
  482. Cond: --
  483. */
  484. void PRIVATE Dobj_DrawString(
  485. LPDOBJ this,
  486. HDC hdc,
  487. UINT uState,
  488. int cxEllipses,
  489. int cyText)
  490. {
  491. UINT ufAlignSav;
  492. ASSERT(this);
  493. // Prep the alignment
  494. //
  495. if (this->uFlags & (DOF_LEFT | DOF_CENTER | DOF_RIGHT))
  496. {
  497. UINT ufMode;
  498. ufMode = IsFlagSet(this->uFlags, DOF_CENTER) ? TA_CENTER :
  499. (IsFlagSet(this->uFlags, DOF_RIGHT) ? TA_RIGHT : TA_LEFT);
  500. ufAlignSav = SetTextAlign(hdc, ufMode);
  501. }
  502. // Draw the string
  503. //
  504. switch (this->uKind)
  505. {
  506. case DOK_IDS:
  507. case DOK_STRING:
  508. {
  509. TCHAR szBuf[MAXBUFLEN];
  510. LPTSTR lpsz;
  511. UINT uflag = ETO_OPAQUE;
  512. if (this->uKind == DOK_IDS)
  513. lpsz = SzFromIDS(PtrToUlong(this->lpvObject), szBuf, ARRAYSIZE(szBuf));
  514. else
  515. lpsz = (LPTSTR)this->lpvObject;
  516. if (!IsRectEmpty(&this->rcClip))
  517. uflag |= ETO_CLIPPED;
  518. if (IsFlagSet(this->uFlags, DOF_MENU) &&
  519. IsFlagSet(this->uFlags, DOF_DISABLED) &&
  520. IsFlagClear(uState, ODS_SELECTED))
  521. {
  522. int imodeOld;
  523. COLORREF crOld;
  524. // For disabled menu strings (not selected), we draw the string
  525. // twice. The first is offset down and to the right and drawn
  526. // in the 3D hilight color. The second time is the disabled text
  527. // color in the normal offset.
  528. //
  529. crOld = SetTextColor(hdc, GetSysColor(COLOR_3DHILIGHT));
  530. imodeOld = SetBkMode(hdc, TRANSPARENT);
  531. ExtTextOut(hdc, this->x+1, this->y+1, uflag, &this->rcClip, lpsz,
  532. lstrlen(lpsz), NULL);
  533. // Reset back to original color. Also, turn off the opaqueness.
  534. //
  535. SetTextColor(hdc, crOld);
  536. uflag ^= ETO_OPAQUE;
  537. }
  538. ExtTextOut(hdc, this->x, this->y, uflag, &this->rcClip, lpsz,
  539. lstrlen(lpsz), NULL);
  540. }
  541. break;
  542. case DOK_SIDEITEM:
  543. SideItem_Display((LPSIDEITEM)this->lpvObject, hdc, &this->rcClip,
  544. cxEllipses, cyText);
  545. break;
  546. }
  547. // Clean up
  548. //
  549. if (this->uFlags & (DOF_LEFT | DOF_CENTER | DOF_RIGHT))
  550. {
  551. SetTextAlign(hdc, ufAlignSav);
  552. }
  553. }
  554. /*----------------------------------------------------------
  555. Purpose: Draw an object
  556. Returns: --
  557. Cond: --
  558. */
  559. void PUBLIC Dobj_Draw(
  560. HDC hdc,
  561. LPDOBJ rgdobj,
  562. int cItems,
  563. UINT uState, // ODS_*
  564. int cxEllipses,
  565. int cyText,
  566. COLORREF clrBkgnd)
  567. {
  568. UINT uDrawStyle;
  569. LPDOBJ pdobj;
  570. int i;
  571. ASSERT(rgdobj);
  572. //Bug 199701, 199647, 199699
  573. if (g_bMirroredOS)
  574. {
  575. SetLayout(hdc, LAYOUT_RTL);
  576. }
  577. //End bug 199701, 199647, 199699
  578. for (i = 0, pdobj = rgdobj; i < cItems; i++, pdobj++)
  579. {
  580. if (IsFlagSet(pdobj->uFlags, DOF_NODRAW))
  581. continue ;
  582. uDrawStyle = Dobj_SetColors(pdobj, hdc, uState, clrBkgnd);
  583. // Draw the object
  584. //
  585. switch (pdobj->uKind)
  586. {
  587. case DOK_IMAGE:
  588. if (IsFlagSet(pdobj->uFlags, DOF_MENU))
  589. Dobj_DrawMenuImage(pdobj, hdc, uState, cyText, clrBkgnd);
  590. else
  591. Dobj_DrawIconImage(pdobj, hdc, uState, cxEllipses, cyText, clrBkgnd);
  592. break;
  593. #ifdef UNUSED
  594. case DOK_BITMAP:
  595. case DOK_ICON:
  596. Dobj_DrawPicture(pdobj, hdc, uState, uDrawStyle);
  597. break;
  598. #endif
  599. case DOK_IDS:
  600. case DOK_STRING:
  601. case DOK_SIDEITEM:
  602. Dobj_DrawString(pdobj, hdc, uState, cxEllipses, cyText);
  603. break;
  604. }
  605. }
  606. }