1 /*-*- c++ -*-******************************************************** 
   2  * wxLwindow.h : a scrolled Window for displaying/entering rich text* 
   4  * (C) 1998, 1999 by Karsten Ballüder (Ballueder@usa.net)           * 
   7  *******************************************************************/ 
   9 // ============================================================================ 
  11 // ============================================================================ 
  13 // ---------------------------------------------------------------------------- 
  15 // ---------------------------------------------------------------------------- 
  18 #   pragma implementation "wxlwindow.h" 
  21 #include <wx/wxprec.h> 
  32 #     include "gui/wxMenuDefs.h" 
  33 #     include "gui/wxMApp.h" 
  35 #   include "gui/wxlwindow.h" 
  36 #   include "gui/wxlparser.h" 
  39 #       include <wx/msw/private.h> 
  42 #   include "wxlwindow.h" 
  43 #   include "wxlparser.h" 
  46 #include <wx/clipbrd.h> 
  47 #include <wx/textctrl.h> 
  48 #include <wx/dataobj.h> 
  50 #ifdef WXLAYOUT_USE_CARET 
  51 #   include <wx/caret.h> 
  52 #endif // WXLAYOUT_USE_CARET 
  56 // ---------------------------------------------------------------------------- 
  58 // ---------------------------------------------------------------------------- 
  61 #  define   WXLO_DEBUG(x)      wxLogDebug x 
  63 #  define WXLO_DEBUG(x) 
  66 // ---------------------------------------------------------------------------- 
  68 // ---------------------------------------------------------------------------- 
  70 /// offsets to put a nice frame around text 
  71 #define WXLO_XOFFSET   4 
  72 #define WXLO_YOFFSET   4 
  74 /// offset to the right and bottom for when to redraw scrollbars 
  75 #define   WXLO_ROFFSET   20 
  76 #define   WXLO_BOFFSET   20 
  78 /// the size of one scrollbar page in pixels 
  79 static const int X_SCROLL_PAGE 
= 10; 
  80 static const int Y_SCROLL_PAGE 
= 20; 
  82 // ---------------------------------------------------------------------------- 
  84 // ---------------------------------------------------------------------------- 
  86 BEGIN_EVENT_TABLE(wxLayoutWindow
,wxScrolledWindow
) 
  87    EVT_SIZE    (wxLayoutWindow::OnSize
) 
  89    EVT_PAINT    (wxLayoutWindow::OnPaint
) 
  91    EVT_CHAR     (wxLayoutWindow::OnChar
) 
  92    EVT_KEY_UP   (wxLayoutWindow::OnKeyUp
) 
  94    EVT_LEFT_DOWN(wxLayoutWindow::OnLeftMouseDown
) 
  95    EVT_LEFT_UP(wxLayoutWindow::OnLeftMouseUp
) 
  96    EVT_RIGHT_DOWN(wxLayoutWindow::OnRightMouseClick
) 
  97    EVT_LEFT_DCLICK(wxLayoutWindow::OnMouseDblClick
) 
  98    EVT_MIDDLE_DOWN(wxLayoutWindow::OnMiddleMouseDown
) 
  99    EVT_MOTION    (wxLayoutWindow::OnMouseMove
) 
 101    EVT_UPDATE_UI(WXLOWIN_MENU_UNDERLINE
, wxLayoutWindow::OnUpdateMenuUnderline
) 
 102    EVT_UPDATE_UI(WXLOWIN_MENU_BOLD
, wxLayoutWindow::OnUpdateMenuBold
) 
 103    EVT_UPDATE_UI(WXLOWIN_MENU_ITALICS
, wxLayoutWindow::OnUpdateMenuItalic
) 
 104    EVT_MENU_RANGE(WXLOWIN_MENU_FIRST
, WXLOWIN_MENU_LAST
, wxLayoutWindow::OnMenu
) 
 106    EVT_SET_FOCUS(wxLayoutWindow::OnSetFocus
) 
 107    EVT_KILL_FOCUS(wxLayoutWindow::OnKillFocus
) 
 110 // ---------------------------------------------------------------------------- 
 111 // function prototypes 
 112 // ---------------------------------------------------------------------------- 
 114 /// returns TRUE if keyCode is one of arrows/home/end/page{up|down} keys 
 115 static bool IsDirectionKey(long keyCode
); 
 117 // ============================================================================ 
 119 // ============================================================================ 
 121 /* LEAVE IT HERE UNTIL WXGTK WORKS AGAIN!!! */ 
 123 /// allows me to compare to wxPoints 
 124 static bool operator != (wxPoint 
const &p1
, wxPoint 
const &p2
) 
 126    return p1
