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.

731 lines
16 KiB

  1. /*************************************************************************
  2. **
  3. ** OLE 2 Sample Code
  4. **
  5. ** outlline.c
  6. **
  7. ** This file contains Line functions.
  8. **
  9. ** (c) Copyright Microsoft Corp. 1992 - 1993 All Rights Reserved
  10. **
  11. *************************************************************************/
  12. #include "outline.h"
  13. OLEDBGDATA
  14. extern LPOUTLINEAPP g_lpApp;
  15. /* Line_Init
  16. * ---------
  17. *
  18. * Init the calculated data of a line object
  19. */
  20. void Line_Init(LPLINE lpLine, int nTab, HDC hDC)
  21. {
  22. lpLine->m_lineType = UNKNOWNLINETYPE;
  23. lpLine->m_nTabLevel = nTab;
  24. lpLine->m_nTabWidthInHimetric = Line_CalcTabWidthInHimetric(lpLine,hDC);
  25. lpLine->m_nWidthInHimetric = 0;
  26. lpLine->m_nHeightInHimetric = 0;
  27. lpLine->m_fSelected = FALSE;
  28. #if defined( USE_DRAGDROP )
  29. lpLine->m_fDragOverLine = FALSE;
  30. #endif
  31. }
  32. /* Line_Edit
  33. * ---------
  34. *
  35. * Edit the line object.
  36. *
  37. * Returns TRUE if line was changed
  38. * FALSE if the line was NOT changed
  39. */
  40. BOOL Line_Edit(LPLINE lpLine, HWND hWndDoc, HDC hDC)
  41. {
  42. switch (lpLine->m_lineType) {
  43. case TEXTLINETYPE:
  44. return TextLine_Edit((LPTEXTLINE)lpLine, hWndDoc, hDC);
  45. #if defined( OLE_CNTR )
  46. case CONTAINERLINETYPE:
  47. ContainerLine_Edit((LPCONTAINERLINE)lpLine, hWndDoc, hDC);
  48. break;
  49. #endif
  50. default:
  51. return FALSE; // unknown line type
  52. }
  53. }
  54. /* Line_GetLineType
  55. * ----------------
  56. *
  57. * Return type of the line
  58. */
  59. LINETYPE Line_GetLineType(LPLINE lpLine)
  60. {
  61. if (! lpLine) return 0;
  62. return lpLine->m_lineType;
  63. }
  64. /* Line_GetTextLen
  65. * ---------------
  66. *
  67. * Return length of string representation of the Line
  68. * (not considering the tab level).
  69. */
  70. int Line_GetTextLen(LPLINE lpLine)
  71. {
  72. switch (lpLine->m_lineType) {
  73. case TEXTLINETYPE:
  74. return TextLine_GetTextLen((LPTEXTLINE)lpLine);
  75. #if defined( OLE_CNTR )
  76. case CONTAINERLINETYPE:
  77. return ContainerLine_GetTextLen((LPCONTAINERLINE)lpLine);
  78. #endif
  79. default:
  80. return 0; // unknown line type
  81. }
  82. }
  83. /* Line_GetTextData
  84. * ----------------
  85. *
  86. * Return the string representation of the Line.
  87. * (not considering the tab level).
  88. */
  89. void Line_GetTextData(LPLINE lpLine, LPSTR lpszBuf)
  90. {
  91. switch (lpLine->m_lineType) {
  92. case TEXTLINETYPE:
  93. TextLine_GetTextData((LPTEXTLINE)lpLine, lpszBuf);
  94. break;
  95. #if defined( OLE_CNTR )
  96. case CONTAINERLINETYPE:
  97. ContainerLine_GetTextData((LPCONTAINERLINE)lpLine, lpszBuf);
  98. break;
  99. #endif
  100. default:
  101. *lpszBuf = '\0';
  102. return; // unknown line type
  103. }
  104. }
  105. /* Line_GetOutlineData
  106. * -------------------
  107. *
  108. * Return the CF_OUTLINE format representation of the Line.
  109. */
  110. BOOL Line_GetOutlineData(LPLINE lpLine, LPTEXTLINE lpBuf)
  111. {
  112. switch (lpLine->m_lineType) {
  113. case TEXTLINETYPE:
  114. return TextLine_GetOutlineData((LPTEXTLINE)lpLine, lpBuf);
  115. #if defined( OLE_CNTR )
  116. case CONTAINERLINETYPE:
  117. return ContainerLine_GetOutlineData(
  118. (LPCONTAINERLINE)lpLine,
  119. lpBuf
  120. );
  121. #endif
  122. default:
  123. return FALSE; // unknown line type
  124. }
  125. }
  126. /* Line_CalcTabWidthInHimetric
  127. * ---------------------------
  128. *
  129. * Recalculate the width for the line's current tab level
  130. */
  131. static int Line_CalcTabWidthInHimetric(LPLINE lpLine, HDC hDC)
  132. {
  133. int nTabWidthInHimetric;
  134. nTabWidthInHimetric=lpLine->m_nTabLevel * TABWIDTH;
  135. return nTabWidthInHimetric;
  136. }
  137. /* Line_Indent
  138. * -----------
  139. *
  140. * Increment the tab level for the line
  141. */
  142. void Line_Indent(LPLINE lpLine, HDC hDC)
  143. {
  144. lpLine->m_nTabLevel++;
  145. lpLine->m_nTabWidthInHimetric = Line_CalcTabWidthInHimetric(lpLine, hDC);
  146. #if defined( INPLACE_CNTR )
  147. if (Line_GetLineType(lpLine) == CONTAINERLINETYPE)
  148. ContainerLine_UpdateInPlaceObjectRects((LPCONTAINERLINE)lpLine, NULL);
  149. #endif
  150. }
  151. /* Line_Unindent
  152. * -------------
  153. *
  154. * Decrement the tab level for the line
  155. */
  156. void Line_Unindent(LPLINE lpLine, HDC hDC)
  157. {
  158. if(lpLine->m_nTabLevel > 0) {
  159. lpLine->m_nTabLevel--;
  160. lpLine->m_nTabWidthInHimetric = Line_CalcTabWidthInHimetric(lpLine, hDC);
  161. }
  162. #if defined( INPLACE_CNTR )
  163. if (Line_GetLineType(lpLine) == CONTAINERLINETYPE)
  164. ContainerLine_UpdateInPlaceObjectRects((LPCONTAINERLINE)lpLine, NULL);
  165. #endif
  166. }
  167. /* Line_GetTotalWidthInHimetric
  168. * ----------------------------
  169. *
  170. * Calculate the total width of the line
  171. */
  172. UINT Line_GetTotalWidthInHimetric(LPLINE lpLine)
  173. {
  174. return lpLine->m_nWidthInHimetric + lpLine->m_nTabWidthInHimetric;
  175. }
  176. /* Line_SetWidthInHimetric
  177. * -----------------------
  178. *
  179. * Set the width of the line
  180. */
  181. void Line_SetWidthInHimetric(LPLINE lpLine, int nWidth)
  182. {
  183. if (!lpLine)
  184. return;
  185. lpLine->m_nWidthInHimetric = nWidth;
  186. }
  187. /* Line_GetWidthInHimetric
  188. * -----------------------
  189. *
  190. * Return the width of the line
  191. */
  192. UINT Line_GetWidthInHimetric(LPLINE lpLine)
  193. {
  194. if (!lpLine)
  195. return 0;
  196. return lpLine->m_nWidthInHimetric;
  197. }
  198. /* Line_GetTabLevel
  199. * ----------------
  200. *
  201. * Return the tab level of a line object.
  202. */
  203. UINT Line_GetTabLevel(LPLINE lpLine)
  204. {
  205. return lpLine->m_nTabLevel;
  206. }
  207. /* Line_DrawToScreen
  208. * -----------------
  209. *
  210. * Draw the item in the owner-draw listbox
  211. */
  212. void Line_DrawToScreen(
  213. LPLINE lpLine,
  214. HDC hDC,
  215. LPRECT lprcPix,
  216. UINT itemAction,
  217. UINT itemState,
  218. LPRECT lprcDevice
  219. )
  220. {
  221. if (!lpLine || !hDC || !lprcPix || !lprcDevice)
  222. return;
  223. /* Draw a list box item in its normal drawing action.
  224. * Then check if it is selected or has the focus state, and call
  225. * functions to handle drawing for these states if necessary.
  226. */
  227. if(itemAction & (ODA_SELECT | ODA_DRAWENTIRE)) {
  228. HFONT hfontOld;
  229. int nMapModeOld;
  230. RECT rcWindowOld;
  231. RECT rcViewportOld;
  232. RECT rcLogical;
  233. // NOTE: we have to set the device context to HIMETRIC in order
  234. // draw the line; however, we have to restore the HDC before
  235. // we draw focus or dragfeedback...
  236. rcLogical.left = 0;
  237. rcLogical.bottom = 0;
  238. rcLogical.right = lpLine->m_nWidthInHimetric;
  239. rcLogical.top = lpLine->m_nHeightInHimetric;
  240. {
  241. HBRUSH hbr;
  242. RECT rcDraw;
  243. lpLine->m_fSelected = (BOOL)(itemState & ODS_SELECTED);
  244. if (ODS_SELECTED & itemState) {
  245. /*Get proper txt colors */
  246. hbr = CreateSolidBrush(GetSysColor(COLOR_HIGHLIGHT));
  247. }
  248. else {
  249. hbr = CreateSolidBrush(GetSysColor(COLOR_WINDOW));
  250. }
  251. rcDraw = *lprcPix;
  252. rcDraw.right = lprcDevice->left;
  253. FillRect(hDC, lprcPix, hbr);
  254. rcDraw = *lprcPix;
  255. rcDraw.left = lprcDevice->right;
  256. FillRect(hDC, lprcPix, hbr);
  257. DeleteObject(hbr);
  258. }
  259. nMapModeOld=SetDCToAnisotropic(hDC, lprcDevice, &rcLogical,
  260. (LPRECT)&rcWindowOld, (LPRECT)&rcViewportOld);
  261. // Set the default font size, and font face name
  262. hfontOld = SelectObject(hDC, OutlineApp_GetActiveFont(g_lpApp));
  263. Line_Draw(lpLine, hDC, &rcLogical, NULL, (ODS_SELECTED & itemState));
  264. SelectObject(hDC, hfontOld);
  265. ResetOrigDC(hDC, nMapModeOld, (LPRECT)&rcWindowOld,
  266. (LPRECT)&rcViewportOld);
  267. #if defined( OLE_CNTR )
  268. if ((itemState & ODS_SELECTED) &&
  269. (Line_GetLineType(lpLine)==CONTAINERLINETYPE))
  270. ContainerLine_DrawSelHilight(
  271. (LPCONTAINERLINE)lpLine,
  272. hDC,
  273. lprcPix,
  274. ODA_SELECT,
  275. ODS_SELECTED
  276. );
  277. #endif
  278. }
  279. /* If a list box item just gained or lost the focus,
  280. * call function (which could check if ODS_FOCUS bit is set)
  281. * and draws item in focus or non-focus state.
  282. */
  283. if(itemAction & ODA_FOCUS )
  284. Line_DrawFocusRect(lpLine, hDC, lprcPix, itemAction, itemState);
  285. #if defined( OLE_CNTR )
  286. if (Line_GetLineType(lpLine) == CONTAINERLINETYPE) {
  287. LPCONTAINERLINE lpContainerLine = (LPCONTAINERLINE)lpLine;
  288. LPCONTAINERDOC lpDoc = lpContainerLine->m_lpDoc;
  289. BOOL fIsLink;
  290. RECT rcObj;
  291. if (ContainerDoc_GetShowObjectFlag(lpDoc)) {
  292. ContainerLine_GetOleObjectRectInPixels(lpContainerLine, &rcObj);
  293. fIsLink = ContainerLine_IsOleLink(lpContainerLine);
  294. OleUIShowObject(&rcObj, hDC, fIsLink);
  295. }
  296. }
  297. #endif
  298. #if defined( USE_DRAGDROP )
  299. if (lpLine->m_fDragOverLine)
  300. Line_DrawDragFeedback(lpLine, hDC, lprcPix, itemState );
  301. #endif
  302. }
  303. /* Line_Draw
  304. * ---------
  305. *
  306. * Draw a line on a DC.
  307. *
  308. * Parameters:
  309. * hDC - DC to which the line will be drawn
  310. * lpRect - the object rect in logical coordinates
  311. */
  312. void Line_Draw(
  313. LPLINE lpLine,
  314. HDC hDC,
  315. LPRECT lpRect,
  316. LPRECT lpRectWBounds,
  317. BOOL fHighlight
  318. )
  319. {
  320. switch (lpLine->m_lineType) {
  321. case TEXTLINETYPE:
  322. TextLine_Draw(
  323. (LPTEXTLINE)lpLine, hDC, lpRect,lpRectWBounds,fHighlight);
  324. break;
  325. #if defined( OLE_CNTR )
  326. case CONTAINERLINETYPE:
  327. ContainerLine_Draw(
  328. (LPCONTAINERLINE)lpLine,hDC,lpRect,lpRectWBounds,fHighlight);
  329. break;
  330. #endif
  331. default:
  332. return; // unknown line type
  333. }
  334. return;
  335. }
  336. /* Line_DrawSelHilight
  337. * -------------------
  338. *
  339. * Handles selection of list box item
  340. */
  341. void Line_DrawSelHilight(LPLINE lpLine, HDC hDC, LPRECT lpRect, UINT itemAction, UINT itemState)
  342. {
  343. switch (lpLine->m_lineType) {
  344. case TEXTLINETYPE:
  345. TextLine_DrawSelHilight((LPTEXTLINE)lpLine, hDC, lpRect,
  346. itemAction, itemState);
  347. break;
  348. #if defined( OLE_CNTR )
  349. case CONTAINERLINETYPE:
  350. ContainerLine_DrawSelHilight((LPCONTAINERLINE)lpLine, hDC, lpRect,
  351. itemAction, itemState);
  352. break;
  353. #endif
  354. default:
  355. return; // unknown line type
  356. }
  357. return;
  358. }
  359. /* Line_DrawFocusRect
  360. * ------------------
  361. *
  362. * Handles focus state of list box item
  363. */
  364. void Line_DrawFocusRect(LPLINE lpLine, HDC hDC, LPRECT lpRect, UINT itemAction, UINT itemState)
  365. {
  366. if(lpLine)
  367. DrawFocusRect(hDC, lpRect);
  368. }
  369. #if defined( USE_DRAGDROP )
  370. /* Line_DrawDragFeedback
  371. * ---------------------
  372. *
  373. * Handles focus state of list box item
  374. */
  375. void Line_DrawDragFeedback(LPLINE lpLine, HDC hDC, LPRECT lpRect, UINT itemState )
  376. {
  377. if(lpLine)
  378. DrawFocusRect(hDC, lpRect);
  379. }
  380. #endif // USE_DRAGDROP
  381. /* Line_GetHeightInHimetric
  382. * ------------------------
  383. *
  384. * Return the height of the item in HIMETRIC units
  385. */
  386. UINT Line_GetHeightInHimetric(LPLINE lpLine)
  387. {
  388. if (!lpLine)
  389. return 0;
  390. return (UINT)lpLine->m_nHeightInHimetric;
  391. }
  392. /* Line_SetHeightInHimetric
  393. * ------------------------
  394. *
  395. * Set the height of the item in HIMETRIC units.
  396. */
  397. void Line_SetHeightInHimetric(LPLINE lpLine, int nHeight)
  398. {
  399. if (!lpLine)
  400. return;
  401. switch (lpLine->m_lineType) {
  402. case TEXTLINETYPE:
  403. TextLine_SetHeightInHimetric((LPTEXTLINE)lpLine, nHeight);
  404. break;
  405. #if defined( OLE_CNTR )
  406. case CONTAINERLINETYPE:
  407. ContainerLine_SetHeightInHimetric((LPCONTAINERLINE)lpLine,
  408. nHeight);
  409. break;
  410. #endif
  411. }
  412. }
  413. /* Line_Delete
  414. * -----------
  415. *
  416. * Delete the Line structure
  417. */
  418. void Line_Delete(LPLINE lpLine)
  419. {
  420. switch (lpLine->m_lineType) {
  421. case TEXTLINETYPE:
  422. TextLine_Delete((LPTEXTLINE)lpLine);
  423. break;
  424. #if defined( OLE_CNTR )
  425. case CONTAINERLINETYPE:
  426. ContainerLine_Delete((LPCONTAINERLINE)lpLine);
  427. break;
  428. #endif
  429. default:
  430. break; // unknown line type
  431. }
  432. }
  433. /* Line_CopyToDoc
  434. * --------------
  435. *
  436. * Copy a line to another Document (usually ClipboardDoc)
  437. */
  438. BOOL Line_CopyToDoc(LPLINE lpSrcLine, LPOUTLINEDOC lpDestDoc, int nIndex)
  439. {
  440. switch (lpSrcLine->m_lineType) {
  441. case TEXTLINETYPE:
  442. return TextLine_CopyToDoc((LPTEXTLINE)lpSrcLine,lpDestDoc,nIndex);
  443. break;
  444. #if defined( OLE_CNTR )
  445. case CONTAINERLINETYPE:
  446. return ContainerLine_CopyToDoc(
  447. (LPCONTAINERLINE)lpSrcLine,
  448. lpDestDoc,
  449. nIndex
  450. );
  451. break;
  452. #endif
  453. default:
  454. return FALSE; // unknown line type
  455. }
  456. }
  457. /* Line_SaveToStg
  458. * --------------
  459. *
  460. * Save a single line object to a storage
  461. *
  462. * Return TRUE if successful, FALSE otherwise
  463. */
  464. BOOL Line_SaveToStg(LPLINE lpLine, UINT uFormat, LPSTORAGE lpSrcStg, LPSTORAGE lpDestStg, LPSTREAM lpLLStm, BOOL fRemember)
  465. {
  466. LINERECORD_ONDISK lineRecord;
  467. ULONG nWritten;
  468. HRESULT hrErr;
  469. BOOL fStatus;
  470. LARGE_INTEGER dlibSavePos;
  471. LARGE_INTEGER dlibZeroOffset;
  472. LISet32( dlibZeroOffset, 0 );
  473. /* save seek position before line record is written in case of error */
  474. hrErr = lpLLStm->lpVtbl->Seek(
  475. lpLLStm,
  476. dlibZeroOffset,
  477. STREAM_SEEK_CUR,
  478. (ULARGE_INTEGER FAR*)&dlibSavePos
  479. );
  480. if (hrErr != NOERROR) return FALSE;
  481. #if defined( OLE_CNTR )
  482. if (lpLine->m_lineType == CONTAINERLINETYPE) {
  483. /* OLE2NOTE: asking an OLE object to save may cause the
  484. ** object to send an OnViewChange notification if there are any
  485. ** outstanding changes to the object. this is particularly true
  486. ** for objects with coarse update granularity like OLE 1.0
  487. ** objects. if an OnViewChange notification is received then the
  488. ** object's presentation cache will be updated BEFORE it is
  489. ** saved. It is important that the extents stored as part of
  490. ** the ContainerLine/Line record associated with the OLE object
  491. ** are updated before the Line data is saved to the storage. it
  492. ** is important that this extent information matches the data
  493. ** saved with the OLE object. the Line extent information is
  494. ** updated in the IAdviseSink::OnViewChange method implementation.
  495. */
  496. // only save the OLE object if format is compatible.
  497. if (uFormat != ((LPCONTAINERAPP)g_lpApp)->m_cfCntrOutl)
  498. goto error;
  499. fStatus = ContainerLine_SaveOleObjectToStg(
  500. (LPCONTAINERLINE)lpLine,
  501. lpSrcStg,
  502. lpDestStg,
  503. fRemember
  504. );
  505. if (! fStatus) goto error;
  506. }
  507. #endif
  508. // Compilers should handle aligment correctly
  509. lineRecord.m_lineType = (USHORT) lpLine->m_lineType;
  510. lineRecord.m_nTabLevel = (USHORT) lpLine->m_nTabLevel;
  511. lineRecord.m_nTabWidthInHimetric = (USHORT) lpLine->m_nTabWidthInHimetric;
  512. lineRecord.m_nWidthInHimetric = (USHORT) lpLine->m_nWidthInHimetric;
  513. lineRecord.m_nHeightInHimetric = (USHORT) lpLine->m_nHeightInHimetric;
  514. lineRecord.m_reserved = 0;
  515. /* write line record header */
  516. hrErr = lpLLStm->lpVtbl->Write(
  517. lpLLStm,
  518. (LPVOID)&lineRecord,
  519. sizeof(lineRecord),
  520. &nWritten
  521. );
  522. if (hrErr != NOERROR) {
  523. OleDbgOutHResult("Write Line header returned", hrErr);
  524. goto error;
  525. }
  526. switch (lpLine->m_lineType) {
  527. case TEXTLINETYPE:
  528. fStatus = TextLine_SaveToStm((LPTEXTLINE)lpLine, lpLLStm);
  529. if (! fStatus) goto error;
  530. break;
  531. #if defined( OLE_CNTR )
  532. case CONTAINERLINETYPE:
  533. fStatus=ContainerLine_SaveToStm((LPCONTAINERLINE)lpLine,lpLLStm);
  534. if (! fStatus) goto error;
  535. break;
  536. #endif
  537. default:
  538. goto error; // unknown line type
  539. }
  540. return TRUE;
  541. error:
  542. /* retore seek position prior to writing Line record */
  543. lpLLStm->lpVtbl->Seek(
  544. lpLLStm,
  545. dlibSavePos,
  546. STREAM_SEEK_SET,
  547. NULL
  548. );
  549. return FALSE;
  550. }
  551. /* Line_LoadFromStg
  552. * ----------------
  553. *
  554. * Load a single line object from storage
  555. */
  556. LPLINE Line_LoadFromStg(LPSTORAGE lpSrcStg, LPSTREAM lpLLStm, LPOUTLINEDOC lpDestDoc)
  557. {
  558. LINERECORD_ONDISK lineRecord;
  559. LPLINE lpLine = NULL;
  560. ULONG nRead;
  561. HRESULT hrErr;
  562. /* read line record header */
  563. hrErr = lpLLStm->lpVtbl->Read(
  564. lpLLStm,
  565. (LPVOID)&lineRecord,
  566. sizeof(lineRecord),
  567. &nRead
  568. );
  569. if (hrErr != NOERROR) {
  570. OleDbgOutHResult("Read Line header returned", hrErr);
  571. return NULL;
  572. }
  573. switch ((LINETYPE) lineRecord.m_lineType) {
  574. case TEXTLINETYPE:
  575. lpLine = TextLine_LoadFromStg(lpSrcStg, lpLLStm, lpDestDoc);
  576. break;
  577. #if defined( OLE_CNTR )
  578. case CONTAINERLINETYPE:
  579. lpLine = ContainerLine_LoadFromStg(lpSrcStg, lpLLStm, lpDestDoc);
  580. break;
  581. #endif
  582. default:
  583. return NULL; // unknown line type
  584. }
  585. lpLine->m_lineType = (LINETYPE) lineRecord.m_lineType;
  586. lpLine->m_nTabLevel = (UINT) lineRecord.m_nTabLevel;
  587. lpLine->m_nTabWidthInHimetric = (UINT) lineRecord.m_nTabWidthInHimetric;
  588. lpLine->m_nWidthInHimetric = (UINT) lineRecord.m_nWidthInHimetric;
  589. lpLine->m_nHeightInHimetric = (UINT) lineRecord.m_nHeightInHimetric;
  590. return lpLine;
  591. }
  592. /* Line_IsSelected
  593. * ---------------
  594. *
  595. * Return the selection state of the line
  596. */
  597. BOOL Line_IsSelected(LPLINE lpLine)
  598. {
  599. if (!lpLine)
  600. return FALSE;
  601. return lpLine->m_fSelected;
  602. }