home *** CD-ROM | disk | FTP | other *** search
/ io Programmo 23 / IOPROG_23.ISO / SOFT / MSGTRACE.ZIP / MyProjects / MsgTrace / MsgTracer / OutputView.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-05-30  |  30.2 KB  |  1,214 lines

  1. /////////////////////////////////////////////////////////////////////////////
  2. //
  3. // File        : OutputView.cpp
  4. // Project     : MsgTrace
  5. // Component   : MsgTracer
  6. //---------------------------------------------------------------------------
  7. // Description : output-view class
  8. //
  9. /////////////////////////////////////////////////////////////////////////////
  10. //
  11. // SourceSafe Strings. Do not change.
  12. //---------------------------------------------------------------------------
  13. // $Author: jeskes $
  14. // $Date: $
  15. // $Revision: $
  16. //
  17. /////////////////////////////////////////////////////////////////////////////
  18.  
  19. #include "stdafx.h"
  20.  
  21. #include "MsgTracerApp.h"
  22. #include "mainfrm.h"
  23.  
  24. #include "OutputDoc.h"
  25. #include "OutputLine.h"
  26. #include "OutputView.h"
  27.  
  28. #include "ColFont.h"
  29.  
  30. /////////////////////////////////////////////////////////////////////////////
  31.  
  32. #ifdef _DEBUG
  33. #undef THIS_FILE
  34. static char BASED_CODE THIS_FILE[] = __FILE__;
  35. #endif
  36.  
  37. /////////////////////////////////////////////////////////////////////////////
  38.  
  39. #define ENDOFLINE                                    ((int) 0x7fff )
  40. #define ENDOFLINES                                    ((int) 0x7fff )
  41. #define CURRENT_VALUE                                ((int) 0xffff )
  42.  
  43. #define SCROLL_RIGHT                                0x0001
  44. #define SCROLL_LEFT                                    0x0002
  45. #define SCROLL_UP                                    0x0010
  46. #define SCROLL_DOWN                                    0x0020
  47. #define SCROLL_POSITION                                0x0100
  48.  
  49. #define CARET_WIDTH                                    2
  50. #define CARET_HEIGHT                                m_nRowHeight
  51.  
  52. #define CAPTURE_TIMER                                100
  53. #define CAPTURE_TIMER_TIMEOUT                        50
  54.  
  55. /////////////////////////////////////////////////////////////////////////////
  56. // COutputView
  57. /////////////////////////////////////////////////////////////////////////////
  58.  
  59. IMPLEMENT_DYNCREATE(COutputView, CScrollView)
  60.  
  61. BEGIN_MESSAGE_MAP(COutputView, CScrollView)
  62.     //{{AFX_MSG_MAP(COutputView)
  63.     ON_WM_SIZE()
  64.     ON_WM_CREATE()
  65.     ON_WM_SETFOCUS()
  66.     ON_COMMAND(ID_VIEW_FONT, OnViewFont)
  67.     ON_WM_KILLFOCUS()
  68.     ON_WM_SETCURSOR()
  69.     ON_WM_LBUTTONDOWN()
  70.     ON_WM_RBUTTONUP()
  71.     ON_WM_KEYDOWN()
  72.     ON_COMMAND(ID_EDIT_COPY, OnEditCopy)
  73.     ON_UPDATE_COMMAND_UI(ID_EDIT_COPY, OnUpdateEditCopy)
  74.     ON_WM_LBUTTONUP()
  75.     ON_WM_TIMER()
  76.     ON_WM_MOUSEMOVE()
  77.     //}}AFX_MSG_MAP
  78.  
  79.     // Standard Print commands (print only - not preview)
  80.     ON_COMMAND(ID_FILE_PRINT, CScrollView::OnFilePrint)
  81. END_MESSAGE_MAP()
  82.  
  83. /////////////////////////////////////////////////////////////////////////////
  84. // COutputView: construction
  85. /////////////////////////////////////////////////////////////////////////////
  86.  
  87. COutputView::COutputView() :
  88.  
  89.     m_hPrinterFont( NULL ),
  90.     
  91.     m_nPrintRowHeight( 0 ),
  92.     m_nPrintLinesPerPage( 0 ),
  93.  
  94.     m_nMaxVisibleLines( 0 ),
  95.     m_nRowWidth( 0 ),
  96.     m_nRowHeight( 0 ),
  97.  
  98.     m_nCurCol( 0 ),
  99.     m_nCurRow( 0 ),
  100.     m_nSelCol( 0 ),
  101.     m_nSelRow( 0 ),
  102.  
  103.     m_bWhileSelecting( FALSE ),
  104.  
  105.     m_nIDCaptureTimer( 0 )
  106.  
  107. {
  108.     m_pColoredFont = new CColoredFont( "out" );
  109.     m_pTrackMenu = new CMenu;
  110.  
  111.     m_pTrackMenu->LoadMenu( IDR_PROPS_OUTPUTTYPE );
  112. }
  113.  
  114. /////////////////////////////////////////////////////////////////////////////
  115.  
  116. COutputView::~COutputView()
  117. {
  118.     if( NULL != m_hPrinterFont )
  119.     {
  120.         ::DeleteObject( m_hPrinterFont );
  121.     }
  122.  
  123.     delete m_pColoredFont;
  124.     m_pColoredFont = NULL;
  125.  
  126.     delete m_pTrackMenu;
  127.     m_pTrackMenu = NULL;
  128. }
  129.  
  130. /////////////////////////////////////////////////////////////////////////////
  131.  
  132. int COutputView::OnCreate( LPCREATESTRUCT lpCreateStruct )
  133. {
  134.     if( CScrollView::OnCreate( lpCreateStruct ) == -1 )
  135.     {
  136.         return( -1 );
  137.     }
  138.  
  139.     return( 0 );
  140. }
  141.  
  142. /////////////////////////////////////////////////////////////////////////////
  143.  
  144. COutputDoc* COutputView::GetDocument()
  145.     return( (COutputDoc*) m_pDocument ); 
  146. }
  147.  
  148. /////////////////////////////////////////////////////////////////////////////
  149.  
  150. void COutputView::OnInitialUpdate()
  151. {
  152.     CScrollView::OnInitialUpdate();
  153.     UpdateScrollSizes();
  154. }
  155.  
  156. /////////////////////////////////////////////////////////////////////////////
  157.  
  158. void COutputView::OnUpdate( CView* pSender, LPARAM lHint, CObject* pHint )
  159. {
  160.     if( OUTPUTDOC_LINEADDED == lHint )
  161.     {
  162.         COutputLine* pLine = (COutputLine*) pHint;
  163.  
  164.         if( NULL == pLine )
  165.         {
  166.             return;
  167.         }
  168.  
  169.         CClientDC dc( this );
  170.  
  171.         CSize sizeText = dc.GetTabbedTextExtent( (const char*) *pLine, 
  172.                                                  pLine->GetLength(), 
  173.                                                  pLine->GetFormat().GetTabStops(), 
  174.                                                  (int*) pLine->GetFormat().GetTabStopPositionsPixel( dc ) );
  175.  
  176.         m_nRowWidth = max( m_nRowWidth, sizeText.cx );
  177.  
  178.         UpdateScrollSizes();
  179.         
  180.         
  181.         /***
  182.         int nMax = GetDocument()->GetMaxLines();
  183.         int nVis = GetMaxVisibleLines();
  184.  
  185.         if( nMax > nVis )
  186.         {
  187.             ScrollToDevicePosition( CPoint( 0, ( nMax - nVis ) * m_nRowHeight ) );
  188.         }
  189.         ***/
  190.  
  191.         Invalidate();
  192.         SetCurPos( 0, GetDocument()->GetMaxLines() - 1 );
  193.     }
  194.     else if( OUTPUTDOC_CLEARED == lHint )
  195.     {
  196.         m_nSelCol = 0;
  197.         m_nSelCol = 0;
  198.         m_bWhileSelecting = FALSE;
  199.     }
  200. }
  201.  
  202. /////////////////////////////////////////////////////////////////////////////
  203.  
  204. void COutputView::OnPrepareDC( CDC* pDC, CPrintInfo* pInfo )
  205. {
  206.     CScrollView::OnPrepareDC( pDC, pInfo );
  207.  
  208.     if( NULL != pInfo )
  209.     {
  210.         pInfo->m_bContinuePrinting =
  211.             ( (int) pInfo->m_nCurPage <= 
  212.               GetDocument()->GetMaxLines() / m_nPrintLinesPerPage + 1 );
  213.     }
  214. }
  215.  
  216. /////////////////////////////////////////////////////////////////////////////
  217. // COutputView: drawing stuff
  218. /////////////////////////////////////////////////////////////////////////////
  219.  
  220. void COutputView::OnDraw( CDC* pDC )
  221. {
  222.     //-----------------------------------------------------------------------
  223.     // prepare for drawing
  224.     //-----------------------------------------------------------------------
  225.     
  226.     HideCaret();
  227.  
  228.     pDC->SelectObject( *ColoredFontGet() );
  229.     pDC->SetTextColor( *ColoredFontGet() );
  230.  
  231.     //-----------------------------------------------------------------------
  232.     // draw only neccessary lines of document
  233.     //-----------------------------------------------------------------------
  234.     
  235.     int nFirstLine;
  236.     int nLastLine;
  237.     
  238.     CRect rectClip;
  239.     pDC->GetClipBox( &rectClip );
  240.     
  241.     RectToRange( rectClip, nFirstLine, nLastLine );
  242.  
  243.     int y = m_nRowHeight * nFirstLine;
  244.     
  245.     for( int nLine = nFirstLine
  246.          ; 
  247.          nLine <= nLastLine
  248.          ; 
  249.          nLine++, y+= m_nRowHeight )
  250.     {
  251.         OnDrawLine( pDC, nLine, y, FALSE );
  252.     }
  253.  
  254.     ShowCaret();
  255. }
  256.  
  257. /////////////////////////////////////////////////////////////////////////////
  258.  
  259. void COutputView::OnDrawLine( CDC* pDC, int nLine, int y, BOOL bSelected )
  260. {
  261.     //-----------------------------------------------------------------------
  262.     // draw neccessary lines of document
  263.     //-----------------------------------------------------------------------
  264.     
  265.     COutputDoc* pDoc = GetDocument();
  266.     COutputLine& sLine = pDoc->GetLine( nLine );
  267.  
  268.     if( "$LINE" == sLine )
  269.     {
  270.         y += m_nRowHeight / 2;
  271.  
  272.         pDC->MoveTo( 0, y );
  273.         pDC->LineTo( 10000, y );
  274.     }
  275.     else
  276.     {
  277.         int nStartCol, nEndCol;
  278.         GetSelForRow( nLine, nStartCol, nEndCol );
  279.         if( ENDOFLINE == nEndCol )
  280.         {
  281.             nEndCol = sLine.GetLength();
  282.         }
  283.  
  284.         LPCSTR lpszLine = (LPCSTR) sLine;
  285.  
  286.         COLORREF rgbNormalTextColor = pDC->GetTextColor();
  287.         COLORREF rgbNormalBkColor = pDC->GetBkColor();
  288.         
  289.         CSize sizeLeft =
  290.             pDC->TabbedTextOut( 0,
  291.                                 y,
  292.                                 lpszLine,
  293.                                 nStartCol,
  294.                                 sLine.GetFormat().GetTabStops(),
  295.                                 (int*) sLine.GetFormat().GetTabStopPositionsPixel( *pDC ),
  296.                                 0 );
  297.  
  298.         pDC->SetTextColor( rgbNormalBkColor );
  299.         pDC->SetBkColor( rgbNormalTextColor );
  300.  
  301.         CSize sizeMid = 
  302.             pDC->TabbedTextOut( sizeLeft.cx,
  303.                                 y,
  304.                                 lpszLine + nStartCol,
  305.                                 nEndCol - nStartCol,
  306.                                 sLine.GetFormat().GetTabStops(),
  307.                                 (int*) sLine.GetFormat().GetTabStopPositionsPixel( *pDC ),
  308.                                 0 );
  309.  
  310.         pDC->SetTextColor( rgbNormalTextColor );
  311.         pDC->SetBkColor( rgbNormalBkColor );
  312.  
  313.         CSize sizeRight = 
  314.             pDC->TabbedTextOut( sizeLeft.cx + sizeMid.cx,
  315.                                 y,
  316.                                 lpszLine + nEndCol,
  317.                                 sLine.GetLength() - nEndCol,
  318.                                 sLine.GetFormat().GetTabStops(),
  319.                                 (int*) sLine.GetFormat().GetTabStopPositionsPixel( *pDC ),
  320.                                 0 );
  321.     }
  322. }
  323.  
  324. /////////////////////////////////////////////////////////////////////////////
  325.  
  326. void COutputView::OnSize( UINT nType, int cx, int cy )
  327. {
  328.     CScrollView::OnSize( nType, cx, cy );
  329.     
  330.     UpdateScrollSizes();    
  331. }
  332.  
  333. /////////////////////////////////////////////////////////////////////////////
  334.  
  335. void COutputView::UpdateScrollSizes()
  336. {
  337.     //-----------------------------------------------------------------------
  338.     // UpdateScrollSizes() is called when it is necessary to adjust the
  339.     // scrolling range or page/line sizes.  There are two occassions
  340.     // where this is necessary:  (1) when a new row is added-- see
  341.     // OnUpdate()-- and (2) when the window size changes-- see OnSize().
  342.     //-----------------------------------------------------------------------
  343.  
  344.     CRect rectClient;
  345.     GetClientRect( &rectClient );
  346.  
  347.     CClientDC dc( this );
  348.     dc.SelectObject( *ColoredFontGet() );
  349.                 
  350.        TEXTMETRIC tm;
  351.     dc.GetTextMetrics( &tm );
  352.     m_nRowHeight = tm.tmHeight;
  353.  
  354.     //-----------------------------------------------------------------------
  355.     // The vert scrolling range is the total display height of all the rows
  356.     // the horz scrolling range is the width of a row
  357.     //-----------------------------------------------------------------------
  358.     
  359.     CSize sizeTotal( m_nRowWidth + rectClient.right, 
  360.                      m_nRowHeight * GetDocument()->GetMaxLines() );
  361.  
  362.     //-----------------------------------------------------------------------
  363.     // The vertical per-page scrolling distance is equal to the
  364.     // how many rows can be displayed in the current window, less
  365.     // one row for paging overlap.
  366.     //-----------------------------------------------------------------------
  367.     
  368.     m_nMaxVisibleLines = rectClient.bottom / m_nRowHeight;
  369.     
  370.     CSize sizePage( m_nRowWidth / 5,
  371.                     max( m_nRowHeight,
  372.                          m_nRowHeight * m_nMaxVisibleLines ) );
  373.  
  374.     //-----------------------------------------------------------------------
  375.     // The vertical per-line scrolling distance is equal to the
  376.     // height of the row.
  377.     //-----------------------------------------------------------------------
  378.  
  379.     CSize sizeLine( tm.tmMaxCharWidth, m_nRowHeight );
  380.  
  381.     SetScrollSizes( MM_TEXT, sizeTotal, sizePage, sizeLine );
  382. }
  383.  
  384. /////////////////////////////////////////////////////////////////////////////
  385.  
  386. void COutputView::RectToRange( const CRect& rect, int& nFirst, int& nLast )
  387. {
  388.     nFirst = rect.top / m_nRowHeight;
  389.     
  390.     nLast = min( nFirst + rect.Height() / m_nRowHeight + 1,
  391.                  GetDocument()->GetMaxLines() - 1 );
  392. }
  393.  
  394. /////////////////////////////////////////////////////////////////////////////
  395. // COutputView: printing stuff
  396. /////////////////////////////////////////////////////////////////////////////
  397.  
  398. BOOL COutputView::OnPreparePrinting( CPrintInfo* pInfo )
  399. {
  400.     return( DoPreparePrinting( pInfo ) );
  401. }
  402.  
  403. /////////////////////////////////////////////////////////////////////////////
  404.  
  405. void COutputView::OnBeginPrinting( CDC* pDC, CPrintInfo* pInfo )
  406. {
  407.     if( NULL != m_hPrinterFont )
  408.     {
  409.         ::DeleteObject( m_hPrinterFont );
  410.         m_hPrinterFont = NULL;
  411.     }
  412.  
  413.     //-----------------------------------------------------------------------    
  414.     // get display font...
  415.     //-----------------------------------------------------------------------    
  416.     
  417.     CFont* pFont = *ColoredFontGet();
  418.  
  419.     LOGFONT lf;
  420.     pFont->GetObject( sizeof( LOGFONT ), &lf );
  421.  
  422.     //-----------------------------------------------------------------------    
  423.     // ...map to printer font metrics...
  424.     //-----------------------------------------------------------------------    
  425.     
  426.     HDC hDCFrom = ::GetDC( NULL );
  427.     
  428.     lf.lfHeight = ::MulDiv( lf.lfHeight, 
  429.                               pDC->GetDeviceCaps( LOGPIXELSY ),
  430.                               ::GetDeviceCaps( hDCFrom, LOGPIXELSY ) );
  431.     
  432.     lf.lfWidth = 0;
  433. /***              
  434.     lf.lfWidth = ::MulDiv( lf.lfWidth, 
  435.                            pDC->GetDeviceCaps( LOGPIXELSX ),
  436.                            ::GetDeviceCaps( hDCFrom, LOGPIXELSX ) );
  437. ***/
  438.  
  439.     ::ReleaseDC( NULL, hDCFrom );
  440.  
  441.     //-----------------------------------------------------------------------    
  442.     // ...and create font for printing
  443.     //-----------------------------------------------------------------------    
  444.     
  445.     m_hPrinterFont = ::CreateFontIndirect( &lf );
  446.  
  447.     //-----------------------------------------------------------------------    
  448.     // ...and create font for printing
  449.     //-----------------------------------------------------------------------    
  450.     
  451.     pDC->SetMapMode( MM_TEXT );
  452.     pDC->SelectObject( CFont::FromHandle( m_hPrinterFont ) );
  453.     
  454.     TEXTMETRIC tm;
  455.     pDC->GetTextMetrics( &tm );
  456.     
  457.     int nVertRes = pDC->GetDeviceCaps( VERTRES );
  458.     
  459.     m_nPrintRowHeight = tm.tmHeight + tm.tmExternalLeading;
  460.     m_nPrintLinesPerPage = pDC->GetDeviceCaps( VERTRES ) / m_nPrintRowHeight;
  461. }
  462.  
  463. /////////////////////////////////////////////////////////////////////////////
  464.  
  465. void COutputView::OnEndPrinting( CDC*, CPrintInfo* )
  466. {
  467.     if( NULL != m_hPrinterFont  )
  468.     {
  469.         ::DeleteObject( m_hPrinterFont );
  470.         m_hPrinterFont = NULL;
  471.     }
  472.  
  473.     m_nPrintRowHeight = 0;
  474.     m_nPrintLinesPerPage = 0;
  475. }
  476.  
  477. /////////////////////////////////////////////////////////////////////////////
  478.  
  479. void COutputView::OnPrint( CDC* pDC, CPrintInfo* pInfo )
  480. {
  481.     CFont* pOldFont = pDC->SelectObject( CFont::FromHandle( m_hPrinterFont ) );
  482.     pDC->SetBkMode( TRANSPARENT );
  483.  
  484.     int y = 0;
  485.  
  486.     int nPageStartRow = ( pInfo->m_nCurPage - 1 ) * m_nPrintLinesPerPage;
  487.     int nPageMaxEndRow = min( GetDocument()->GetMaxLines(),
  488.                               nPageStartRow + m_nPrintLinesPerPage );
  489.                               
  490.     for( int nLine = nPageStartRow; nLine < nPageMaxEndRow; nLine++ )
  491.     {
  492.         OnDrawLine( pDC, nLine, y, FALSE );
  493.         y+= m_nPrintRowHeight;
  494.     }
  495.     
  496.     pDC->SelectObject( pOldFont );
  497. }
  498.  
  499. /////////////////////////////////////////////////////////////////////////////
  500.  
  501. void COutputView::OnViewFont() 
  502. {
  503.     if( ColoredFontGet()->ChooseColoredFont() )
  504.     {
  505.         InvalidateRect( NULL );
  506.         UpdateScrollSizes();
  507.     }
  508. }
  509.  
  510. /////////////////////////////////////////////////////////////////////////////
  511. // COutputView: caret and cursor stuff
  512. /////////////////////////////////////////////////////////////////////////////
  513.  
  514. BOOL COutputView::OnSetCursor( CWnd* pWnd, UINT nHitTest, UINT message )
  515. {
  516.     if( HTCLIENT == nHitTest )
  517.     {
  518.         ::SetCursor( ::LoadCursor( NULL, MAKEINTRESOURCE( IDC_IBEAM ) ) );
  519.         return( TRUE );
  520.     }
  521.  
  522.     return( CScrollView::OnSetCursor( pWnd, nHitTest, message ) );
  523. }
  524.  
  525. /////////////////////////////////////////////////////////////////////////////
  526.  
  527. void COutputView::OnSetFocus(CWnd* pOldWnd) 
  528. {
  529.     CScrollView::OnSetFocus(pOldWnd);
  530.  
  531. /******
  532.     // we must invalidate active view - otherwise Ctrl-F6 doesn't work
  533.     // after we have activated the output view in Split Mode
  534.  
  535.     CMainFrame* pFrame = (CMainFrame*) AfxGetMainWnd();
  536.     ASSERT( NULL != pFrame );
  537.  
  538.     pFrame->SetActiveView( NULL, FALSE );
  539.     pFrame->OnUpdateFrameMenu( GetDocument()->GetDefaultMenu() );
  540. **********/    
  541.     // caret stuff
  542.     
  543.     ::CreateCaret( m_hWnd, (HBITMAP) NULL, CARET_WIDTH, CARET_HEIGHT ); 
  544.     ShowCaret();
  545.     MoveCaretToCurPos();
  546. }
  547.  
  548. /////////////////////////////////////////////////////////////////////////////
  549.  
  550. void COutputView::OnKillFocus(CWnd* pNewWnd) 
  551. {
  552.     CScrollView::OnKillFocus(pNewWnd);
  553.     
  554.     ::DestroyCaret();
  555.  
  556.     CMainFrame* pFrame = (CMainFrame*) AfxGetMainWnd();
  557.     ASSERT( NULL != pFrame );
  558.     pFrame->OnUpdateFrameMenu( NULL );
  559. }
  560.  
  561. /////////////////////////////////////////////////////////////////////////////
  562.  
  563. void COutputView::OnLButtonDown(UINT nFlags, CPoint point) 
  564. {
  565.     CScrollView::OnLButtonDown( nFlags, point );
  566.  
  567.     BOOL bMoveCaret = TRUE;
  568.     BOOL bClearSelection = !( GetAsyncKeyState( VK_SHIFT ) < 0 );
  569.     
  570.     SetCapture();
  571.     SetCurPos( point, bMoveCaret, bClearSelection );
  572. }
  573.  
  574. /////////////////////////////////////////////////////////////////////////////
  575.  
  576. void COutputView::OnLButtonUp(UINT nFlags, CPoint point) 
  577. {
  578.     CScrollView::OnLButtonUp(nFlags, point);
  579.  
  580.     SetCurPos( point, TRUE, FALSE );
  581.     ReleaseCapture();
  582. }
  583.  
  584. /////////////////////////////////////////////////////////////////////////////
  585.  
  586. void COutputView::OnRButtonUp(UINT nFlags, CPoint point) 
  587. {
  588.     CScrollView::OnRButtonUp(nFlags, point);
  589.  
  590.     MapWindowPoints( NULL, &point, 1 );
  591.  
  592.     CMenu* pTrackPopup = m_pTrackMenu->GetSubMenu( 0 );
  593.  
  594.     if( NULL != pTrackPopup )
  595.     {
  596.         pTrackPopup->TrackPopupMenu( TPM_LEFTALIGN | TPM_LEFTBUTTON, 
  597.                                      point.x,
  598.                                      point.y,
  599.                                      this );
  600.     }
  601. }
  602.  
  603. /////////////////////////////////////////////////////////////////////////////
  604.  
  605. void COutputView::OnMouseMove(UINT nFlags, CPoint point) 
  606. {
  607.     CScrollView::OnMouseMove(nFlags, point);
  608.  
  609.     if( !( MK_LBUTTON & nFlags ) )
  610.     {
  611.         return;
  612.     }
  613.  
  614.     // point is restricted to ClientRect
  615.  
  616.     CRect rectClient;
  617.     GetClientRect( rectClient );
  618.  
  619.     point.x = max( min( point.x, rectClient.right ), rectClient.left );
  620.     point.y = max( min( point.y, rectClient.bottom ), rectClient.top );
  621.  
  622.     // set caret - and do scrolling if neccessary..
  623.         
  624.     SetCurPos( point, TRUE, FALSE );
  625. }
  626.  
  627. /////////////////////////////////////////////////////////////////////////////
  628.  
  629. void COutputView::SetCapture()
  630. {
  631.     CScrollView::SetCapture();
  632.  
  633.     m_nIDCaptureTimer = SetTimer( CAPTURE_TIMER, CAPTURE_TIMER_TIMEOUT, NULL );
  634. }
  635.  
  636. void COutputView::ReleaseCapture()
  637. {
  638.     KillTimer( m_nIDCaptureTimer );
  639.     ::ReleaseCapture();
  640. }
  641.  
  642. void COutputView::OnTimer(UINT nIDEvent) 
  643. {
  644.     CScrollView::OnTimer(nIDEvent);
  645.  
  646.     // simulate a mouse move...
  647.  
  648.     CPoint point;
  649.     GetCursorPos( &point );
  650.     ScreenToClient( &point );
  651.  
  652.     UINT nFlags = 0;
  653.  
  654.     if( GetAsyncKeyState( VK_CONTROL ) < 0 )
  655.     {
  656.         nFlags |= MK_CONTROL;
  657.     }
  658.     if( GetAsyncKeyState( VK_LBUTTON ) < 0 )
  659.     {
  660.         nFlags |= MK_LBUTTON;
  661.     }
  662.     if( GetAsyncKeyState( VK_MBUTTON ) < 0 )
  663.     {
  664.         nFlags |= MK_MBUTTON;
  665.     }
  666.     if( GetAsyncKeyState( VK_RBUTTON ) < 0 )
  667.     {
  668.         nFlags |= MK_RBUTTON;
  669.     }
  670.     if( GetAsyncKeyState( VK_SHIFT ) < 0 )
  671.     {
  672.         nFlags |= MK_SHIFT;
  673.     }
  674.  
  675.     OnMouseMove( nFlags, point );
  676. }
  677.  
  678. /////////////////////////////////////////////////////////////////////////////
  679.  
  680. void COutputView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) 
  681. {
  682.     CScrollView::OnKeyDown(nChar, nRepCnt, nFlags);
  683.  
  684.     BOOL bMoveCaret = TRUE;
  685.     BOOL bClearSelection = !( GetAsyncKeyState( VK_SHIFT ) < 0 );
  686.  
  687.     switch( nChar )
  688.     {
  689.         case VK_HOME:
  690.             if( GetAsyncKeyState( VK_CONTROL ) < 0 )
  691.             {
  692.                 SetCurPos( 0, 0, bMoveCaret, bClearSelection );
  693.             }
  694.             else
  695.             {
  696.                 SetCurPos( 0, CURRENT_VALUE, bMoveCaret, bClearSelection );
  697.             }
  698.             break; 
  699.  
  700.         case VK_END:
  701.             if( GetAsyncKeyState( VK_CONTROL ) < 0 )
  702.             {
  703.                 SetCurPos( ENDOFLINE, ENDOFLINES, bMoveCaret, bClearSelection );
  704.             }
  705.             else
  706.             {
  707.                 SetCurPos( ENDOFLINE, CURRENT_VALUE, bMoveCaret, bClearSelection );
  708.             }
  709.             break; 
  710.  
  711.         case VK_PRIOR:
  712.         {
  713.             CPoint pt = GetCaretPos();
  714.             pt.y -= ( ( m_nMaxVisibleLines - 1 ) * m_nRowHeight );
  715.             SetCurPos( pt, bMoveCaret, bClearSelection );
  716.             break; 
  717.         }    
  718.         case VK_NEXT:
  719.         {
  720.             CPoint pt = GetCaretPos();
  721.             pt.y += ( ( m_nMaxVisibleLines - 1 ) * m_nRowHeight );
  722.             SetCurPos( pt, bMoveCaret, bClearSelection );
  723.             break; 
  724.         }    
  725.         case VK_LEFT:
  726.             SetCurPos( GetCurCol() - 1, CURRENT_VALUE, bMoveCaret, bClearSelection );
  727.             break; 
  728.  
  729.         case VK_RIGHT:
  730.             SetCurPos( GetCurCol() + 1, CURRENT_VALUE, bMoveCaret, bClearSelection );
  731.             break; 
  732.  
  733.         case VK_UP:
  734.         {
  735.             CPoint pt = GetCaretPos();
  736.             pt.y -= m_nRowHeight;
  737.             SetCurPos( pt, bMoveCaret, bClearSelection );
  738.             break; 
  739.         }
  740.         case VK_DOWN:
  741.         {
  742.             CPoint pt = GetCaretPos();
  743.             pt.y += m_nRowHeight;
  744.             SetCurPos( pt, bMoveCaret, bClearSelection );
  745.             break; 
  746.         }
  747.     }
  748. }
  749.  
  750. /////////////////////////////////////////////////////////////////////////////
  751.  
  752. CPoint COutputView::VirtCharPosFromCoords( int nCol, int nRow )
  753. {
  754.     CClientDC dc( this );
  755.     dc.SelectObject( *ColoredFontGet() );
  756.  
  757.     COutputLine& sLine = GetDocument()->GetLine( nRow );
  758.  
  759.     if( nCol > sLine.GetLength() )
  760.     {
  761.         nCol = sLine.GetLength();
  762.     }
  763.     
  764.     CSize size = dc.GetTabbedTextExtent( (const char*) sLine, 
  765.                                          nCol, 
  766.                                          sLine.GetFormat().GetTabStops(), 
  767.                                          (int*) sLine.GetFormat().GetTabStopPositionsPixel( dc ) );
  768.  
  769.     return( CPoint( size.cx, nRow * m_nRowHeight ) );
  770. }
  771.  
  772. /////////////////////////////////////////////////////////////////////////////
  773.  
  774. void COutputView::CharCoordsFromVirtPoint( CPoint pt, int& nCol, int& nRow )
  775. {
  776.     nCol = 0;
  777.     nRow = min( pt.y / m_nRowHeight, GetDocument()->GetMaxLines() - 1 );
  778.     nRow = max( nRow, 0 );
  779.  
  780.     COutputLine& sLine = GetDocument()->GetLine( nRow );
  781.  
  782.     CClientDC dc( this );
  783.     dc.SelectObject( *ColoredFontGet() );
  784.  
  785.     while( nCol < sLine.GetLength() )
  786.     {
  787.         CSize size = dc.GetTabbedTextExtent( (const char*) sLine, 
  788.                                              nCol + 1,
  789.                                              sLine.GetFormat().GetTabStops(), 
  790.                                              (int*) sLine.GetFormat().GetTabStopPositionsPixel( dc ) );
  791.  
  792.         if( size.cx > pt.x ) 
  793.         {
  794.             break;
  795.         }
  796.  
  797.         nCol++;
  798.     }
  799. }
  800.  
  801. /////////////////////////////////////////////////////////////////////////////
  802.  
  803. void COutputView::SetCurPos( int nCol, int nRow, BOOL bMoveCaret, BOOL bClearSelection )
  804. {
  805.     // convienince values
  806.  
  807.     if( CURRENT_VALUE == nCol )
  808.     {
  809.         nCol = m_nCurCol;
  810.     }
  811.  
  812.     if( CURRENT_VALUE == nRow )
  813.     {
  814.         nRow = m_nCurRow;
  815.     }
  816.  
  817.     // check and correct position values
  818.  
  819.     nRow = min( nRow, GetDocument()->GetMaxLines() - 1 );
  820.     nRow = max( nRow, 0 );
  821.  
  822.     COutputLine& sLine = GetDocument()->GetLine( nRow );
  823.  
  824.     nCol = min( nCol, sLine.GetLength() );
  825.     nCol = max( nCol, 0 );
  826.  
  827.     // check for selection
  828.  
  829.     if( bClearSelection )
  830.     {
  831.         if( m_bWhileSelecting )
  832.         {
  833.             InvalidateSelRange();
  834.             m_bWhileSelecting = FALSE;
  835.         }
  836.  
  837.         m_nSelCol = nCol;
  838.         m_nSelRow = nRow;
  839.     }
  840.     else
  841.     {
  842.         m_bWhileSelecting = TRUE;
  843.         InvalidateNewRange( nCol, nRow );
  844.     }
  845.  
  846.     // now remember position
  847.  
  848.     m_nCurCol = nCol;
  849.     m_nCurRow = nRow;
  850.  
  851.     // move the caret if neccessary
  852.  
  853.     if( bMoveCaret )
  854.     {
  855.         MoveCaretToCurPos();
  856.     }
  857. }
  858.  
  859. /////////////////////////////////////////////////////////////////////////////
  860.  
  861. void COutputView::SetCurPos( CPoint pt, BOOL bMoveCaret, BOOL bClearSelection )
  862. {
  863.     pt.x += GetDeviceScrollPosition().x;
  864.     pt.y += GetDeviceScrollPosition().y;
  865.  
  866.     int nCol;
  867.     int nRow;
  868.  
  869.     CharCoordsFromVirtPoint( pt, nCol, nRow );
  870.  
  871.     SetCurPos( nCol, nRow, bMoveCaret, bClearSelection );
  872. }
  873.  
  874. /////////////////////////////////////////////////////////////////////////////
  875.  
  876. void COutputView::MoveCaretToCurPos()
  877. {
  878.     HideCaret();
  879.     CPoint ptCaret = GetCaretPos();
  880.     InvalidateRect( CRect( ptCaret, CSize( CARET_WIDTH, CARET_HEIGHT ) ) );
  881.     
  882.     CPoint pt = VirtCharPosFromCoords( m_nCurCol, m_nCurRow );
  883.     AdjustScrollToVirtPoint( pt );
  884.  
  885.     pt.x -= GetDeviceScrollPosition().x;
  886.     pt.y -= GetDeviceScrollPosition().y;
  887.     
  888.     SetCaretPos( pt );
  889.  
  890.     ShowCaret();
  891. }
  892.  
  893. /////////////////////////////////////////////////////////////////////////////
  894.  
  895. CString COutputView::GetCurRowAsString()
  896. {
  897.     return( GetDocument()->GetLine( m_nCurRow ) );
  898. }
  899.  
  900. /////////////////////////////////////////////////////////////////////////////
  901.  
  902. BOOL COutputView::GetSelForRow( int nRow, int& nStartCol, int& nEndCol ) const
  903. {
  904.     nStartCol = 0;
  905.     nEndCol = 0;
  906.  
  907.     int nSelStartCol, nSelEndCol, nSelStartRow, nSelEndRow;
  908.     GetSelRange( nSelStartCol, nSelStartRow, nSelEndCol, nSelEndRow );
  909.  
  910.     if( ( nRow < nSelStartRow ) || ( nRow > nSelEndRow ) )
  911.     {
  912.         return( FALSE );
  913.     }
  914.  
  915.     if( nRow == nSelStartRow )
  916.     {
  917.         nStartCol = nSelStartCol;
  918.     }
  919.  
  920.     if( nRow == nSelEndRow )
  921.     {
  922.         nEndCol = nSelEndCol;
  923.     }
  924.     
  925.     if( nRow < nSelEndRow )
  926.     {
  927.         nEndCol = ENDOFLINE;
  928.     }
  929.  
  930.     return( TRUE );
  931. }
  932.  
  933. /////////////////////////////////////////////////////////////////////////////
  934.  
  935. void COutputView::InvalidateSelRange()
  936. {
  937.     int nStartCol, nStartRow, nEndCol, nEndRow;
  938.     GetSelRange( nStartCol, nStartRow, nEndCol, nEndRow );
  939.  
  940.     InvalidateRange( nStartCol, nStartRow, nEndCol, nEndRow );
  941. }
  942.  
  943. void COutputView::InvalidateNewRange( int nCol, int nRow )
  944. {
  945.     int nStartCol, nStartRow, nEndCol, nEndRow;
  946.  
  947.     if( m_nCurRow < nRow )
  948.     {
  949.         nStartRow = m_nCurRow;
  950.         nStartCol = m_nCurCol;
  951.  
  952.         nEndRow = nRow;
  953.         nEndCol = nCol;
  954.     }
  955.     else if( m_nCurRow > nRow )
  956.     {
  957.         nStartRow = nRow;
  958.         nStartCol = nCol;
  959.  
  960.         nEndRow = m_nCurRow;
  961.         nEndCol = m_nCurCol;
  962.     }
  963.     else
  964.     {
  965.         nStartRow = nRow;
  966.         nStartCol = min( m_nCurCol, nCol );
  967.  
  968.         nEndRow = m_nCurRow;
  969.         nEndCol = max( m_nCurCol, nCol );
  970.     }
  971.  
  972.     InvalidateRange( nStartCol, nStartRow, nEndCol, nEndRow );
  973. }
  974.  
  975. void COutputView::InvalidateRange( int nStartCol, int nStartRow, int nEndCol, int nEndRow )
  976. {
  977.     if( !::IsWindow( m_hWnd ) )
  978.     {
  979.         return;
  980.     }
  981.  
  982.     CPoint ptScroll = GetDeviceScrollPosition();
  983.     
  984.     CPoint ptStart = VirtCharPosFromCoords( nStartCol, nStartRow );
  985.     ptStart.x -= ptScroll.x;
  986.     ptStart.y -= ptScroll.y;
  987.  
  988.     CPoint ptEnd = VirtCharPosFromCoords( nEndCol, nEndRow );
  989.     ptEnd.x -= ptScroll.x;
  990.     ptEnd.y -= ptScroll.y;
  991.  
  992.     CRect rect;
  993.     rect.top = ptStart.y;
  994.     rect.bottom = ptEnd.y + m_nRowHeight;
  995.  
  996.     if( nStartRow == nEndRow )
  997.     {
  998.         rect.left = ptStart.x;
  999.         rect.right = ptEnd.x;
  1000.     }
  1001.     else
  1002.     {
  1003.         CRect rectClient;
  1004.         GetClientRect( rectClient );
  1005.  
  1006.         rect.left = 0;
  1007.         rect.right = rectClient.Width();
  1008.     }
  1009.     
  1010.     InvalidateRect( rect, FALSE );
  1011. }
  1012.     
  1013. /////////////////////////////////////////////////////////////////////////////
  1014.  
  1015. BOOL COutputView::GetSelRange( int& nSelStartCol, int& nSelStartRow, int& nSelEndCol, int& nSelEndRow ) const
  1016. {
  1017.     if( m_nCurRow < m_nSelRow )
  1018.     {
  1019.         nSelStartRow = m_nCurRow;
  1020.         nSelStartCol = m_nCurCol;
  1021.  
  1022.         nSelEndRow = m_nSelRow;
  1023.         nSelEndCol = m_nSelCol;
  1024.     }
  1025.     else if( m_nCurRow > m_nSelRow )
  1026.     {
  1027.         nSelStartRow = m_nSelRow;
  1028.         nSelStartCol = m_nSelCol;
  1029.  
  1030.         nSelEndRow = m_nCurRow;
  1031.         nSelEndCol = m_nCurCol;
  1032.     }
  1033.     else
  1034.     {
  1035.         nSelStartRow = m_nSelRow;
  1036.         nSelStartCol = min( m_nCurCol, m_nSelCol );
  1037.  
  1038.         nSelEndRow = m_nCurRow;
  1039.         nSelEndCol = max( m_nCurCol, m_nSelCol );
  1040.     }
  1041.  
  1042.     return( ( nSelStartCol != nSelEndRow ) || ( nSelStartCol != nSelEndCol ) );
  1043. }
  1044.  
  1045. /////////////////////////////////////////////////////////////////////////////
  1046.  
  1047. void COutputView::GetSelectedText( CString& strResult )
  1048. {
  1049.     int nSelStartCol, nSelEndCol, nSelStartRow, nSelEndRow;
  1050.     GetSelRange( nSelStartCol, nSelStartRow, nSelEndCol, nSelEndRow );
  1051.  
  1052.     if( nSelStartRow == nSelEndRow )
  1053.     {
  1054.         strResult = GetDocument()->GetLine( nSelStartRow ).Mid( nSelStartCol, nSelEndCol - nSelStartCol );
  1055.     }
  1056.     else
  1057.     {
  1058.         strResult = GetDocument()->GetLine( nSelStartRow ).Mid( nSelStartCol );
  1059.  
  1060.         for( int nRow = nSelStartRow + 1; nRow < nSelEndRow; nRow++ )
  1061.         {
  1062.             strResult += CString( "\r\n" );
  1063.             strResult += GetDocument()->GetLine( nRow );
  1064.         }
  1065.  
  1066.         strResult += CString( "\r\n" );
  1067.         strResult += GetDocument()->GetLine( nSelEndRow ).Left( nSelEndCol );
  1068.     }
  1069. }
  1070.  
  1071. /////////////////////////////////////////////////////////////////////////////
  1072.  
  1073. void COutputView::AdjustScrollToVirtPoint( CPoint ptVirt )
  1074. {
  1075.     CPoint ptScroll = GetDeviceScrollPosition();
  1076.     CPoint ptCaret = ptVirt - ptScroll;
  1077.     CRect rectCaret( ptCaret, CSize( CARET_WIDTH, CARET_HEIGHT ) );
  1078.  
  1079.     CRect rectClient;
  1080.     GetClientRect( rectClient );
  1081.  
  1082.     // rectCaret fully contained in rectClient ??
  1083.     
  1084.     CRect rectIntersect;
  1085.     rectIntersect.IntersectRect( rectClient, rectCaret );
  1086.  
  1087.     if( rectCaret == rectIntersect )
  1088.     {
  1089.         return;
  1090.     }
  1091.  
  1092.     int nMapMode;
  1093.     CSize sizeTotal, sizePage, sizeLine;
  1094.  
  1095.     GetDeviceScrollSizes( nMapMode, sizeTotal, sizePage, sizeLine );
  1096.     //sizePage.cx -= sizeLine.cx;
  1097.     //sizePage.cy -= sizeLine.cy;
  1098.     
  1099.     // maybe scroll a char to the left
  1100.  
  1101.     if( ( rectCaret.left < rectClient.left ) && ( rectCaret.left >= rectClient.left - sizeLine.cx ) &&
  1102.         ( rectCaret.top >= rectClient.top ) && ( rectCaret.bottom <= rectClient.bottom ) )
  1103.     {
  1104.         ptScroll.x -= sizeLine.cx;
  1105.     }
  1106.  
  1107.     // maybe scroll a char to the right
  1108.  
  1109.     else if( ( rectCaret.right > rectClient.right ) && ( rectCaret.right <= rectClient.right + sizeLine.cx ) &&
  1110.              ( rectCaret.top >= rectClient.top ) && ( rectCaret.bottom <= rectClient.bottom ) )
  1111.     {
  1112.         ptScroll.x += sizeLine.cx;
  1113.     }
  1114.  
  1115.     // maybe scroll a page to the left
  1116.  
  1117.     else if( ( rectCaret.left < rectClient.left ) && ( rectCaret.left > rectClient.left - sizePage.cx ) &&
  1118.              ( rectCaret.top >= rectClient.top ) && ( rectCaret.bottom <= rectClient.bottom ) )
  1119.  
  1120.     {
  1121.         ptScroll.x -= sizePage.cx;
  1122.     }
  1123.  
  1124.     // maybe scroll a page to the right
  1125.  
  1126.     else if( ( rectCaret.right > rectClient.right ) && ( rectCaret.right < rectClient.right + sizePage.cx ) &&
  1127.              ( rectCaret.top >= rectClient.top ) && ( rectCaret.bottom <= rectClient.bottom ) )
  1128.  
  1129.     {
  1130.         ptScroll.x += sizePage.cx;
  1131.     }
  1132.  
  1133.     // maybe scroll a line up
  1134.         
  1135.     else if( ( rectCaret.top < rectClient.top ) && ( rectCaret.top >= rectClient.top - sizeLine.cy ) &&
  1136.              ( rectCaret.left >= rectClient.left ) && ( rectCaret.right <= rectClient.right ) )
  1137.  
  1138.     {
  1139.         ptScroll.y -= sizeLine.cy;
  1140.     }
  1141.  
  1142.     // maybe scroll a line down
  1143.         
  1144.     else if( ( rectCaret.bottom > rectClient.bottom ) && ( rectCaret.bottom <= rectClient.bottom + sizeLine.cy ) &&
  1145.              ( rectCaret.left >= rectClient.left ) && ( rectCaret.right <= rectClient.right ) )
  1146.     {
  1147.         ptScroll.y += sizeLine.cy;
  1148.     }
  1149.  
  1150.     // maybe scroll a page up
  1151.  
  1152.     else if( ( rectCaret.top < rectClient.top ) && ( rectCaret.top > rectClient.top - sizePage.cy ) &&
  1153.              ( rectCaret.left >= rectClient.left ) && ( rectCaret.right <= rectClient.right ) )
  1154.     {
  1155.         ptScroll.y -= sizePage.cy;
  1156.     }
  1157.  
  1158.     // maybe scroll a page down
  1159.  
  1160.     else if( ( rectCaret.bottom > rectClient.bottom ) && ( rectCaret.bottom < rectClient.bottom + sizePage.cy ) &&
  1161.              ( rectCaret.left >= rectClient.left ) && ( rectCaret.right <= rectClient.right ) )
  1162.     {
  1163.         ptScroll.y += sizePage.cy;
  1164.     }
  1165.  
  1166.     // otherwise position direct
  1167.  
  1168.     else
  1169.     {
  1170.         ptScroll = ptVirt;
  1171.  
  1172.         // as far left as possible
  1173.  
  1174.         ptScroll.x -= ( rectClient.Width() - sizeLine.cx );
  1175.         ptScroll.x = max( 0, ptScroll.x );
  1176.     }
  1177.  
  1178.     ptScroll.x = max( 0, ptScroll.x );
  1179.     ptScroll.y = max( 0, ptScroll.y );
  1180.  
  1181.     ScrollToDevicePosition( ptScroll );
  1182. }
  1183.  
  1184. /////////////////////////////////////////////////////////////////////////////
  1185.  
  1186. void COutputView::OnEditCopy() 
  1187. {
  1188.     CString sSelText;
  1189.     GetSelectedText( sSelText );
  1190.  
  1191.     if( ::OpenClipboard( m_hWnd ) )
  1192.     {
  1193.         HGLOBAL hData = ::GlobalAlloc( GHND, sSelText.GetLength() + 1 );
  1194.         char* psz = (char*) ::GlobalLock( hData );
  1195.         ASSERT( NULL != psz );
  1196.         strcpy( psz, (const char*) sSelText );
  1197.         ::GlobalUnlock( hData );
  1198.         
  1199.         ::SetClipboardData( CF_TEXT, hData );
  1200.         ::CloseClipboard();
  1201.     }
  1202. }
  1203.  
  1204. /////////////////////////////////////////////////////////////////////////////
  1205.  
  1206. void COutputView::OnUpdateEditCopy(CCmdUI* pCmdUI) 
  1207. {
  1208.     int nSelStartCol, nSelEndCol, nSelStartRow, nSelEndRow;
  1209.     GetSelRange( nSelStartCol, nSelStartRow, nSelEndCol, nSelEndRow );
  1210.  
  1211.     pCmdUI->Enable( ( nSelStartRow != nSelEndRow ) || ( nSelStartCol != nSelEndCol ) );
  1212. }
  1213.