.x 
!= p2
.x 
|| p1
.y 
!= p2
.y
; 
 130 #ifndef wxWANTS_CHARS 
 131    #define wxWANTS_CHARS 0 
 134 // ---------------------------------------------------------------------------- 
 136 // ---------------------------------------------------------------------------- 
 138 wxLayoutWindow::wxLayoutWindow(wxWindow 
*parent
) 
 139               : wxScrolledWindow(parent
, -1, 
 140                                  wxDefaultPosition
, wxDefaultSize
, 
 141                                  wxHSCROLL 
| wxVSCROLL 
| 
 146    SetStatusBar(NULL
); // don't use statusbar 
 148    m_doSendEvents 
= false; 
 149    m_ViewStartX 
= 0; m_ViewStartY 
= 0; 
 150    m_DoPopupMenu 
= true; 
 151    m_PopupMenu 
= MakeFormatMenu(); 
 152    m_memDC 
= new wxMemoryDC
; 
 153    m_bitmap 
= new wxBitmap(4,4); 
 154    m_bitmapSize 
= wxPoint(4,4); 
 155    m_llist 
= new wxLayoutList(); 
 157    m_ScrollToCursor 
= false; 
 160    // no scrollbars initially 
 162    m_hasVScrollbar 
= false; 
 166 #ifdef WXLAYOUT_USE_CARET 
 167    // FIXME cursor size shouldn't be hardcoded 
 168    wxCaret 
*caret 
= new wxCaret(this, 2, 20); 
 170    m_llist
->SetCaret(caret
); 
 171 #endif // WXLAYOUT_USE_CARET 
 174    m_HandCursor 
= FALSE
; 
 175    m_CursorVisibility 
= -1; 
 176    SetCursor(wxCURSOR_IBEAM
); 
 179    // at least under Windows, this should be the default behaviour 
 181    m_AutoDeleteSelection 
= TRUE
; 
 183    m_AutoDeleteSelection 
= FALSE
; 
 187 wxLayoutWindow::~wxLayoutWindow() 
 189    delete m_memDC
; // deletes bitmap automatically (?) 
 193    SetBackgroundBitmap(NULL
); 
 197 wxLayoutWindow::Clear(int family
, 
 205    GetLayoutList()->Clear(family
,size
,style
,weight
,underline
,fg
,bg
); 
 206    SetBackgroundColour(GetLayoutList()->GetDefaultStyleInfo().GetBGColour()); 
 207    wxScrolledWindow::Clear(); 
 208    ResizeScrollbars(true); 
 212 #ifdef WXLAYOUT_USE_CARET 
 213    if ( m_CursorVisibility 
== 1 ) 
 215 #endif // WXLAYOUT_USE_CARET 
 217    DoPaint((wxRect 
*)NULL
); 
 220 void wxLayoutWindow::Refresh(bool eraseBackground
, const wxRect 
*rect
) 
 222    wxScrolledWindow::Refresh(eraseBackground
, rect
); 
 229 wxLayoutWindow::OnMouse(int eventId
, wxMouseEvent
& event
) 
 231    wxClientDC 
dc( this ); 
 233    if ( eventId 
!= WXLOWIN_MENU_MOUSEMOVE 
) 
 235       // moving the mouse in a window shouldn't give it the focus! 
 236       // Oh yes! wxGTK's focus handling is so broken, that this is the  
 237       // only sensible way to go. 
 242    findPos
.x 
= dc
.DeviceToLogicalX(event
.GetX()); 
 243    findPos
.y 
= dc
.DeviceToLogicalY(event
.GetY()); 
 245    findPos
.x 
-= WXLO_XOFFSET
; 
 246    findPos
.y 
-= WXLO_YOFFSET
; 
 253    m_ClickPosition 
= wxPoint(event
.GetX(), event
.GetY()); 
 257    wxLayoutObject 
*obj 
= m_llist
->FindObjectScreen(dc
, findPos
, 
 259    wxLayoutObject::UserData 
*u 
= obj 
? obj
->GetUserData() : NULL
; 
 261    // has the mouse only been moved? 
 264       case WXLOWIN_MENU_MOUSEMOVE
: 
 265          // found is only true if we are really over an object, not just 
 267          if(found 
&& u 
&& ! m_Selecting
) 
 270                SetCursor(wxCURSOR_HAND
); 
 272             if(m_StatusBar 
&& m_StatusFieldLabel 
!= -1) 
 274                const wxString 
&label 
= u
->GetLabel(); 
 276                   m_StatusBar
->SetStatusText(label
, 
 283                SetCursor(wxCURSOR_IBEAM
); 
 284             m_HandCursor 
= FALSE
; 
 285             if(m_StatusBar 
&& m_StatusFieldLabel 
!= -1) 
 286                m_StatusBar
->SetStatusText("", m_StatusFieldLabel
); 
 290          if ( event
.LeftIsDown() ) 
 292             // m_Selecting might not be set if the button got pressed 
 293             // outside this window, so check for it: 
 296                m_llist
->ContinueSelection(cursorPos
, m_ClickPosition
); 
 297                DoPaint();  // TODO: we don't have to redraw everything! 
 308       case WXLOWIN_MENU_LDOWN
: 
 310              // always move cursor to mouse click: 
 313                 // we have found the real position 
 314                 m_llist
->MoveCursorTo(cursorPos
); 
 318                 // click beyond the end of the text 
 319                 m_llist
->MoveCursorToEnd(); 
 322              // clicking a mouse removes the selection 
 323              if ( m_llist
->HasSelection() ) 
 325                 m_llist
->DiscardSelection(); 
 327                 DoPaint();     // TODO: we don't have to redraw everything! 
 330              // Calculate where the top of the visible area is: 
 334              GetScrollPixelsPerUnit(&dx
, &dy
); 
 337              wxPoint 
offset(-x0
+WXLO_XOFFSET
, -y0
+WXLO_YOFFSET
); 
 339              if(m_CursorVisibility 
== -1) 
 340                 m_CursorVisibility 
= 1; 
 342              if(m_CursorVisibility 
!= 0) 
 344                 // draw a thick cursor for editable windows with focus 
 345                 m_llist
->DrawCursor(dc
, m_HaveFocus 
&& IsEditable(), offset
); 
 349              DoPaint(); // DoPaint suppresses flicker under GTK 
 353              m_llist
->StartSelection(wxPoint(-1, -1), m_ClickPosition
); 
 358       case WXLOWIN_MENU_LUP
: 
 361             m_llist
->EndSelection(); 
 364             DoPaint();     // TODO: we don't have to redraw everything! 
 368       case WXLOWIN_MENU_MDOWN
: 
 372       case WXLOWIN_MENU_DBLCLICK
: 
 373          // select a word under cursor 
 374          m_llist
->MoveCursorTo(cursorPos
); 
 375          m_llist
->MoveCursorWord(-1); 
 376          m_llist
->StartSelection(); 
 377          m_llist
->MoveCursorWord(1, false); 
 378          m_llist
->EndSelection(); 
 380          DoPaint();     // TODO: we don't have to redraw everything! 
 384    // notify about mouse events? 
 387       // only do the menu if activated, editable and not on a clickable object 
 388       if(eventId 
== WXLOWIN_MENU_RCLICK
 
 390          && (! obj 
|| u 
== NULL
)) 
 392          PopupMenu(m_PopupMenu
, m_ClickPosition
.x
, m_ClickPosition
.y
); 
 397       // find the object at this position 
 400          wxCommandEvent 
commandEvent(wxEVT_COMMAND_MENU_SELECTED
, eventId
); 
 401          commandEvent
.SetEventObject( this ); 
 402          commandEvent
.SetClientData((char *)obj
); 
 403          GetEventHandler()->ProcessEvent(commandEvent
); 
 411 // ---------------------------------------------------------------------------- 
 412 // keyboard handling. 
 413 // ---------------------------------------------------------------------------- 
 416 wxLayoutWindow::OnChar(wxKeyEvent
& event
) 
 418    int keyCode 
= event
.KeyCode(); 
 419    bool ctrlDown 
= event
.ControlDown(); 
 421 #ifdef WXLAYOUT_DEBUG 
 422    if(keyCode 
== WXK_F1
) 
 430    // Force m_Selecting to be false if shift is no longer 
 431    // pressed. OnKeyUp() cannot catch all Shift-Up events. 
 432    if(m_Selecting 
&& !event
.ShiftDown()) 
 435       m_llist
->EndSelection(); 
 439    // If we deleted the selection here, we must not execute the 
 440    // deletion in Delete/Backspace handling. 
 441    bool deletedSelection 
= false; 
 442    // pressing any non-arrow key optionally replaces the selection: 
 443    if(m_AutoDeleteSelection
 
 445       && m_llist
->HasSelection()  
 446       && ! IsDirectionKey(keyCode
) 
 447       && ! (event
.AltDown() || ctrlDown
) 
 450       m_llist
->DeleteSelection(); 
 451       deletedSelection 
= true; 
 454    // <Shift>+<arrow> starts selection 
 455    if ( IsDirectionKey(keyCode
) ) 
 459          // just continue the old selection 
 460          if( event
.ShiftDown() ) 
 461             m_llist
->ContinueSelection(); 
 464             m_llist
->DiscardSelection(); 
 468       else if( event
.ShiftDown() ) 
 471          m_llist
->StartSelection(); 
 476    // If needed, make cursor visible: 
 477    if(m_CursorVisibility 
== -1) 
 478       m_CursorVisibility 
= 1; 
 480    /* These two nested switches work like this: 
 481       The first one processes all non-editing keycodes, to move the 
 482       cursor, etc. It's default will process all keycodes causing 
 483       modifications to the buffer, but only if editing is allowed. 
 489          m_llist
->MoveCursorWord(1); 
 491          m_llist
->MoveCursorHorizontally(1); 
 495          m_llist
->MoveCursorWord(-1); 
 497          m_llist
->MoveCursorHorizontally(-1); 
 500       m_llist
->MoveCursorVertically(-1); 
 503       m_llist
->MoveCursorVertically(1); 
 506       m_llist
->MoveCursorVertically(-Y_SCROLL_PAGE
); 
 509       m_llist
->MoveCursorVertically(Y_SCROLL_PAGE
); 
 513          m_llist
->MoveCursorTo(wxPoint(0, 0)); 
 515          m_llist
->MoveCursorToBeginOfLine(); 
 519          m_llist
->MoveCursorToEnd(); 
 521          m_llist
->MoveCursorToEndOfLine(); 
 525       if(keyCode 
== 'c' && ctrlDown
) 
 527          // this should work even in read-only mode 
 530       else if( IsEditable() ) 
 532          /* First, handle control keys */ 
 533          if(ctrlDown 
&& ! event
.AltDown()) 
 542                if(! deletedSelection
) // already done 
 546                m_llist
->DeleteLines(1); 
 548             case 'h': // like backspace 
 549                if(m_llist
->MoveCursorHorizontally(-1)) m_llist
->Delete(1); 
 552                m_llist
->DeleteToBeginOfLine(); 
 555                m_llist
->DeleteToEndOfLine(); 
 563 #ifdef WXLAYOUT_DEBUG 
 565                m_llist
->SetFont(-1,-1,-1,-1,true);  // underlined 
 573          else if( event
.AltDown() && ! event
.ControlDown() ) 
 579                m_llist
->DeleteWord(); 
 586          else if ( ! event
.AltDown() && ! event
.ControlDown()) 
 591                if(event
.ShiftDown()) 
 595                if(event
.ShiftDown()) 
 598                   if(! deletedSelection
) 
 601             case WXK_BACK
: // backspace 
 602                if(! deletedSelection
) 
 603                   if(m_llist
->MoveCursorHorizontally(-1)) 
 608                   m_llist
->WrapLine(m_WrapMargin
); 
 609                m_llist
->LineBreak(); 
 614                    // TODO should be configurable 
 615                    static const int tabSize 
= 8; 
 617                    CoordType x 
= m_llist
->GetCursorPos().x
; 
 618                    size_t numSpaces 
= tabSize 
- x 
% tabSize
; 
 619                    m_llist
->Insert(wxString(' ', numSpaces
)); 
 624                if((!(event
.ControlDown() || event
.AltDown() || event
.MetaDown())) 
 625                   && (keyCode 
< 256 && keyCode 
>= 32) 
 628                   if(m_WrapMargin 
> 0 && isspace(keyCode
)) 
 629                      m_llist
->WrapLine(m_WrapMargin
); 
 630                   m_llist
->Insert((char)keyCode
); 
 642       // continue selection to the current (new) cursor position 
 643       m_llist
->ContinueSelection(); 
 646    // we must call ResizeScrollbars() before ScrollToCursor(), otherwise the 
 647    // ne cursor position might be outside the current scrolllbar range 
 651    // refresh the screen 
 652    DoPaint(m_llist
->GetUpdateRect()); 
 656 wxLayoutWindow::OnKeyUp(wxKeyEvent
& event
) 
 658    if ( event
.KeyCode() == WXK_SHIFT 
&& m_Selecting 
) 
 660       m_llist
->EndSelection(); 
 669 wxLayoutWindow::ScrollToCursor(void) 
 671    wxClientDC 
dc( this ); 
 674    int x0
,y0
,x1
,y1
, dx
, dy
; 
 676    // Calculate where the top of the visible area is: 
 678    GetScrollPixelsPerUnit(&dx
, &dy
); 
 681    WXLO_DEBUG(("ScrollToCursor: ViewStart is %d/%d", x0
, y0
)); 
 683    // Get the size of the visible window: 
 684    GetClientSize(&x1
, &y1
); 
 686    // update the cursor screen position 
 689    // Make sure that the scrollbars are at a position so that the cursor is 
 690    // visible if we are editing 
 691    WXLO_DEBUG(("m_ScrollToCursor = %d", (int) m_ScrollToCursor
)); 
 692    wxPoint cc 
= m_llist
->GetCursorScreenPos(dc
); 
 694    // the cursor should be completely visible in both directions 
 695    wxPoint 
cs(m_llist
->GetCursorSize()); 
 698    if ( cc
.x 
< x0 
|| cc
.x 
>= x0 
+ x1 
- cs
.x 
) 
 705    if ( cc
.y 
< y0 
|| cc
.y 
>= y0 
+ y1 
- cs
.y 
) 
 712    if ( nx 
!= -1 || ny 
!= -1 ) 
 714       // set new view start 
 715       Scroll(nx 
== -1 ? -1 : (nx
+dx
-1)/dx
, ny 
== -1 ? -1 : (ny
+dy
-1)/dy
); 
 718       m_ScrollToCursor 
= false; 
 723 wxLayoutWindow::OnPaint( wxPaintEvent 
&WXUNUSED(event
)) 
 725    wxRect region 
= GetUpdateRegion().GetBox(); 
 726    InternalPaint(®ion
); 
 730 wxLayoutWindow::DoPaint(const wxRect 
*updateRect
) 
 733    // Calling Refresh() causes bad flicker under wxGTK!!! 
 734    InternalPaint(updateRect
); 
 736    // shouldn't specify the update rectangle if it doesn't include all the 
 737    // changed locations - otherwise, they won't be repainted at all because 
 738    // the system clips the display to the update rect 
 739    Refresh(FALSE
); //, updateRect); 
 744 wxLayoutWindow::InternalPaint(const wxRect 
*updateRect
) 
 746    wxPaintDC 
dc( this ); 
 749 #ifdef WXLAYOUT_USE_CARET 
 750    // hide the caret before drawing anything 
 752 #endif // WXLAYOUT_USE_CARET 
 754    int x0
,y0
,x1
,y1
, dx
, dy
; 
 756    // Calculate where the top of the visible area is: 
 758    GetScrollPixelsPerUnit(&dx
, &dy
); 
 761    // Get the size of the visible window: 
 762    GetClientSize(&x1
,&y1
); 
 768       WXLO_DEBUG(("Update rect: %ld,%ld / %ld,%ld", 
 769                   updateRect
->x
, updateRect
->y
, 
 770                   updateRect
->x
+updateRect
->width
, 
 771                   updateRect
->y
+updateRect
->height
)); 
 779    /* Check whether the window has grown, if so, we need to reallocate 
 780       the bitmap to be larger. */ 
 781    if(x1 
> m_bitmapSize
.x 
|| y1 
> m_bitmapSize
.y
) 
 783       wxASSERT(m_bitmapSize
.x 
> 0); 
 784       wxASSERT(m_bitmapSize
.y 
> 0); 
 786       m_memDC
->SelectObject(wxNullBitmap
); 
 788       m_bitmapSize 
= wxPoint(x1
,y1
); 
 789       m_bitmap 
= new wxBitmap(x1
,y1
); 
 790       m_memDC
->SelectObject(*m_bitmap
); 
 793    m_memDC
->SetDeviceOrigin(0,0); 
 794    m_memDC
->SetBackground(wxBrush(m_llist
->GetDefaultStyleInfo().GetBGColour(),wxSOLID
)); 
 795    m_memDC
->SetPen(wxPen(m_llist
->GetDefaultStyleInfo().GetBGColour(), 
 797    m_memDC
->SetLogicalFunction(wxCOPY
); 
 800    // fill the background with the background bitmap 
 805          w 
= m_BGbitmap
->GetWidth(), 
 806          h 
= m_BGbitmap
->GetHeight(); 
 807       for(y 
= 0; y 
< y1
; y
+=h
) 
 808          for(x 
= 0; x 
< x1
; x
+=w
) 
 809             m_memDC
->DrawBitmap(*m_BGbitmap
, x
, y
); 
 810       m_memDC
->SetBackgroundMode(wxTRANSPARENT
); 
 813    // This is the important bit: we tell the list to draw itself 
 817       WXLO_DEBUG(("Update rect: %ld,%ld / %ld,%ld", 
 818                   updateRect
->x
, updateRect
->y
, 
 819                   updateRect
->x
+updateRect
->width
, 
 820                   updateRect
->y
+updateRect
->height
)); 
 824    // Device origins on the memDC are suspect, we translate manually 
 825    // with the translate parameter of Draw(). 
 826    wxPoint 
offset(-x0
+WXLO_XOFFSET
,-y0
+WXLO_YOFFSET
); 
 827    m_llist
->Draw(*m_memDC
,offset
, y0
, y0
+y1
); 
 829    // We start calculating a new update rect before drawing the 
 830    // cursor, so that the cursor coordinates get included in the next 
 831    // update rectangle (although they are drawn on the memDC, this is 
 832    // needed to erase it): 
 833    m_llist
->InvalidateUpdateRect(); 
 834    if(m_CursorVisibility 
!= 0) 
 836       // draw a thick cursor for editable windows with focus 
 837       m_llist
->DrawCursor(*m_memDC
, 
 838                           m_HaveFocus 
&& IsEditable(), 
 842 // Now copy everything to the screen: 
 844    // This somehow doesn't work, but even the following bit with the 
 845    // whole rect at once is still a bit broken I think. 
 846    wxRegionIterator 
ri ( GetUpdateRegion() ); 
 850          WXLO_DEBUG(("UpdateRegion: %ld,%ld, %ld,%ld", 
 851                      ri
.GetX(),ri
.GetY(),ri
.GetW(),ri
.GetH())); 
 852          dc
.Blit(x0
+ri
.GetX(),y0
+ri
.GetY(),ri
.GetW(),ri
.GetH(), 
 853                  m_memDC
,ri
.GetX(),ri
.GetY(),wxCOPY
,FALSE
); 
 859       // FIXME: Trying to copy only the changed parts, but it does not seem 
 861 //      x0 = updateRect->x; y0 = updateRect->y; 
 862 //      if(updateRect->height < y1) 
 863 //         y1 = updateRect->height; 
 864 //      y1 += WXLO_YOFFSET; //FIXME might not be needed 
 865       dc
.Blit(x0
,y0
,x1
,y1
,m_memDC
,0,0,wxCOPY
,FALSE
); 
 868 #ifdef WXLAYOUT_USE_CARET 
 869    // show the caret back after everything is redrawn 
 871 #endif // WXLAYOUT_USE_CARET 
 874    m_ScrollToCursor 
= false; 
 876    if ( m_StatusBar 
&& m_StatusFieldCursor 
!= -1 ) 
 878       static wxPoint 
s_oldCursorPos(-1, -1); 
 880       wxPoint 
pos(m_llist
->GetCursorPos()); 
 882       // avoid unnecessary status bar refreshes 
 883       if ( pos 
!= s_oldCursorPos 
) 
 885          s_oldCursorPos 
= pos
; 
 888          label
.Printf(_("Ln:%d Col:%d"), pos
.y 
+ 1, pos
.x 
+ 1); 
 889          m_StatusBar
->SetStatusText(label
, m_StatusFieldCursor
); 
 895 wxLayoutWindow::OnSize(wxSizeEvent 
&event
) 
 905 // change the range and position of scrollbars 
 907 wxLayoutWindow::ResizeScrollbars(bool exact
) 
 909    wxPoint max 
= m_llist
->GetSize(); 
 910    wxSize size 
= GetClientSize(); 
 912    WXLO_DEBUG(("ResizeScrollbars: max size = (%ld, %ld)", 
 913                (long int)max
.x
, (long int) max
.y
)); 
 915    // in the absence of scrollbars we should compare with the client size 
 916    if ( !m_hasHScrollbar 
) 
 917       m_maxx 
= size
.x 
- WXLO_ROFFSET
; 
 918    if ( !m_hasVScrollbar 
) 
 919       m_maxy 
= size
.y 
- WXLO_BOFFSET
; 
 921    // check if the text hasn't become too big 
 922    // TODO why do we set both at once? they're independent... 
 923    if( max
.x 
> m_maxx 
- WXLO_ROFFSET 
|| max
.y 
> m_maxy 
- WXLO_BOFFSET 
|| exact 
) 
 925       // text became too large 
 928          // add an extra bit to the sizes to avoid future updates 
 929          max
.x 
+= WXLO_ROFFSET
; 
 930          max
.y 
+= WXLO_BOFFSET
; 
 933       ViewStart(&m_ViewStartX
, &m_ViewStartY
); 
 934       SetScrollbars(X_SCROLL_PAGE
, Y_SCROLL_PAGE
, 
 935                     max
.x 
/ X_SCROLL_PAGE 
+ 1, max
.y 
/ Y_SCROLL_PAGE 
+ 1, 
 936                     m_ViewStartX
, m_ViewStartY
, 
 940       m_hasVScrollbar 
= true; 
 942       m_maxx 
= max
.x 
+ X_SCROLL_PAGE
; 
 943       m_maxy 
= max
.y 
+ Y_SCROLL_PAGE
; 
 948       // check if the window hasn't become too big, thus making the scrollbars 
 950       if ( m_hasHScrollbar 
&& (max
.x 
< size
.x
) ) 
 952          // remove the horizontal scrollbar 
 953          SetScrollbars(0, -1, 0, -1, 0, -1, true); 
 954          m_hasHScrollbar 
= false; 
 957       if ( m_hasVScrollbar 
&& (max
.y 
< size
.y
) ) 
 959          // remove the vertical scrollbar 
 960          SetScrollbars(-1, 0, -1, 0, -1, 0, true); 
 961          m_hasVScrollbar 
= false; 
 967 // ---------------------------------------------------------------------------- 
 968 // clipboard operations 
 970 // ---------------------------------------------------------------------------- 
 973 wxLayoutWindow::Paste(bool primary
) 
 976    if (wxTheClipboard
->Open()) 
 980          wxTheClipboard
->UsePrimarySelection(); 
 982 #if wxUSE_PRIVATE_CLIPBOARD_FORMAT 
 983       wxLayoutDataObject wxldo
; 
 984       if (wxTheClipboard
->IsSupported( wxldo
.GetFormat() )) 
 986          wxTheClipboard
->GetData(&wxldo
); 
 989          //FIXME: missing functionality  m_llist->Insert(wxldo.GetList()); 
 994          wxTextDataObject data
; 
 995          if (wxTheClipboard
->IsSupported( data
.GetFormat() )) 
 997             wxTheClipboard
->GetData(&data
); 
 998             wxString text 
= data
.GetText(); 
 999             wxLayoutImportText( m_llist
, text
); 
1002       wxTheClipboard
->Close(); 
1007 wxLayoutWindow::Copy(bool invalidate
) 
1009    // Calling GetSelection() will automatically do an EndSelection() 
1010    // on the list, but we need to take a note of it, too: 
1013       m_Selecting 
= false; 
1014       m_llist
->EndSelection(); 
1017    wxLayoutDataObject wldo
; 
1018    wxLayoutList 
*llist 
= m_llist
->GetSelection(&wldo
, invalidate
); 
1021    // Export selection as text: 
1023    wxLayoutExportObject 
*export
; 
1024    wxLayoutExportStatus 
status(llist
); 
1025    while((export 
= wxLayoutExport( &status
, WXLO_EXPORT_AS_TEXT
)) != NULL
) 
1027       if(export
->type 
== WXLO_EXPORT_TEXT
) 
1028          text 
<< *(export
->content
.text
); 
1033    // The exporter always appends a newline, so we chop it off if it 
1036       size_t len 
= text
.Length(); 
1037       if(len 
> 2 && text
[len
-2] ==  '\r') // Windows 
1038          text 
= text
.Mid(0,len
-2); 
1039       else if(len 
> 1 && text
[len
-1] == '\n') 
1040          text 
= text
.Mid(0,len
-1); 
1044    if (wxTheClipboard
->Open()) 
1046       wxTextDataObject 
*data 
= new wxTextDataObject( text 
); 
1047       bool  rc 
= wxTheClipboard
->SetData( data 
); 
1048 #if wxUSE_PRIVATE_CLIPBOARD_FORMAT 
1049       rc 
|= wxTheClipboard
->AddData( &wldo 
); 
1051       wxTheClipboard
->Close(); 
1059 wxLayoutWindow::Cut(void) 
1061    if(Copy(false)) // do not invalidate selection after copy 
1063       m_llist
->DeleteSelection(); 
1070 // ---------------------------------------------------------------------------- 
1072 // ---------------------------------------------------------------------------- 
1075 wxLayoutWindow::Find(const wxString 
&needle
, 
1076                      wxPoint 
* fromWhere
) 
1080    if(fromWhere 
== NULL
) 
1081       found 
= m_llist
->FindText(needle
, m_llist
->GetCursorPos()); 
1083       found 
= m_llist
->FindText(needle
, *fromWhere
); 
1091       m_llist
->MoveCursorTo(found
); 
1098 // ---------------------------------------------------------------------------- 
1100 // ---------------------------------------------------------------------------- 
1103 wxLayoutWindow::MakeFormatMenu() 
1105    wxMenu 
*m 
= new wxMenu(_("Layout Menu")); 
1107    m
->Append(WXLOWIN_MENU_LARGER   
,_("&Larger"),_("Switch to larger font."), false); 
1108    m
->Append(WXLOWIN_MENU_SMALLER  
,_("&Smaller"),_("Switch to smaller font."), false); 
1109    m
->AppendSeparator(); 
1110    m
->Append(WXLOWIN_MENU_UNDERLINE
, _("&Underline"),_("Underline mode."), true); 
1111    m
->Append(WXLOWIN_MENU_BOLD
, _("&Bold"),_("Bold mode."), true); 
1112    m
->Append(WXLOWIN_MENU_ITALICS
, _("&Italics"),_("Italics mode."), true); 
1113    m
->AppendSeparator(); 
1114    m
->Append(WXLOWIN_MENU_ROMAN     
,_("&Roman"),_("Switch to roman font."), false); 
1115    m
->Append(WXLOWIN_MENU_TYPEWRITER
,_("&Typewriter"),_("Switch to typewriter font."), false); 
1116    m
->Append(WXLOWIN_MENU_SANSSERIF 
,_("&Sans Serif"),_("Switch to sans serif font."), false); 
1121 void wxLayoutWindow::OnUpdateMenuUnderline(wxUpdateUIEvent
& event
) 
1123    event
.Check(m_llist
->IsFontUnderlined()); 
1126 void wxLayoutWindow::OnUpdateMenuBold(wxUpdateUIEvent
& event
) 
1128    event
.Check(m_llist
->IsFontBold()); 
1131 void wxLayoutWindow::OnUpdateMenuItalic(wxUpdateUIEvent
& event
) 
1133    event
.Check(m_llist
->IsFontItalic()); 
1136 void wxLayoutWindow::OnMenu(wxCommandEvent
& event
) 
1138    switch (event
.GetId()) 
1140    case WXLOWIN_MENU_LARGER
: 
1141       m_llist
->SetFontLarger(); Refresh(FALSE
); break; 
1142    case WXLOWIN_MENU_SMALLER
: 
1143       m_llist
->SetFontSmaller(); Refresh(FALSE
); break; 
1144    case WXLOWIN_MENU_UNDERLINE
: 
1145       m_llist
->ToggleFontUnderline(); Refresh(FALSE
); break; 
1146    case WXLOWIN_MENU_BOLD
: 
1147       m_llist
->ToggleFontWeight(); Refresh(FALSE
); break; 
1148    case WXLOWIN_MENU_ITALICS
: 
1149       m_llist
->ToggleFontItalics(); Refresh(FALSE
); break; 
1150    case WXLOWIN_MENU_ROMAN
: 
1151       m_llist
->SetFontFamily(wxROMAN
); Refresh(FALSE
); break; 
1152    case WXLOWIN_MENU_TYPEWRITER
: 
1153       m_llist
->SetFontFamily(wxFIXED
); Refresh(FALSE
); break; 
1154    case WXLOWIN_MENU_SANSSERIF
: 
1155       m_llist
->SetFontFamily(wxSWISS
); Refresh(FALSE
); break; 
1159 // ---------------------------------------------------------------------------- 
1161 // ---------------------------------------------------------------------------- 
1164 wxLayoutWindow::OnSetFocus(wxFocusEvent 
&ev
) 
1171 wxLayoutWindow::OnKillFocus(wxFocusEvent 
&ev
) 
1173    m_HaveFocus 
= false; 
1177 // ---------------------------------------------------------------------------- 
1178 // private functions 
1179 // ---------------------------------------------------------------------------- 
1181 static bool IsDirectionKey(long keyCode
)