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.

1183 lines
28 KiB

  1. /*************************************************************************
  2. **
  3. ** OLE 2 Sample Code
  4. **
  5. ** outldata.c
  6. **
  7. ** This file contains LineList and NameTable functions
  8. ** and related support functions.
  9. **
  10. ** (c) Copyright Microsoft Corp. 1992 - 1993 All Rights Reserved
  11. **
  12. *************************************************************************/
  13. #include "outline.h"
  14. OLEDBGDATA
  15. extern LPOUTLINEAPP g_lpApp;
  16. char ErrMsgListBox[] = "Can't create ListBox!";
  17. static int g_iMapMode;
  18. /* LineList_Init
  19. * -------------
  20. *
  21. * Create and Initialize the LineList (owner-drawn listbox)
  22. */
  23. BOOL LineList_Init(LPLINELIST lpLL, LPOUTLINEDOC lpOutlineDoc)
  24. {
  25. LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp;
  26. #if defined( INPLACE_CNTR )
  27. lpLL->m_hWndListBox = CreateWindow(
  28. "listbox", /* Window class name */
  29. NULL, /* Window's title */
  30. /* OLE2NOTE: an in-place contanier MUST use
  31. ** WS_CLIPCHILDREN window style for the window
  32. ** that it uses as the parent for the server's
  33. ** in-place active window so that its
  34. ** painting does NOT interfere with the painting
  35. ** of the server's in-place active child window.
  36. */
  37. WS_CLIPCHILDREN |
  38. WS_CHILDWINDOW |
  39. WS_VISIBLE |
  40. WS_VSCROLL |
  41. WS_HSCROLL |
  42. LBS_EXTENDEDSEL |
  43. LBS_NOTIFY |
  44. LBS_OWNERDRAWVARIABLE |
  45. LBS_NOINTEGRALHEIGHT |
  46. LBS_USETABSTOPS,
  47. 0, 0, /* Use default X, Y */
  48. 0, 0, /* Use default X, Y */
  49. lpOutlineDoc->m_hWndDoc,/* Parent window's handle */
  50. (HMENU)IDC_LINELIST, /* Child Window ID */
  51. lpOutlineApp->m_hInst, /* Instance of window */
  52. NULL); /* Create struct for WM_CREATE */
  53. #else
  54. lpLL->m_hWndListBox = CreateWindow(
  55. "listbox", /* Window class name */
  56. NULL, /* Window's title */
  57. WS_CHILDWINDOW |
  58. WS_VISIBLE |
  59. WS_VSCROLL |
  60. WS_HSCROLL |
  61. LBS_EXTENDEDSEL |
  62. LBS_NOTIFY |
  63. LBS_OWNERDRAWVARIABLE |
  64. LBS_NOINTEGRALHEIGHT |
  65. LBS_USETABSTOPS,
  66. 0, 0, /* Use default X, Y */
  67. 0, 0, /* Use default X, Y */
  68. lpOutlineDoc->m_hWndDoc,/* Parent window's handle */
  69. (HMENU)IDC_LINELIST, /* Child Window ID */
  70. lpOutlineApp->m_hInst, /* Instance of window */
  71. NULL); /* Create struct for WM_CREATE */
  72. #endif
  73. if(! lpLL->m_hWndListBox) {
  74. OutlineApp_ErrorMessage(g_lpApp, ErrMsgListBox);
  75. return FALSE;
  76. }
  77. lpOutlineApp->m_ListBoxWndProc =
  78. (FARPROC) GetWindowLongPtr ( lpLL->m_hWndListBox, GWLP_WNDPROC );
  79. SetWindowLongPtr (lpLL->m_hWndListBox, GWLP_WNDPROC, (LONG_PTR) LineListWndProc);
  80. #if defined ( USE_DRAGDROP )
  81. /* m_iDragOverLine saves index of line that has drag/drop target
  82. ** feedback. we currently use our focus rectangle feedback for
  83. ** this. it would be better to have a different visual feedback
  84. ** for potential target of the pending drop.
  85. */
  86. lpLL->m_iDragOverLine = -1;
  87. #endif
  88. lpLL->m_nNumLines = 0;
  89. lpLL->m_nMaxLineWidthInHimetric = 0;
  90. lpLL->m_lpDoc = lpOutlineDoc;
  91. _fmemset(&lpLL->m_lrSaveSel, 0, sizeof(LINERANGE));
  92. return TRUE;
  93. }
  94. /* LineList_Destroy
  95. * ----------------
  96. *
  97. * Clear (delete) all Line objects from the list and free supporting
  98. * memory (ListBox Window) used by the LineList object itself.
  99. */
  100. void LineList_Destroy(LPLINELIST lpLL)
  101. {
  102. int i;
  103. int linesTotal = lpLL->m_nNumLines;
  104. // Delete all Line objects
  105. for (i = 0; i < linesTotal; i++)
  106. LineList_DeleteLine(lpLL, 0); // NOTE: always delete line 0
  107. // Remove all Lines from the ListBox
  108. SendMessage(lpLL->m_hWndListBox,LB_RESETCONTENT,0,0L);
  109. lpLL->m_nNumLines=0;
  110. DestroyWindow(lpLL->m_hWndListBox);
  111. lpLL->m_hWndListBox = NULL;
  112. }
  113. /* LineList_AddLine
  114. * ----------------
  115. *
  116. * Add one line to the list box. The line is added following the
  117. * line with index "nIndex". If nIndex is larger than the number of lines
  118. * in the ListBox, then the line is appended to the end. The selection
  119. * is set to the newly added line.
  120. */
  121. void LineList_AddLine(LPLINELIST lpLL, LPLINE lpLine, int nIndex)
  122. {
  123. int nAddIndex = (lpLL->m_nNumLines == 0 ?
  124. 0 :
  125. (nIndex >= lpLL->m_nNumLines ? lpLL->m_nNumLines : nIndex+1));
  126. LINERANGE lrSel;
  127. #if defined( USE_HEADING )
  128. int nHeight = Line_GetHeightInHimetric(lpLine);
  129. nHeight = XformHeightInHimetricToPixels(NULL, nHeight);
  130. // Add a dummy string to the row heading
  131. Heading_RH_SendMessage(OutlineDoc_GetHeading(lpLL->m_lpDoc),
  132. LB_INSERTSTRING, (WPARAM)nAddIndex, MAKELPARAM(nHeight, 0));
  133. #endif
  134. lrSel.m_nStartLine = nAddIndex;
  135. lrSel.m_nEndLine = nAddIndex;
  136. if (!lpLine) {
  137. OutlineApp_ErrorMessage(g_lpApp, "Could not create line.");
  138. return;
  139. }
  140. SendMessage(lpLL->m_hWndListBox, LB_INSERTSTRING, (WPARAM)nAddIndex,
  141. (DWORD)lpLine);
  142. LineList_SetMaxLineWidthInHimetric(
  143. lpLL,
  144. Line_GetTotalWidthInHimetric(lpLine)
  145. );
  146. lpLL->m_nNumLines++;
  147. LineList_SetSel(lpLL, &lrSel);
  148. }
  149. /* LineList_DeleteLine
  150. * -------------------
  151. *
  152. * Delete one line from listbox and memory
  153. */
  154. void LineList_DeleteLine(LPLINELIST lpLL, int nIndex)
  155. {
  156. LPLINE lpLine = LineList_GetLine(lpLL, nIndex);
  157. BOOL fResetSel;
  158. fResetSel = (BOOL)SendMessage(lpLL->m_hWndListBox, LB_GETSEL, (WPARAM)nIndex, 0L);
  159. if (lpLine)
  160. Line_Delete(lpLine); // free memory of Line
  161. // Remove the Line from the ListBox
  162. SendMessage(lpLL->m_hWndListBox, LB_DELETESTRING, (WPARAM)nIndex, 0L);
  163. lpLL->m_nNumLines--;
  164. if (fResetSel) {
  165. if (nIndex > 0) {
  166. #if defined( WIN32 )
  167. SendMessage(
  168. lpLL->m_hWndListBox,
  169. LB_SETSEL,
  170. (WPARAM)TRUE,
  171. (LPARAM)nIndex-1
  172. );
  173. #else
  174. SendMessage(
  175. lpLL->m_hWndListBox,
  176. LB_SETSEL,
  177. (WPARAM)TRUE,
  178. MAKELPARAM(nIndex-1,0)
  179. );
  180. #endif
  181. } else {
  182. if (lpLL->m_nNumLines > 0) {
  183. #if defined( WIN32 )
  184. SendMessage(
  185. lpLL->m_hWndListBox,
  186. LB_SETSEL,
  187. (WPARAM)TRUE,
  188. (LPARAM)0
  189. );
  190. #else
  191. SendMessage(
  192. lpLL->m_hWndListBox,
  193. LB_SETSEL,
  194. (WPARAM)TRUE,
  195. MAKELPARAM(0,0)
  196. );
  197. #endif
  198. }
  199. }
  200. }
  201. #if defined( USE_HEADING )
  202. // Remove the dummy string from the row heading
  203. Heading_RH_SendMessage(OutlineDoc_GetHeading(lpLL->m_lpDoc),
  204. LB_DELETESTRING, (WPARAM)nIndex, 0L);
  205. #endif
  206. }
  207. /* LineList_ReplaceLine
  208. * --------------------
  209. *
  210. * Replace the line at a given index in the list box with a new
  211. * line.
  212. */
  213. void LineList_ReplaceLine(LPLINELIST lpLL, LPLINE lpLine, int nIndex)
  214. {
  215. LPLINE lpOldLine = LineList_GetLine(lpLL, nIndex);
  216. if (lpOldLine)
  217. Line_Delete(lpOldLine); // free memory of Line
  218. else
  219. return; // if no previous line then invalid index
  220. SendMessage(
  221. lpLL->m_hWndListBox,
  222. LB_SETITEMDATA,
  223. (WPARAM)nIndex,
  224. (LPARAM)lpLine
  225. );
  226. }
  227. /* LineList_GetLineIndex
  228. * ---------------------
  229. *
  230. * Return the index of the Line given a pointer to the line.
  231. * Return -1 if the line is not found.
  232. */
  233. int LineList_GetLineIndex(LPLINELIST lpLL, LPLINE lpLine)
  234. {
  235. LRESULT lRet;
  236. if (! lpLine) return -1;
  237. lRet = SendMessage(
  238. lpLL->m_hWndListBox,
  239. LB_FINDSTRING,
  240. (WPARAM)-1,
  241. (LPARAM)(LPCSTR)lpLine
  242. );
  243. return ((lRet == LB_ERR) ? -1 : (int)lRet);
  244. }
  245. /* LineList_GetLine
  246. * ----------------
  247. *
  248. * Retrieve the pointer to the Line given its index in the LineList
  249. */
  250. LPLINE LineList_GetLine(LPLINELIST lpLL, int nIndex)
  251. {
  252. DWORD dWord;
  253. LRESULT lRet;
  254. if (lpLL->m_nNumLines == 0 || nIndex > lpLL->m_nNumLines || nIndex < 0)
  255. return NULL;
  256. lRet = SendMessage(
  257. lpLL->m_hWndListBox,LB_GETTEXT,nIndex,(LPARAM)(LPCSTR)&dWord);
  258. return ((lRet == LB_ERR || lRet == 0) ? NULL : (LPLINE)dWord);
  259. }
  260. /* LineList_SetFocusLine
  261. * ---------------------
  262. *
  263. */
  264. void LineList_SetFocusLine ( LPLINELIST lpLL, WORD wIndex )
  265. {
  266. SendMessage(lpLL->m_hWndListBox, LB_SETCARETINDEX, (WPARAM)wIndex, 0L );
  267. }
  268. /* LineList_GetLineRect
  269. * --------------------
  270. *
  271. * Retrieve the rectangle of a Line given its index in the LineList
  272. */
  273. BOOL LineList_GetLineRect(LPLINELIST lpLL, int nIndex, LPRECT lpRect)
  274. {
  275. DWORD iReturn = (DWORD)LB_ERR;
  276. if ( !(lpLL->m_nNumLines == 0 || nIndex > lpLL->m_nNumLines || nIndex < 0) )
  277. iReturn = SendMessage(lpLL->m_hWndListBox,LB_GETITEMRECT,nIndex,(LPARAM)lpRect);
  278. return (iReturn == LB_ERR ? FALSE : TRUE );
  279. }
  280. /* LineList_GetFocusLineIndex
  281. * --------------------------
  282. *
  283. * Get the index of the line that currently has focus (the active line).
  284. */
  285. int LineList_GetFocusLineIndex(LPLINELIST lpLL)
  286. {
  287. return (int)SendMessage(lpLL->m_hWndListBox,LB_GETCARETINDEX,0,0L);
  288. }
  289. /* LineList_GetCount
  290. * -----------------
  291. *
  292. * Return number of line objects
  293. */
  294. int LineList_GetCount(LPLINELIST lpLL)
  295. {
  296. if (lpLL)
  297. return lpLL->m_nNumLines;
  298. else {
  299. OleDbgAssert(lpLL!=NULL);
  300. return 0;
  301. }
  302. }
  303. /* LineList_SetMaxLineWidthInHimetric
  304. * ----------------------------------
  305. *
  306. * Adjust the maximum line width for the listbox. The max line width is
  307. * used to determine if a horizontal scroll bar is needed.
  308. *
  309. * Parameters:
  310. * nWidthInHimetric - if +ve, width of an additional line
  311. * - if -ve, reset Max to be the value
  312. *
  313. * Returns:
  314. * TRUE is max line width of LineList changed
  315. * FALSE if no change
  316. */
  317. BOOL LineList_SetMaxLineWidthInHimetric(LPLINELIST lpLL, int nWidthInHimetric)
  318. {
  319. int nWidthInPix;
  320. BOOL fSizeChanged = FALSE;
  321. LPSCALEFACTOR lpscale;
  322. if (!lpLL)
  323. return FALSE;
  324. lpscale = OutlineDoc_GetScaleFactor(lpLL->m_lpDoc);
  325. if (nWidthInHimetric < 0) {
  326. lpLL->m_nMaxLineWidthInHimetric = -1;
  327. nWidthInHimetric *= -1;
  328. }
  329. if (nWidthInHimetric > lpLL->m_nMaxLineWidthInHimetric) {
  330. lpLL->m_nMaxLineWidthInHimetric = nWidthInHimetric;
  331. nWidthInPix = XformWidthInHimetricToPixels(NULL, nWidthInHimetric +
  332. LOWORD(OutlineDoc_GetMargin(lpLL->m_lpDoc)) +
  333. HIWORD(OutlineDoc_GetMargin(lpLL->m_lpDoc)));
  334. nWidthInPix = (int)(nWidthInPix * lpscale->dwSxN / lpscale->dwSxD);
  335. SendMessage(
  336. lpLL->m_hWndListBox,
  337. LB_SETHORIZONTALEXTENT,
  338. nWidthInPix,
  339. 0L
  340. );
  341. fSizeChanged = TRUE;
  342. #if defined( USE_HEADING )
  343. Heading_CH_SetHorizontalExtent(
  344. OutlineDoc_GetHeading(lpLL->m_lpDoc), lpLL->m_hWndListBox);
  345. #endif
  346. }
  347. return fSizeChanged;
  348. }
  349. /* LineList_GetMaxLineWidthInHimetric
  350. * ----------------------------------
  351. *
  352. * Return the width of the widest line
  353. */
  354. int LineList_GetMaxLineWidthInHimetric(LPLINELIST lpLL)
  355. {
  356. return lpLL->m_nMaxLineWidthInHimetric;
  357. }
  358. /* LineList_RecalcMaxLineWidthInHimetric
  359. * -------------------------------------
  360. *
  361. * Recalculate the maximum line width in the entire list.
  362. *
  363. * Parameters:
  364. * nWidthInHimetric should be set to the width of line being removed.
  365. * nWidthInHimetric == 0 forces list to recalculate in all cases.
  366. * nWidthInHimetric == current max width => forces recalc.
  367. *
  368. * Returns:
  369. * TRUE is max line width of LineList changed
  370. * FALSE if no change
  371. */
  372. BOOL LineList_RecalcMaxLineWidthInHimetric(
  373. LPLINELIST lpLL,
  374. int nWidthInHimetric
  375. )
  376. {
  377. int i;
  378. LPLINE lpLine;
  379. BOOL fSizeChanged = FALSE;
  380. int nOrgMaxLineWidthInHimetric = lpLL->m_nMaxLineWidthInHimetric;
  381. if (nWidthInHimetric == 0 ||
  382. nWidthInHimetric == lpLL->m_nMaxLineWidthInHimetric) {
  383. lpLL->m_nMaxLineWidthInHimetric = -1;
  384. LineList_SetMaxLineWidthInHimetric(lpLL, 0);
  385. for(i = 0; i < lpLL->m_nNumLines; i++) {
  386. lpLine=LineList_GetLine(lpLL, i);
  387. LineList_SetMaxLineWidthInHimetric(
  388. lpLL,
  389. Line_GetTotalWidthInHimetric(lpLine)
  390. );
  391. }
  392. }
  393. if (nOrgMaxLineWidthInHimetric != lpLL->m_nMaxLineWidthInHimetric)
  394. fSizeChanged = TRUE;
  395. return fSizeChanged;
  396. }
  397. /* LineList_CalcSelExtentInHimetric
  398. * --------------------------------
  399. *
  400. * Calculate the extents (widht and height) of a selection of lines.
  401. *
  402. * if lplrSel == NULL, calculate extent of all lines.
  403. */
  404. void LineList_CalcSelExtentInHimetric(
  405. LPLINELIST lpLL,
  406. LPLINERANGE lplrSel,
  407. LPSIZEL lpsizel
  408. )
  409. {
  410. int i;
  411. int nEndLine;
  412. int nStartLine;
  413. LPLINE lpLine;
  414. long lWidth;
  415. if (lplrSel) {
  416. nEndLine = lplrSel->m_nEndLine;
  417. nStartLine = lplrSel->m_nStartLine;
  418. } else {
  419. nEndLine = LineList_GetCount(lpLL) - 1;
  420. nStartLine = 0;
  421. }
  422. lpsizel->cx = 0;
  423. lpsizel->cy = 0;
  424. for(i = nStartLine; i <= nEndLine; i++) {
  425. lpLine=LineList_GetLine(lpLL,i);
  426. if (lpLine) {
  427. lWidth = (long)Line_GetTotalWidthInHimetric(lpLine);
  428. lpsizel->cx = max(lpsizel->cx, lWidth);
  429. lpsizel->cy += lpLine->m_nHeightInHimetric;
  430. }
  431. }
  432. }
  433. /* LineList_GetWindow
  434. * ------------------
  435. *
  436. * Return handle of list box
  437. */
  438. HWND LineList_GetWindow(LPLINELIST lpLL)
  439. {
  440. return lpLL->m_hWndListBox;
  441. }
  442. /* LineList_GetDC
  443. * --------------
  444. *
  445. * Return DC handle of list box
  446. */
  447. HDC LineList_GetDC(LPLINELIST lpLL)
  448. {
  449. HFONT hfontOld;
  450. HDC hDC = GetDC(lpLL->m_hWndListBox);
  451. int iXppli; //* pixels per logical inch along width
  452. int iYppli; //* pixels per logical inch along height
  453. SIZE size;
  454. // Setup a mapping mode for the DC which maps physical pixel
  455. // coordinates to HIMETRIC units. The standard MM_HIMETRIC mapping
  456. // mode does not work correctly because it does not take into
  457. // account that a logical inch on the display screen is drawn
  458. // physically larger than 1 inch. We will setup an anisotropic
  459. // mapping mode which will perform the transformation properly.
  460. g_iMapMode = SetMapMode(hDC, MM_ANISOTROPIC);
  461. iXppli = GetDeviceCaps (hDC, LOGPIXELSX);
  462. iYppli = GetDeviceCaps (hDC, LOGPIXELSY);
  463. SetViewportExtEx(hDC, iXppli, iYppli, &size);
  464. SetWindowExtEx(hDC, HIMETRIC_PER_INCH, HIMETRIC_PER_INCH, &size);
  465. // Set the default font size, and font face name
  466. hfontOld = SelectObject(hDC, OutlineApp_GetActiveFont(g_lpApp));
  467. return hDC;
  468. }
  469. /* LineList_ReleaseDC
  470. * ------------------
  471. *
  472. * Release DC of list box returned from previous LineList_GetDC call.
  473. */
  474. void LineList_ReleaseDC(LPLINELIST lpLL, HDC hDC)
  475. {
  476. SetMapMode(hDC, g_iMapMode);
  477. ReleaseDC(lpLL->m_hWndListBox, hDC);
  478. }
  479. /* LineList_SetLineHeight
  480. * ----------------------
  481. *
  482. * Set the height of a line in the LineList list box
  483. */
  484. void LineList_SetLineHeight(LPLINELIST lpLL,int nIndex,int nHeightInHimetric)
  485. {
  486. LPARAM lParam;
  487. LPOUTLINEDOC lpDoc;
  488. LPSCALEFACTOR lpscale;
  489. UINT uHeightInPix;
  490. LPHEADING lphead;
  491. if (!lpLL)
  492. return;
  493. lpDoc = lpLL->m_lpDoc;
  494. lphead = OutlineDoc_GetHeading(lpDoc);
  495. lpscale = OutlineDoc_GetScaleFactor(lpDoc);
  496. uHeightInPix = XformHeightInHimetricToPixels(NULL, nHeightInHimetric);
  497. Heading_RH_SendMessage(lphead, LB_SETITEMDATA, (WPARAM)nIndex,
  498. MAKELPARAM(uHeightInPix, 0));
  499. uHeightInPix = (UINT)(uHeightInPix * lpscale->dwSyN / lpscale->dwSyD);
  500. if (uHeightInPix > LISTBOX_HEIGHT_LIMIT)
  501. uHeightInPix = LISTBOX_HEIGHT_LIMIT;
  502. lParam = MAKELPARAM(uHeightInPix, 0);
  503. SendMessage(lpLL->m_hWndListBox,LB_SETITEMHEIGHT,(WPARAM)nIndex, lParam);
  504. Heading_RH_SendMessage(lphead, LB_SETITEMHEIGHT, (WPARAM)nIndex, lParam);
  505. Heading_RH_ForceRedraw(lphead, TRUE);
  506. }
  507. /* LineList_ReScale
  508. * ----------------
  509. *
  510. * Re-scale the LineList list box
  511. */
  512. void LineList_ReScale(LPLINELIST lpLL, LPSCALEFACTOR lpscale)
  513. {
  514. int nIndex;
  515. LPLINE lpLine;
  516. UINT uWidthInHim;
  517. if (!lpLL)
  518. return;
  519. for (nIndex = 0; nIndex < lpLL->m_nNumLines; nIndex++) {
  520. lpLine = LineList_GetLine(lpLL, nIndex);
  521. if (lpLine) {
  522. LineList_SetLineHeight(
  523. lpLL,
  524. nIndex,
  525. Line_GetHeightInHimetric(lpLine)
  526. );
  527. }
  528. }
  529. uWidthInHim = LineList_GetMaxLineWidthInHimetric(lpLL);
  530. LineList_SetMaxLineWidthInHimetric(lpLL, -(int)uWidthInHim);
  531. }
  532. /* LineList_SetSel
  533. * ---------------
  534. *
  535. * Set the selection in list box
  536. */
  537. void LineList_SetSel(LPLINELIST lpLL, LPLINERANGE lplrSel)
  538. {
  539. DWORD dwSel;
  540. if (lpLL->m_nNumLines <= 0 || lplrSel->m_nStartLine < 0)
  541. return; // no lines in list; can't set a selection
  542. dwSel = MAKELPARAM(lplrSel->m_nStartLine, lplrSel->m_nEndLine);
  543. lpLL->m_lrSaveSel = *lplrSel;
  544. /* remove previous selection */
  545. #if defined( WIN32 )
  546. SendMessage(
  547. lpLL->m_hWndListBox,
  548. LB_SETSEL,
  549. (WPARAM)FALSE,
  550. (LPARAM)-1
  551. );
  552. #else
  553. SendMessage(
  554. lpLL->m_hWndListBox,
  555. LB_SETSEL,
  556. (WPARAM)FALSE,
  557. MAKELPARAM(-1,0)
  558. );
  559. #endif
  560. /* mark selection */
  561. SendMessage(lpLL->m_hWndListBox,LB_SELITEMRANGE, (WPARAM)TRUE, (LPARAM)dwSel);
  562. /* set focus line (caret) */
  563. LineList_SetFocusLine ( lpLL, (WORD)lplrSel->m_nStartLine );
  564. }
  565. /* LineList_GetSel
  566. * ---------------
  567. *
  568. * Get the selection in list box.
  569. *
  570. * Returns the count of items selected
  571. */
  572. int LineList_GetSel(LPLINELIST lpLL, LPLINERANGE lplrSel)
  573. {
  574. int nNumSel=(int)SendMessage(lpLL->m_hWndListBox,LB_GETSELCOUNT,0,0L);
  575. if (nNumSel) {
  576. SendMessage(lpLL->m_hWndListBox,LB_GETSELITEMS,
  577. (WPARAM)1,(LPARAM)(int FAR*)&(lplrSel->m_nStartLine));
  578. lplrSel->m_nEndLine = lplrSel->m_nStartLine + nNumSel - 1;
  579. } else {
  580. _fmemset(lplrSel, 0, sizeof(LINERANGE));
  581. }
  582. return nNumSel;
  583. }
  584. /* LineList_RemoveSel
  585. * ------------------
  586. *
  587. * Remove the selection in list box but save the selection state so that
  588. * it can be restored by calling LineList_RestoreSel
  589. * LineList_RemoveSel is called when the LineList window looses focus.
  590. */
  591. void LineList_RemoveSel(LPLINELIST lpLL)
  592. {
  593. LINERANGE lrSel;
  594. if (LineList_GetSel(lpLL, &lrSel) > 0) {
  595. lpLL->m_lrSaveSel = lrSel;
  596. #if defined( WIN32 )
  597. SendMessage(
  598. lpLL->m_hWndListBox,
  599. LB_SETSEL,
  600. (WPARAM)FALSE,
  601. (LPARAM)-1
  602. );
  603. #else
  604. SendMessage(
  605. lpLL->m_hWndListBox,
  606. LB_SETSEL,
  607. (WPARAM)FALSE,
  608. MAKELPARAM(-1,0)
  609. );
  610. #endif
  611. }
  612. }
  613. /* LineList_RestoreSel
  614. * ------------------
  615. *
  616. * Restore the selection in list box that was previously saved by a call to
  617. * LineList_RemoveSel.
  618. * LineList_RestoreSel is called when the LineList window gains focus.
  619. */
  620. void LineList_RestoreSel(LPLINELIST lpLL)
  621. {
  622. LineList_SetSel(lpLL, &lpLL->m_lrSaveSel);
  623. }
  624. /* LineList_SetRedraw
  625. * ------------------
  626. *
  627. * Enable/Disable the redraw of the linelist (listbox) on screen
  628. *
  629. * fEnbaleDraw = TRUE - enable redraw
  630. * FALSE - disable redraw
  631. */
  632. void LineList_SetRedraw(LPLINELIST lpLL, BOOL fEnableDraw)
  633. {
  634. SendMessage(lpLL->m_hWndListBox,WM_SETREDRAW,(WPARAM)fEnableDraw,0L);
  635. }
  636. /* LineList_ForceRedraw
  637. * --------------------
  638. *
  639. * Force redraw of the linelist (listbox) on screen
  640. */
  641. void LineList_ForceRedraw(LPLINELIST lpLL, BOOL fErase)
  642. {
  643. InvalidateRect(lpLL->m_hWndListBox, NULL, fErase);
  644. }
  645. /* LineList_ForceLineRedraw
  646. * ------------------------
  647. *
  648. * Force a particular line of the linelist (listbox) to redraw.
  649. */
  650. void LineList_ForceLineRedraw(LPLINELIST lpLL, int nIndex, BOOL fErase)
  651. {
  652. RECT rect;
  653. LineList_GetLineRect( lpLL, nIndex, (LPRECT)&rect );
  654. InvalidateRect( lpLL->m_hWndListBox, (LPRECT)&rect, fErase );
  655. }
  656. /* LineList_ScrollLineIntoView
  657. * ---------------------------
  658. * Make sure that the specified line is in view; if necessary scroll
  659. * the listbox. if any portion of the line is visible, then no
  660. * scrolling will occur.
  661. */
  662. void LineList_ScrollLineIntoView(LPLINELIST lpLL, int nIndex)
  663. {
  664. RECT rcWindow;
  665. RECT rcLine;
  666. RECT rcInt;
  667. if ( lpLL->m_nNumLines == 0 )
  668. return;
  669. if (! LineList_GetLineRect( lpLL, nIndex, (LPRECT)&rcLine ) )
  670. return;
  671. GetClientRect( lpLL->m_hWndListBox, (LPRECT) &rcWindow );
  672. if (! IntersectRect((LPRECT)&rcInt, (LPRECT)&rcWindow, (LPRECT)&rcLine))
  673. SendMessage(
  674. lpLL->m_hWndListBox,
  675. LB_SETTOPINDEX,
  676. (WPARAM)nIndex,
  677. (LPARAM)NULL
  678. );
  679. }
  680. /* LineList_CopySelToDoc
  681. * ---------------------
  682. *
  683. * Copy the selection of the linelist to another document
  684. *
  685. * RETURNS: number of lines copied.
  686. */
  687. int LineList_CopySelToDoc(
  688. LPLINELIST lpSrcLL,
  689. LPLINERANGE lplrSel,
  690. LPOUTLINEDOC lpDestDoc
  691. )
  692. {
  693. int nEndLine;
  694. int nStartLine;
  695. LPLINELIST lpDestLL = &lpDestDoc->m_LineList;
  696. signed short nDestIndex = LineList_GetFocusLineIndex(lpDestLL);
  697. LPLINE lpSrcLine;
  698. int nCopied = 0;
  699. int i;
  700. if (lplrSel) {
  701. nEndLine = lplrSel->m_nEndLine;
  702. nStartLine = lplrSel->m_nStartLine;
  703. } else {
  704. nEndLine = LineList_GetCount(lpSrcLL) - 1;
  705. nStartLine = 0;
  706. }
  707. for(i = nStartLine; i <= nEndLine; i++) {
  708. lpSrcLine = LineList_GetLine(lpSrcLL, i);
  709. if (lpSrcLine && Line_CopyToDoc(lpSrcLine, lpDestDoc, nDestIndex)) {
  710. nDestIndex++;
  711. nCopied++;
  712. }
  713. }
  714. return nCopied;
  715. }
  716. /* LineList_SaveSelToStg
  717. * ---------------------
  718. *
  719. * Save lines in selection into lpDestStg.
  720. *
  721. * Return TRUE if ok, FALSE if error
  722. */
  723. BOOL LineList_SaveSelToStg(
  724. LPLINELIST lpLL,
  725. LPLINERANGE lplrSel,
  726. UINT uFormat,
  727. LPSTORAGE lpSrcStg,
  728. LPSTORAGE lpDestStg,
  729. LPSTREAM lpLLStm,
  730. BOOL fRemember
  731. )
  732. {
  733. int nEndLine;
  734. int nStartLine;
  735. int nNumLinesWritten = 0;
  736. HRESULT hrErr = NOERROR;
  737. ULONG nWritten;
  738. LPLINE lpLine;
  739. LINELISTHEADER_ONDISK llhRecord;
  740. int i;
  741. LARGE_INTEGER dlibSaveHeaderPos;
  742. LARGE_INTEGER dlibZeroOffset;
  743. LISet32( dlibZeroOffset, 0 );
  744. if (lplrSel) {
  745. nEndLine = lplrSel->m_nEndLine;
  746. nStartLine = lplrSel->m_nStartLine;
  747. } else {
  748. nEndLine = LineList_GetCount(lpLL) - 1;
  749. nStartLine = 0;
  750. }
  751. _fmemset(&llhRecord,0,sizeof(llhRecord));
  752. /* save seek position for LineList header record */
  753. hrErr = lpLLStm->lpVtbl->Seek(
  754. lpLLStm,
  755. dlibZeroOffset,
  756. STREAM_SEEK_CUR,
  757. (ULARGE_INTEGER FAR*)&dlibSaveHeaderPos
  758. );
  759. if (hrErr != NOERROR) goto error;
  760. /* write LineList header record */
  761. hrErr = lpLLStm->lpVtbl->Write(
  762. lpLLStm,
  763. (LPVOID)&llhRecord,
  764. sizeof(llhRecord),
  765. &nWritten
  766. );
  767. if (hrErr != NOERROR) {
  768. OleDbgOutHResult("Write LineList header returned", hrErr);
  769. goto error;
  770. }
  771. for(i = nStartLine; i <= nEndLine; i++) {
  772. lpLine = LineList_GetLine(lpLL, i);
  773. if(lpLine &&
  774. Line_SaveToStg(lpLine, uFormat, lpSrcStg, lpDestStg, lpLLStm,
  775. fRemember))
  776. llhRecord.m_nNumLines++;
  777. }
  778. /* retore seek position for LineList header record */
  779. hrErr = lpLLStm->lpVtbl->Seek(
  780. lpLLStm,
  781. dlibSaveHeaderPos,
  782. STREAM_SEEK_SET,
  783. NULL
  784. );
  785. if (hrErr != NOERROR) goto error;
  786. /* write LineList header record */
  787. hrErr = lpLLStm->lpVtbl->Write(
  788. lpLLStm,
  789. (LPVOID)&llhRecord,
  790. sizeof(llhRecord),
  791. &nWritten
  792. );
  793. if (hrErr != NOERROR) goto error;
  794. /* reset seek position to end of stream */
  795. hrErr = lpLLStm->lpVtbl->Seek(
  796. lpLLStm,
  797. dlibZeroOffset,
  798. STREAM_SEEK_END,
  799. NULL
  800. );
  801. if (hrErr != NOERROR) goto error;
  802. return TRUE;
  803. error:
  804. #if defined( _DEBUG )
  805. OleDbgAssertSz(
  806. hrErr == NOERROR,
  807. "Could not write LineList header to LineList stream"
  808. );
  809. #endif
  810. return FALSE;
  811. }
  812. /* LineList_LoadFromStg
  813. * --------------------
  814. *
  815. * Load lines into linelist from storage.
  816. *
  817. * Return TRUE if ok, FALSE if error
  818. */
  819. BOOL LineList_LoadFromStg(
  820. LPLINELIST lpLL,
  821. LPSTORAGE lpSrcStg,
  822. LPSTREAM lpLLStm
  823. )
  824. {
  825. HRESULT hrErr;
  826. ULONG nRead;
  827. LPLINE lpLine;
  828. int i;
  829. int nNumLines;
  830. LINELISTHEADER_ONDISK llineRecord;
  831. /* write LineList header record */
  832. hrErr = lpLLStm->lpVtbl->Read(
  833. lpLLStm,
  834. (LPVOID)&llineRecord,
  835. sizeof(llineRecord),
  836. &nRead
  837. );
  838. if (hrErr != NOERROR) {
  839. OleDbgOutHResult("Read LineList header returned", hrErr);
  840. goto error;
  841. }
  842. nNumLines = (int) llineRecord.m_nNumLines;
  843. for(i = 0; i < nNumLines; i++) {
  844. lpLine = Line_LoadFromStg(lpSrcStg, lpLLStm, lpLL->m_lpDoc);
  845. if (! lpLine)
  846. goto error;
  847. // Directly add lines to LineList without trying to update a NameTbl
  848. LineList_AddLine(lpLL, lpLine, i-1);
  849. }
  850. return TRUE;
  851. error:
  852. // Delete any Line objects that were created
  853. if (lpLL->m_nNumLines > 0) {
  854. int nNumLines = lpLL->m_nNumLines;
  855. for (i = 0; i < nNumLines; i++)
  856. LineList_DeleteLine(lpLL, i);
  857. }
  858. return FALSE;
  859. }
  860. #if defined( USE_DRAGDROP )
  861. /* LineList_SetFocusLineFromPointl
  862. * -------------------------------
  863. *
  864. */
  865. void LineList_SetFocusLineFromPointl( LPLINELIST lpLL, POINTL pointl )
  866. {
  867. int i = LineList_GetLineIndexFromPointl( lpLL, pointl );
  868. if ( i == (int)-1)
  869. return ;
  870. else
  871. LineList_SetFocusLine( lpLL, (WORD)i );
  872. }
  873. /* LineList_SetDragOverLineFromPointl
  874. * ----------------------------------
  875. *
  876. */
  877. void LineList_SetDragOverLineFromPointl ( LPLINELIST lpLL, POINTL pointl )
  878. {
  879. int nIndex = LineList_GetLineIndexFromPointl( lpLL, pointl );
  880. LPLINE lpline = LineList_GetLine( lpLL, nIndex );
  881. if (!lpline)
  882. return;
  883. if (! lpline->m_fDragOverLine) {
  884. /* user has dragged over a new line. force new drop target line
  885. ** to repaint so that drop feedback will be drawn.
  886. */
  887. lpline->m_fDragOverLine = TRUE;
  888. LineList_ForceLineRedraw( lpLL, nIndex, TRUE /*fErase*/);
  889. if (lpLL->m_iDragOverLine!= -1 && lpLL->m_iDragOverLine!=nIndex) {
  890. /* force previous drop target line to repaint so that drop
  891. ** feedback will be undrawn
  892. */
  893. lpline = LineList_GetLine( lpLL, lpLL->m_iDragOverLine );
  894. if (lpline)
  895. lpline->m_fDragOverLine = FALSE;
  896. LineList_ForceLineRedraw(
  897. lpLL,lpLL->m_iDragOverLine,TRUE /*fErase*/);
  898. }
  899. lpLL->m_iDragOverLine = nIndex;
  900. // Force repaint immediately
  901. UpdateWindow(lpLL->m_hWndListBox);
  902. }
  903. }
  904. /* LineList_Scroll
  905. * ---------------
  906. *
  907. * Scroll the LineList list box in the desired direction by one line.
  908. *
  909. * this function is called during a drag operation.
  910. */
  911. void LineList_Scroll(LPLINELIST lpLL, DWORD dwScrollDir)
  912. {
  913. switch (dwScrollDir) {
  914. case SCROLLDIR_UP:
  915. SendMessage( lpLL->m_hWndListBox, WM_VSCROLL, SB_LINEUP, 0L );
  916. break;
  917. case SCROLLDIR_DOWN:
  918. SendMessage( lpLL->m_hWndListBox, WM_VSCROLL, SB_LINEDOWN, 0L );
  919. break;
  920. }
  921. }
  922. /* LineList_GetLineIndexFromPointl
  923. * -------------------------------
  924. * do hit test to get index of line corresponding to pointl
  925. */
  926. int LineList_GetLineIndexFromPointl(LPLINELIST lpLL, POINTL pointl)
  927. {
  928. RECT rect;
  929. POINT point;
  930. DWORD i;
  931. point.x = (int)pointl.x;
  932. point.y = (int)pointl.y;
  933. ScreenToClient( lpLL->m_hWndListBox, &point);
  934. if ( lpLL->m_nNumLines == 0 )
  935. return -1;
  936. GetClientRect( lpLL->m_hWndListBox, (LPRECT) &rect );
  937. i = SendMessage( lpLL->m_hWndListBox, LB_GETTOPINDEX, (WPARAM)NULL, (LPARAM)NULL );
  938. for ( ;; i++){
  939. RECT rectItem;
  940. if (!LineList_GetLineRect( lpLL, (int)i, (LPRECT)&rectItem ) )
  941. return -1;
  942. if ( rectItem.top > rect.bottom )
  943. return -1;
  944. if ( rectItem.top <= point.y && point.y <= rectItem.bottom)
  945. return (int)i;
  946. }
  947. }
  948. /* LineList_RestoreDragFeedback
  949. * ----------------------------
  950. *
  951. * Retore the index of the line that currently has focus (the active line).
  952. */
  953. void LineList_RestoreDragFeedback(LPLINELIST lpLL)
  954. {
  955. LPLINE lpLine;
  956. if (lpLL->m_iDragOverLine < 0 )
  957. return;
  958. lpLine = LineList_GetLine( lpLL, lpLL->m_iDragOverLine);
  959. if (lpLine) {
  960. lpLine->m_fDragOverLine = FALSE;
  961. LineList_ForceLineRedraw( lpLL,lpLL->m_iDragOverLine,TRUE /*fErase*/);
  962. // Force repaint immediately
  963. UpdateWindow(lpLL->m_hWndListBox);
  964. }
  965. lpLL->m_iDragOverLine = -1;
  966. }
  967. #endif