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.

1097 lines
28 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1996 - 2000.
  5. //
  6. // File: brview.cxx
  7. //
  8. // Contents:
  9. //
  10. // History: 15 Aug 1996 DLee Created
  11. //
  12. //--------------------------------------------------------------------------
  13. #include <pch.cxx>
  14. #pragma hdrstop
  15. #define TheModel _layout.GetModel()
  16. #define UNICODE_PARAGRAPH_SEPARATOR 0x2029
  17. const int BUFLEN = 256;
  18. WCHAR LineBuffer[BUFLEN];
  19. const int cpLeftMargin = 3;
  20. int TrimEOL (WCHAR * pwcLine, int cwcLine)
  21. {
  22. // If the line ends in \r\n or \n, don't include that in the length.
  23. // TabbedTextOut() prints garbage when it sees \r or \n
  24. if ((cwcLine >= 2) && (pwcLine[cwcLine - 2] == L'\r'))
  25. cwcLine -= 2;
  26. else if ((cwcLine >= 1) &&
  27. ((pwcLine[cwcLine - 1] == L'\r') ||
  28. (pwcLine[cwcLine - 1] == UNICODE_PARAGRAPH_SEPARATOR) ||
  29. (pwcLine[cwcLine - 1] == L'\n')))
  30. cwcLine--;
  31. return cwcLine;
  32. } //TrimEOL
  33. void TextMetrics::GetSizes ( CharDim& dim )
  34. {
  35. dim.cxChar = _tm.tmAveCharWidth;
  36. dim.cyChar = _tm.tmHeight + _tm.tmExternalLeading;
  37. } //GetSizes
  38. void View::_NoSelection()
  39. {
  40. _Selection.None();
  41. } //NoSelection
  42. void View::_UpdateSelection(
  43. LPARAM lParam )
  44. {
  45. int x = (int) (short) LOWORD( lParam );
  46. int y = (int) (short) HIWORD( lParam );
  47. if ( y < 0 )
  48. y = 0;
  49. else if ( y > _cyClient )
  50. y = _cyClient;
  51. int para, o;
  52. GetParaAndOffset( x, y, para, o );
  53. if ( _fStartIsAnchor )
  54. {
  55. if ( ( para < _Selection.ParaStart() ) ||
  56. ( ( para == _Selection.ParaStart() ) &&
  57. ( o < _Selection.OffStart() ) ) )
  58. {
  59. _Selection.SetEnd( _Selection.ParaStart(), _Selection.OffStart() );
  60. _Selection.SetStart( para, o );
  61. _fStartIsAnchor = FALSE;
  62. }
  63. else
  64. {
  65. _Selection.SetEnd( para, o );
  66. }
  67. }
  68. else
  69. {
  70. if ( ( para > _Selection.ParaEnd() ) ||
  71. ( ( para == _Selection.ParaEnd() ) &&
  72. ( o > _Selection.OffEnd() ) ) )
  73. {
  74. _Selection.SetStart( _Selection.ParaEnd(), _Selection.OffEnd() );
  75. _Selection.SetEnd( para, o );
  76. _fStartIsAnchor = TRUE;
  77. }
  78. else
  79. {
  80. _Selection.SetStart( para, o );
  81. }
  82. }
  83. if ( _fFullSelRepaint )
  84. {
  85. InvalidateRect( _hwnd, NULL, FALSE );
  86. _fFullSelRepaint = FALSE;
  87. }
  88. else
  89. {
  90. int yMin = __min( y, _cpLastSelY );
  91. int yMax = __max( y, _cpLastSelY );
  92. RECT rc;
  93. rc.left = 0;
  94. rc.right = _cxClient;
  95. rc.top = yMin - LineHeight();
  96. rc.bottom = yMax + LineHeight();
  97. InvalidateRect( _hwnd, &rc, FALSE );
  98. }
  99. _cpLastSelY = y;
  100. } //_UpdateSelection
  101. void View::ButtonUp( WPARAM wParam, LPARAM lParam )
  102. {
  103. _fSelecting = FALSE;
  104. if ( GetCapture() == _hwnd )
  105. ReleaseCapture();
  106. if ( _fDblClk )
  107. return;
  108. if ( _Selection.IsNull() )
  109. {
  110. _Selection.None();
  111. return;
  112. }
  113. else
  114. {
  115. _UpdateSelection( lParam );
  116. }
  117. } //ButtonUp
  118. void View::MouseMove( WPARAM wParam, LPARAM lParam )
  119. {
  120. if ( _fSelecting &&
  121. ( wParam & MK_LBUTTON ) )
  122. _UpdateSelection( lParam );
  123. } //MouseMove
  124. void View::ButtonDown( WPARAM wParam, LPARAM lParam )
  125. {
  126. BOOL fOldSel = _Selection.SelectionExists();
  127. _fDblClk = FALSE;
  128. SetCapture( _hwnd );
  129. _fStartIsAnchor = TRUE;
  130. _fSelecting = TRUE;
  131. _NoSelection();
  132. int x = LOWORD( lParam );
  133. int y = HIWORD( lParam );
  134. _cpLastSelY = y;
  135. int para, o;
  136. GetParaAndOffset( x, y, para, o );
  137. _Selection.SetStart( para, o );
  138. _fFullSelRepaint = FALSE;
  139. if ( fOldSel )
  140. InvalidateRect( _hwnd, NULL, FALSE );
  141. } //ButtonDown
  142. int GetCharOffset(
  143. HDC hdc,
  144. int iClickX,
  145. WCHAR * pwcLine,
  146. int cwcLine,
  147. int cpLeft )
  148. {
  149. // a click in the left margin counts
  150. if ( 0 != cwcLine && iClickX < cpLeft )
  151. return 0;
  152. int l = cpLeft;
  153. for ( int c = 0; c < cwcLine; c++ )
  154. {
  155. int dx = LOWORD( GetTabbedTextExtent( hdc, pwcLine, 1 + c, 0, 0 ) );
  156. if ( iClickX >= l && iClickX <= dx + cpLeft )
  157. break;
  158. l = dx + cpLeft;
  159. }
  160. return c;
  161. } //GetCharOffset
  162. void View::GetParaAndOffset(
  163. int x,
  164. int y,
  165. int & para,
  166. int & offset )
  167. {
  168. offset = 0;
  169. HDC hdc = GetDC( _hwnd );
  170. if ( 0 == hdc )
  171. return;
  172. HFONT hOldFont = (HFONT) SelectObject( hdc, _layout.Font() );
  173. para = _layout.FirstPara();
  174. int paLine = _layout.FirstLineInPara(); // line within paragraph
  175. int paOffBeg; // line beginning offset within paragraph
  176. int paOffEnd; // line end offset within paragraph
  177. int line = 0; // line # counting from top of window
  178. int left = cpLeftMargin - _layout.XBegin();
  179. while ( _layout.GetLineOffsets( para, paLine, paOffBeg, paOffEnd ) )
  180. {
  181. do
  182. {
  183. int top = _layout.Y ( line );
  184. int bottom = top + _layout.CyChar();
  185. if ( y >= top && y <= bottom )
  186. {
  187. // got the line, now find the word selected
  188. int cwcLine = __min ( BUFLEN, paOffEnd - paOffBeg );
  189. if ( TheModel.GetLine(para, paOffBeg, cwcLine, LineBuffer ) )
  190. {
  191. cwcLine = TrimEOL( LineBuffer, cwcLine );
  192. offset = paOffBeg + GetCharOffset( hdc,
  193. x,
  194. LineBuffer,
  195. cwcLine,
  196. cpLeftMargin );
  197. }
  198. goto cleanup;
  199. }
  200. line++;
  201. if (line >= _layout.MaxLines())
  202. goto cleanup;
  203. paLine++;
  204. } while ( _layout.GetLineOffsets( para, paLine, paOffBeg, paOffEnd ) );
  205. // next paragraph
  206. para++;
  207. paLine = 0;
  208. }
  209. cleanup:
  210. SelectObject( hdc, hOldFont );
  211. ReleaseDC( _hwnd, hdc );
  212. } //GetParaAndOffset
  213. void View::EditCopy( HWND hwnd, WPARAM wParam )
  214. {
  215. if ( _Selection.SelectionExists() )
  216. {
  217. // is everything in one paragraph? -- easy case
  218. if ( _Selection.IsInOnePara() )
  219. {
  220. int cwcLine = __min ( BUFLEN,
  221. _Selection.OffEnd() - _Selection.OffStart() );
  222. TheModel.GetLine( _Selection.ParaStart(),
  223. _Selection.OffStart(),
  224. cwcLine, LineBuffer );
  225. cwcLine = TrimEOL( LineBuffer, cwcLine );
  226. LineBuffer[cwcLine] = 0;
  227. PutInClipboard( LineBuffer );
  228. }
  229. else
  230. {
  231. // compute how much text to copy
  232. int cwcTotal = 0;
  233. for ( int p = _Selection.ParaStart();
  234. p <= _Selection.ParaEnd();
  235. p++ )
  236. {
  237. int cwcLine = BUFLEN;
  238. if ( p == _Selection.ParaStart() )
  239. {
  240. TheModel.GetLine( p, _Selection.OffStart(),
  241. cwcLine, LineBuffer );
  242. }
  243. else if ( p == _Selection.ParaEnd() )
  244. {
  245. TheModel.GetLine( p, 0, cwcLine, LineBuffer );
  246. cwcLine = _Selection.OffEnd();
  247. }
  248. else
  249. {
  250. TheModel.GetLine( p, 0, cwcLine, LineBuffer );
  251. }
  252. cwcTotal += cwcLine;
  253. }
  254. // allocate a buffer and copy the text
  255. XArray<WCHAR> aClip( cwcTotal + 1 );
  256. WCHAR *pwc = (WCHAR *) aClip.GetPointer();
  257. cwcTotal = 0;
  258. for ( p = _Selection.ParaStart();
  259. p <= _Selection.ParaEnd();
  260. p++ )
  261. {
  262. int cwcLine = BUFLEN;
  263. if ( p == _Selection.ParaStart() )
  264. {
  265. TheModel.GetLine( p, _Selection.OffStart(),
  266. cwcLine, LineBuffer );
  267. }
  268. else if ( p == _Selection.ParaEnd() )
  269. {
  270. TheModel.GetLine( p, 0, cwcLine, LineBuffer );
  271. cwcLine = _Selection.OffEnd();
  272. }
  273. else
  274. {
  275. TheModel.GetLine( p, 0, cwcLine, LineBuffer );
  276. }
  277. LineBuffer[cwcLine] = 0;
  278. wcscpy( pwc + cwcTotal, LineBuffer );
  279. cwcTotal += cwcLine;
  280. }
  281. PutInClipboard( pwc );
  282. }
  283. }
  284. } //EditCopy
  285. BOOL isWhite( WCHAR c )
  286. {
  287. // well, actually white space and C++ break characters
  288. return ( L' ' == c ||
  289. L'\r' == c ||
  290. L'\n' == c ||
  291. L'\t' == c ||
  292. L'\\' == c ||
  293. L'\'' == c ||
  294. L'\"' == c ||
  295. L':' == c ||
  296. L';' == c ||
  297. L',' == c ||
  298. L'[' == c ||
  299. L']' == c ||
  300. L'{' == c ||
  301. L'}' == c ||
  302. L'(' == c ||
  303. L')' == c ||
  304. L'/' == c ||
  305. L'+' == c ||
  306. L'-' == c ||
  307. L'=' == c ||
  308. L'*' == c ||
  309. L'^' == c ||
  310. L'~' == c ||
  311. L'&' == c ||
  312. L'!' == c ||
  313. L'?' == c ||
  314. L'<' == c ||
  315. L'>' == c ||
  316. L'.' == c ||
  317. L'|' == c ||
  318. UNICODE_PARAGRAPH_SEPARATOR == c );
  319. } //isWhite
  320. BOOL GetSelectedWord(
  321. HDC hdc,
  322. int iClickX,
  323. WCHAR *pwcLine,
  324. int cwcLine,
  325. int cpLeft,
  326. int &rStart,
  327. int &rEnd )
  328. {
  329. // what character had the click?
  330. int c = GetCharOffset( hdc, iClickX, pwcLine, cwcLine, cpLeft );
  331. // move left and right till white space is found
  332. if ( c != cwcLine )
  333. {
  334. rEnd = c;
  335. while ( rEnd < (cwcLine - 1) && !isWhite( pwcLine[ rEnd ] ) )
  336. rEnd++;
  337. // selection doesn't include end
  338. if ( ( rEnd == ( cwcLine - 1 ) ) &&
  339. ( !isWhite( pwcLine[ rEnd ] ) ) )
  340. rEnd++;
  341. rStart = c;
  342. while ( rStart > 0 && !isWhite( pwcLine[ rStart ] ) )
  343. rStart--;
  344. // don't include white space if not at start of line
  345. if ( rStart < c && isWhite( pwcLine[ rStart ] ) )
  346. rStart++;
  347. // did we grab anything?
  348. return ( rEnd > rStart );
  349. }
  350. else
  351. {
  352. return FALSE;
  353. }
  354. } //GetSelectedWord
  355. int View::ParaFromY(
  356. int y )
  357. {
  358. int para = _layout.FirstPara();
  359. int paLine = _layout.FirstLineInPara(); // line within paragraph
  360. int paOffBeg; // line beginning offset within paragraph
  361. int paOffEnd; // line end offset within paragraph
  362. int line = 0; // line # counting from top of window
  363. int left = cpLeftMargin - _layout.XBegin();
  364. while ( _layout.GetLineOffsets( para, paLine, paOffBeg, paOffEnd ) )
  365. {
  366. do
  367. {
  368. int top = _layout.Y( line );
  369. int bottom = top + _layout.CyChar();
  370. if ( y >= top && y <= bottom )
  371. {
  372. return 1 + para;
  373. }
  374. line++;
  375. if (line >= _layout.MaxLines())
  376. return _layout.FirstPara();
  377. paLine++;
  378. } while ( _layout.GetLineOffsets( para, paLine, paOffBeg, paOffEnd ) );
  379. // next paragraph
  380. para++;
  381. paLine = 0;
  382. }
  383. return _layout.FirstPara();
  384. } //ParaFromY
  385. void View::DblClk( WPARAM wParam, LPARAM lParam )
  386. {
  387. _fDblClk = TRUE;
  388. BOOL fCtrl = ( 0 != ( 0x8000 & GetAsyncKeyState( VK_CONTROL ) ) );
  389. int x = LOWORD( lParam );
  390. int y = HIWORD( lParam );
  391. Selection oldSel( _Selection );
  392. _Selection.None();
  393. HDC hdc = GetDC( _hwnd );
  394. if ( 0 == hdc )
  395. return;
  396. HFONT hOldFont = (HFONT) SelectObject( hdc, _layout.Font() );
  397. int para = _layout.FirstPara();
  398. int paLine = _layout.FirstLineInPara(); // line within paragraph
  399. int paOffBeg; // line beginning offset within paragraph
  400. int paOffEnd; // line end offset within paragraph
  401. int line = 0; // line # counting from top of window
  402. int left = cpLeftMargin - _layout.XBegin();
  403. while (_layout.GetLineOffsets ( para, paLine, paOffBeg, paOffEnd ))
  404. {
  405. do
  406. {
  407. int top = _layout.Y ( line );
  408. int bottom = top + _layout.CyChar();
  409. if ( y >= top && y <= bottom )
  410. {
  411. // if ctrl key is down, attempt to fire up an editor
  412. if ( fCtrl )
  413. {
  414. ViewFile( _pModel->Filename(), fileEdit, 1+para );
  415. goto cleanup;
  416. }
  417. // got the line, now find the word selected
  418. int cwcLine = __min ( BUFLEN, paOffEnd - paOffBeg );
  419. if ( TheModel.GetLine(para, paOffBeg, cwcLine, LineBuffer ) )
  420. {
  421. cwcLine = TrimEOL( LineBuffer, cwcLine );
  422. int iStart, iEnd;
  423. if ( GetSelectedWord( hdc,
  424. x,
  425. LineBuffer,
  426. cwcLine,
  427. cpLeftMargin,
  428. iStart,
  429. iEnd ) )
  430. _Selection.Set( para,
  431. paOffBeg + iStart,
  432. para,
  433. paOffBeg + iEnd );
  434. RECT rc;
  435. rc.left = 0; rc.right = _cxClient;
  436. rc.top = top; rc.bottom = bottom;
  437. InvalidateRect( _hwnd, &rc, FALSE );
  438. }
  439. }
  440. else if ( oldSel.IsInSelection( para ) )
  441. {
  442. RECT rc;
  443. rc.left = 0; rc.right = _cxClient;
  444. rc.top = top; rc.bottom = bottom;
  445. InvalidateRect( _hwnd, &rc, FALSE );
  446. }
  447. line++;
  448. if (line >= _layout.MaxLines())
  449. goto cleanup;
  450. paLine++;
  451. } while (_layout.GetLineOffsets (para, paLine, paOffBeg, paOffEnd ));
  452. // next paragraph
  453. para++;
  454. paLine = 0;
  455. }
  456. cleanup:
  457. SelectObject( hdc, hOldFont );
  458. ReleaseDC( _hwnd, hdc );
  459. UpdateWindow( _hwnd );
  460. } //DblClk
  461. void View::Size ( int cx, int cy )
  462. {
  463. _cyClient = cy;
  464. _cxClient = cx;
  465. }
  466. void View::SetScrollMax ()
  467. {
  468. int linesFromEnd = _cyClient / _layout.CyChar() - 2;
  469. int cline;
  470. for (int para = TheModel.Paras() - 1; para >= 0; para--)
  471. {
  472. cline = _layout.LinesInPara(para);
  473. if (linesFromEnd < cline)
  474. break;
  475. linesFromEnd -= cline;
  476. }
  477. _paraVScrollMax = TheModel.Paras() - 1;
  478. if ( _paraVScrollMax < 0 )
  479. {
  480. _paraVScrollMax = 0;
  481. _paLineVScrollMax = 0;
  482. }
  483. else
  484. {
  485. _paLineVScrollMax = cline - 1 - linesFromEnd;
  486. }
  487. }
  488. void View::SetRange ( int maxParaLen, int cParas )
  489. {
  490. _layout.SetParaRange(cParas);
  491. #if 0
  492. _nHScrollMax = 2 + maxParaLen - _cxClient / _layout.CxChar();
  493. if ( _nHScrollMax < 0 )
  494. #endif
  495. _nHScrollMax = 0;
  496. }
  497. void View::SetScroll( Position & pos )
  498. {
  499. _fFullSelRepaint = TRUE;
  500. int paLine, paOffBeg, paOffEnd;
  501. _layout.Locate (pos.Para(), pos.BegOff(), paLine, paOffBeg, paOffEnd);
  502. if (paLine >= 3)
  503. {
  504. _paraVScroll = pos.Para();
  505. _paLineVScroll = paLine - 3;
  506. }
  507. else
  508. {
  509. // show last line of prev para
  510. int iOffset = ( 0 == _cyClient ) ? 6 : ( VisibleLines() / 3 );
  511. _paraVScroll = pos.Para() - iOffset;
  512. if (_paraVScroll >= 0 )
  513. {
  514. _paLineVScroll = _layout.LinesInPara(_paraVScroll) - 1;
  515. }
  516. else
  517. {
  518. _paraVScroll = 0;
  519. _paLineVScroll = 0;
  520. }
  521. }
  522. #if 0
  523. if ( pos.EndOff() - _nHScrollPos + 1 > _cxClient / _layout.CxChar() )
  524. _nHScrollPos = pos.EndOff() - _cxClient / _layout.CxChar() + 1;
  525. else
  526. _nHScrollPos = 0;
  527. _nHScrollPos = min ( _nHScrollPos, _nHScrollMax );
  528. #else
  529. _nHScrollPos = 0;
  530. #endif
  531. }
  532. int View::JumpToPara ( int para )
  533. {
  534. _fFullSelRepaint = TRUE;
  535. int delta = 0;
  536. int paraStart;
  537. int paraEnd;
  538. if (para == _paraVScroll)
  539. {
  540. return 0;
  541. }
  542. else if (para < _paraVScroll)
  543. {
  544. // jumping backwards, delta negative
  545. delta = -_paLineVScroll;
  546. for ( int p = _paraVScroll - 1; p >= para; p--)
  547. delta -= _layout.LinesInPara(p);
  548. }
  549. else
  550. {
  551. // jumping forward, delta positive
  552. delta = _layout.LinesInPara(_paraVScroll) - _paLineVScroll;
  553. for (int p = _paraVScroll + 1; p < para; p++)
  554. delta += _layout.LinesInPara(p);
  555. }
  556. _paraVScroll = para;
  557. _paLineVScroll = 0;
  558. // return delta from previous position
  559. return delta;
  560. }
  561. int View::IncVScrollPos ( int cLine )
  562. {
  563. _fFullSelRepaint = TRUE;
  564. int para;
  565. if (cLine >= 0)
  566. {
  567. // first back up to the beginning
  568. // of the current para
  569. int cLineLeft = cLine + _paLineVScroll;
  570. // move forward
  571. for (para = _paraVScroll; para <= _paraVScrollMax; para++)
  572. {
  573. int ln = _layout.LinesInPara(para);
  574. if (cLineLeft < ln)
  575. break;
  576. cLineLeft -= ln;
  577. }
  578. if (para > _paraVScrollMax)
  579. {
  580. // overshot the end
  581. // move back
  582. _paraVScroll = _paraVScrollMax;
  583. int cline = _layout.LinesInPara(_paraVScroll);
  584. _paLineVScroll = _paLineVScrollMax;
  585. cLineLeft += cline - _paLineVScrollMax;
  586. cLine -= cLineLeft;
  587. }
  588. else if (para == _paraVScrollMax && cLineLeft > _paLineVScrollMax)
  589. {
  590. _paraVScroll = _paraVScrollMax;
  591. _paLineVScroll = _paLineVScrollMax;
  592. cLineLeft -= _paLineVScrollMax;
  593. cLine -= cLineLeft;
  594. }
  595. else
  596. {
  597. // cLineLeft < Lines In Para
  598. _paraVScroll = para;
  599. _paLineVScroll = cLineLeft;
  600. }
  601. }
  602. else if (cLine < 0)
  603. {
  604. // first skip to the end
  605. // of the current para
  606. int cLineLeft = - cLine + (_layout.LastLineInPara(_paraVScroll) - _paLineVScroll);
  607. // move backward
  608. for (para = _paraVScroll; para >= 0; para--)
  609. {
  610. int ln = _layout.LinesInPara(para);
  611. if (ln > cLineLeft)
  612. break;
  613. cLineLeft -= ln;
  614. }
  615. if (para < 0)
  616. {
  617. // overshot the beginning.
  618. // move up one line
  619. _paraVScroll = 0;
  620. _paLineVScroll = 0;
  621. cLineLeft++;
  622. cLine += cLineLeft;
  623. }
  624. else
  625. {
  626. // cLineLeft < Lines In Para
  627. _paraVScroll = para;
  628. _paLineVScroll = _layout.LinesInPara(para) - cLineLeft - 1;
  629. }
  630. }
  631. return cLine;
  632. }
  633. int View::IncHScrollPos ( int delta )
  634. {
  635. Win4Assert ( FALSE );
  636. // Clip the increment
  637. if ( delta < -_nHScrollPos )
  638. delta = -_nHScrollPos;
  639. else if ( delta > _nHScrollMax - _nHScrollPos )
  640. delta = _nHScrollMax - _nHScrollPos;
  641. _nHScrollPos += delta;
  642. return delta;
  643. }
  644. void View::Paint( HWND hwnd )
  645. {
  646. _layout.Adjust ( _cxClient, _cyClient, _paraVScroll, _paLineVScroll, _nHScrollPos);
  647. PaintText paint (hwnd, _paraVScroll, _paLineVScroll, _layout, _Selection);
  648. paint.PrintLines ();
  649. paint.HiliteHits ();
  650. }
  651. PaintText::PaintText(HWND hwnd, int paraFirst, int paLineFirst, Layout& layout,
  652. Selection & Selection )
  653. : Paint(hwnd), _paraFirst(paraFirst), _paLineFirst(paLineFirst),
  654. _layout(layout), _Selection( Selection )
  655. {
  656. _hOldFont = (HFONT) SelectObject ( hdc, _layout.Font() );
  657. SetBkColor ( hdc, GetSysColor(COLOR_WINDOW) );
  658. SetTextColor( hdc, GetSysColor(COLOR_WINDOWTEXT) );
  659. }
  660. PaintText::~PaintText()
  661. {
  662. SelectObject ( hdc, _hOldFont );
  663. }
  664. void Layout::SetParaRange (int cParas)
  665. {
  666. _cParas = cParas;
  667. _aParaLine = _pModel->GetParaLine();
  668. }
  669. void Layout::Adjust (int cx, int cy, int& paraVScroll, int& paLineVScroll, int nHScrollPos)
  670. {
  671. _cLine = (cy + _dim.cyChar - 1) / _dim.cyChar;
  672. _cCharWidth = cx / _dim.cxChar;
  673. _xBegin = nHScrollPos * _dim.cxChar;
  674. if ( paraVScroll < 0 )
  675. {
  676. paraVScroll = 0;
  677. paLineVScroll = 0;
  678. }
  679. _paLineFirst = paLineVScroll;
  680. _paraFirst = paraVScroll;
  681. }
  682. int Layout::Y (int line ) const
  683. {
  684. return line * _dim.cyChar;
  685. }
  686. void Layout::Locate (int para, int paOff, int& paLine, int& paOffBeg, int& paOffEnd ) const
  687. {
  688. Win4Assert(para < _cParas);
  689. paLine = 0;
  690. paOffBeg = 0;
  691. for (ParaLine const* p = &_aParaLine[para]; p != 0 && p->offEnd <= paOff; p = p->next)
  692. {
  693. paOffBeg = p->offEnd;
  694. paLine++;
  695. }
  696. if (p == 0)
  697. paOffEnd = 0;
  698. else
  699. paOffEnd = p->offEnd;
  700. }
  701. BOOL Layout::GetLineOffsets (int para, int paLine, int& paOffBeg, int& paOffEnd) const
  702. {
  703. if (para < _paraFirst || para > LastPara() || para >= _cParas)
  704. return FALSE;
  705. ParaLine const * p = &_aParaLine[para];
  706. paOffBeg = 0;
  707. for (int line = 0; line < paLine; line++)
  708. {
  709. paOffBeg = p->offEnd;
  710. p = p->next;
  711. if (p == 0)
  712. return FALSE;
  713. }
  714. paOffEnd = p->offEnd;
  715. Win4Assert ( paOffEnd >= paOffBeg);
  716. return TRUE;
  717. }
  718. int Layout::LastPara() const
  719. {
  720. // at most this number
  721. return _paraFirst + _cLine;
  722. }
  723. int Layout::LineNumber (int para, int paLine) const
  724. {
  725. if (para == _paraFirst)
  726. {
  727. return paLine - _paLineFirst;
  728. }
  729. int curPara = _paraFirst + 1;
  730. int curLine = LinesInPara(_paraFirst) - _paLineFirst;
  731. while (curPara < para)
  732. {
  733. curLine += LinesInPara(curPara);
  734. curPara++;
  735. }
  736. return curLine + paLine;
  737. }
  738. int Layout::LinesInPara (int para) const
  739. {
  740. Win4Assert(para < _cParas);
  741. int line = 1;
  742. for (ParaLine const * p = _aParaLine[para].next; p != 0; p = p->next)
  743. line++;
  744. return line;
  745. }
  746. void EnableHilite( HDC hdc )
  747. {
  748. SetBkColor( hdc, GetSysColor(COLOR_HIGHLIGHT) );
  749. SetTextColor( hdc, GetSysColor(COLOR_HIGHLIGHTTEXT) );
  750. }
  751. void EnableHitHilite( HDC hdc )
  752. {
  753. // SetBkColor( hdc, GetSysColor(COLOR_ACTIVECAPTION) );
  754. // SetTextColor( hdc, GetSysColor(COLOR_CAPTIONTEXT) );
  755. // SetBkColor( hdc, GetSysColor(COLOR_INACTIVECAPTION) );
  756. // SetTextColor( hdc, GetSysColor(COLOR_INACTIVECAPTIONTEXT) );
  757. // SetBkColor( hdc, GetSysColor(COLOR_HIGHLIGHTTEXT) );
  758. // SetTextColor( hdc, GetSysColor(COLOR_HIGHLIGHT) );
  759. SetBkColor( hdc, GetSysColor(COLOR_WINDOWTEXT) );
  760. SetTextColor( hdc, GetSysColor(COLOR_WINDOW) );
  761. // SetBkColor( hdc, GetSysColor(COLOR_HIGHLIGHT) );
  762. // SetTextColor( hdc, GetSysColor(COLOR_HIGHLIGHTTEXT) );
  763. }
  764. void EnableNonCurrentHitHilite( HDC hdc )
  765. {
  766. SetBkColor ( hdc, GetSysColor(COLOR_WINDOW) );
  767. SetTextColor( hdc, GetSysColor(COLOR_HIGHLIGHT) );
  768. }
  769. void DisableHilite( HDC hdc )
  770. {
  771. SetBkColor ( hdc, GetSysColor(COLOR_WINDOW) );
  772. SetTextColor ( hdc, GetSysColor(COLOR_WINDOWTEXT) );
  773. }
  774. void PaintText::PrintLines ()
  775. {
  776. int para = _layout.FirstPara();
  777. int paLine = _layout.FirstLineInPara(); // line within paragraph
  778. int paOffBeg; // line beginning offset within paragraph
  779. int paOffEnd; // line end offset within paragraph
  780. int line = 0; // line # counting from top of window
  781. int left = cpLeftMargin - _layout.XBegin();
  782. while (_layout.GetLineOffsets ( para, paLine, paOffBeg, paOffEnd ))
  783. {
  784. // print paragraph
  785. do
  786. {
  787. // clip to the update rect
  788. int top = _layout.Y ( line );
  789. int bottom = top + _layout.CyChar();
  790. if ( top <= rcPaint.bottom && bottom >= rcPaint.top)
  791. {
  792. int cwcLine = __min ( BUFLEN, paOffEnd - paOffBeg );
  793. if (!TheModel.GetLine( para, paOffBeg, cwcLine, LineBuffer ))
  794. return;
  795. cwcLine = TrimEOL( LineBuffer, cwcLine );
  796. if ( 0 == cwcLine )
  797. {
  798. // to make selections look better...
  799. wcscpy(LineBuffer,L" ");
  800. cwcLine = 1;
  801. }
  802. Win4Assert( cwcLine >= 0 );
  803. if ( _Selection.IsInSelection( para ) )
  804. {
  805. if ( ( para > _Selection.ParaStart() ) &&
  806. ( para < _Selection.ParaEnd() ) )
  807. {
  808. EnableHilite( hdc );
  809. TabbedTextOut( hdc, left, top, LineBuffer, cwcLine,
  810. 0, 0, left );
  811. DisableHilite( hdc );
  812. }
  813. else
  814. {
  815. int l = left;
  816. for ( int c = 0; c < cwcLine; c++ )
  817. {
  818. if ( _Selection.IsInSelection( para, c + paOffBeg ) )
  819. EnableHilite( hdc );
  820. LONG dim = TabbedTextOut( hdc, l, top,
  821. LineBuffer + c, 1,
  822. 0, 0, left );
  823. DisableHilite( hdc );
  824. l += LOWORD(dim);
  825. }
  826. }
  827. }
  828. else
  829. {
  830. TabbedTextOut( hdc, left, top, LineBuffer, cwcLine,
  831. 0, 0, left );
  832. }
  833. }
  834. line++;
  835. if (line >= _layout.MaxLines())
  836. return;
  837. paLine++;
  838. } while (_layout.GetLineOffsets( para, paLine, paOffBeg, paOffEnd ));
  839. // next paragraph
  840. para++;
  841. paLine = 0;
  842. }
  843. } //PrintLines
  844. void PaintText::HiliteHits ()
  845. {
  846. TheModel.HiliteAll( TRUE );
  847. if ( TheModel.FirstHit() )
  848. {
  849. do
  850. {
  851. if ( !TheModel.isSavedCurrent() )
  852. PrintCurrentHit( FALSE );
  853. }
  854. while( TheModel.NextHit() );
  855. TheModel.RestoreHilite();
  856. }
  857. TheModel.HiliteAll( FALSE );
  858. PrintCurrentHit( TRUE );
  859. } //HiliteHits
  860. const int WORDBUFLEN = 80;
  861. static WCHAR WordBuffer [WORDBUFLEN];
  862. void PaintText::PrintCurrentHit( BOOL fCurrent )
  863. {
  864. if ( fCurrent )
  865. EnableHitHilite( hdc );
  866. else
  867. EnableNonCurrentHitHilite( hdc );
  868. int cPos = TheModel.GetPositionCount();
  869. int iPos = 0;
  870. Position pos = TheModel.GetPosition(iPos);
  871. int left = cpLeftMargin - _layout.XBegin();
  872. while ( iPos < cPos )
  873. {
  874. int curPara = pos.Para();
  875. if ( curPara > _layout.LastPara() )
  876. break;
  877. if (curPara >= _layout.FirstPara())
  878. {
  879. int paLine; // line within paragraph
  880. int paOffBeg; // line beginning offset within paragraph
  881. int paOffEnd; // line end offset within paragraph
  882. _layout.Locate ( curPara, pos.BegOff(), paLine, paOffBeg, paOffEnd );
  883. int line = _layout.LineNumber ( curPara, paLine );
  884. // Output the line with highlights
  885. int cwcLine = __min ( BUFLEN, paOffEnd - paOffBeg );
  886. if (!TheModel.GetLine (curPara, paOffBeg, cwcLine, LineBuffer ))
  887. break;
  888. cwcLine = TrimEOL( LineBuffer, cwcLine );
  889. int top = _layout.Y (line);
  890. do
  891. {
  892. int cwc = __min( pos.Len(), WORDBUFLEN);
  893. TheModel.GetWord( curPara, pos.BegOff(), cwc, WordBuffer );
  894. Win4Assert ( cwc >= 0 );
  895. // Find out how much space it takes before the highlight
  896. DWORD dwExt = GetTabbedTextExtent ( hdc,
  897. LineBuffer,
  898. pos.BegOff() - paOffBeg,
  899. 0, 0 );
  900. // Print hilighted text
  901. TabbedTextOut ( hdc,
  902. left + LOWORD(dwExt),
  903. top,
  904. WordBuffer,
  905. cwc,
  906. 0, 0,
  907. left );
  908. iPos++;
  909. if (iPos >= cPos)
  910. break;
  911. pos = TheModel.GetPosition(iPos);
  912. } while ( pos.Para() == curPara );
  913. }
  914. else
  915. {
  916. iPos++;
  917. }
  918. }
  919. DisableHilite( hdc );
  920. } //PrintCurrentHit