/*-*- c++ -*-********************************************************
* wxLwindow.h : a scrolled Window for displaying/entering rich text*
* *
- * (C) 1998, 1999 by Karsten Ballüder (karsten@phy.hw.ac.uk) *
+ * (C) 1998-2000 by Karsten Ballüder (ballueder@gmx.net) *
* *
* $Id$
*******************************************************************/
# pragma implementation "wxlwindow.h"
#endif
-#include <wx/wxprec.h>
+#include "wx/wxprec.h"
#ifdef __BORLANDC__
# pragma hdrstop
#include <ctype.h>
+
// ----------------------------------------------------------------------------
// macros
// ----------------------------------------------------------------------------
# define WXLO_DEBUG(x)
#endif
+// for profiling in debug mode:
+WXLO_TIMER_DEFINE(UpdateTimer);
+WXLO_TIMER_DEFINE(BlitTimer);
+WXLO_TIMER_DEFINE(LayoutTimer);
+WXLO_TIMER_DEFINE(TmpTimer);
+WXLO_TIMER_DEFINE(DrawTimer);
+
// ----------------------------------------------------------------------------
// constants
// ----------------------------------------------------------------------------
-#define wxUSE_PRIVATE_CLIPBOARD_FORMAT 1
-
// ----------------------------------------------------------------------------
// event tables
// ----------------------------------------------------------------------------
#ifndef __WXMSW__
m_FocusFollowMode = false;
#endif
+ SetWordWrap(false);
SetWrapMargin(0);
// no scrollbars initially
{
wxClientDC dc( this );
PrepareDC( dc );
- if ( eventId != WXLOWIN_MENU_MOUSEMOVE
+ if ( (eventId != WXLOWIN_MENU_MOUSEMOVE
#ifndef __WXMSW__
|| m_FocusFollowMode
#endif
+ ) && (wxWindow::FindFocus() != this)
)
SetFocus();
{
//WXLO_DEBUG(("selecting at : %d/%d", (int) event.GetX(), (int)event.GetY()));
int left, top;
- ViewStart(&left, &top);
+ GetViewStart(&left, &top);
wxSize size = GetClientSize();
int xdelta, ydelta;
// Calculate where the top of the visible area is:
int x0, y0;
- ViewStart(&x0,&y0);
+ GetViewStart(&x0,&y0);
int dx, dy;
GetScrollPixelsPerUnit(&dx, &dy);
x0 *= dx; y0 *= dy;
bool deletedSelection = false;
// pressing any non-arrow key optionally replaces the selection:
if(m_AutoDeleteSelection
+ && IsEditable()
&& !m_Selecting
&& m_llist->HasSelection()
&& ! IsDirectionKey(keyCode)
if ( IsDirectionKey(keyCode) )
{
// just continue the old selection
- if ( m_Selecting )
+ if ( m_Selecting && event.ShiftDown() )
+ m_llist->ContinueSelection();
+ else
{
+ m_llist->DiscardSelection();
+ m_Selecting = false;
if( event.ShiftDown() )
- m_llist->ContinueSelection();
- else
{
- m_llist->DiscardSelection();
- m_Selecting = false;
+ m_Selecting = true;
+ m_llist->StartSelection();
}
}
- else if( event.ShiftDown() )
- {
- m_Selecting = true;
- m_llist->StartSelection();
- }
}
// If needed, make cursor visible:
{
case 'c':
// this should work even in read-only mode
- Copy();
+ Copy(TRUE, TRUE);
break;
case 's': // search
Find("");
m_llist->DeleteToEndOfLine();
SetDirty();
break;
+ case 'c':
+ Copy(TRUE, TRUE);
+ break;
case 'v':
- Paste();
+ Paste( TRUE );
break;
case 'x':
Cut();
break;
+ case 'w':
+ if(m_WrapMargin > 0)
+ m_llist->WrapLine(m_WrapMargin);
+ break;
+ case 'q':
+ if(m_WrapMargin > 0)
+ m_llist->WrapAll(m_WrapMargin);
+ break;
#ifdef WXLAYOUT_DEBUG
case WXK_F1:
m_llist->SetFont(-1,-1,-1,-1,true); // underlined
break;
+ case 'l':
+ Refresh(TRUE);
+ break;
#endif
default:
// we don't handle it, maybe an accelerator?
}
break;
case WXK_RETURN:
- if(m_WrapMargin > 0)
+ if(m_DoWordWrap &&
+ m_WrapMargin > 0
+ && m_llist->GetCursorPos().x > m_WrapMargin)
m_llist->WrapLine(m_WrapMargin);
m_llist->LineBreak();
SetDirty();
SetDirty();
}
break;
-
+
default:
if((!(event.ControlDown() || event.AltDown()
))
&& (keyCode < 256 && keyCode >= 32)
)
{
- if(m_WrapMargin > 0 && isspace(keyCode))
+ if(m_DoWordWrap
+ && m_WrapMargin > 0
+ && m_llist->GetCursorPos().x > m_WrapMargin
+ && isspace(keyCode))
m_llist->WrapLine(m_WrapMargin);
m_llist->Insert((char)keyCode);
SetDirty();
{
//is always needed to make sure we know where the cursor is
//if(IsDirty())
- RequestUpdate(m_llist->GetUpdateRect());
+ //RequestUpdate(m_llist->GetUpdateRect());
+
+
+ ResizeScrollbars();
int x0,y0,x1,y1, dx, dy;
// Calculate where the top of the visible area is:
- ViewStart(&x0,&y0);
+ GetViewStart(&x0,&y0);
GetScrollPixelsPerUnit(&dx, &dy);
x0 *= dx; y0 *= dy;
- WXLO_DEBUG(("ScrollToCursor: ViewStart is %d/%d", x0, y0));
+ WXLO_DEBUG(("ScrollToCursor: GetViewStart is %d/%d", x0, y0));
// Get the size of the visible window:
GetClientSize(&x1, &y1);
ny = 0;
}
- if ( nx != -1 || ny != -1 )
+ if( nx != -1 || ny != -1 )
{
// set new view start
Scroll(nx == -1 ? -1 : (nx+dx-1)/dx, ny == -1 ? -1 : (ny+dy-1)/dy);
void
wxLayoutWindow::InternalPaint(const wxRect *updateRect)
{
+
wxPaintDC dc( this );
PrepareDC( dc );
int x0,y0,x1,y1, dx, dy;
// Calculate where the top of the visible area is:
- ViewStart(&x0,&y0);
+ GetViewStart(&x0,&y0);
GetScrollPixelsPerUnit(&dx, &dy);
x0 *= dx; y0 *= dy;
updateRect->y+updateRect->height));
}
- ResizeScrollbars();
+ ResizeScrollbars(true);
-
+ WXLO_TIMER_START(TmpTimer);
/* Check whether the window has grown, if so, we need to reallocate
the bitmap to be larger. */
if(x1 > m_bitmapSize.x || y1 > m_bitmapSize.y)
0,wxTRANSPARENT));
m_memDC->SetLogicalFunction(wxCOPY);
m_memDC->Clear();
-
+ WXLO_TIMER_STOP(TmpTimer);
+
// fill the background with the background bitmap
if(m_BGbitmap)
{
// update rectangle (although they are drawn on the memDC, this is
// needed to erase it):
m_llist->InvalidateUpdateRect();
- if(m_CursorVisibility != 0)
+ if(m_CursorVisibility == 1)
{
// draw a thick cursor for editable windows with focus
m_llist->DrawCursor(*m_memDC,
offset);
}
+ WXLO_TIMER_START(BlitTimer);
// Now copy everything to the screen:
#if 0
// This somehow doesn't work, but even the following bit with the
// y1 += WXLO_YOFFSET; //FIXME might not be needed
dc.Blit(x0,y0,x1,y1,m_memDC,0,0,wxCOPY,FALSE);
}
+ WXLO_TIMER_STOP(BlitTimer);
+
#ifdef WXLAYOUT_USE_CARET
// show the caret back after everything is redrawn
m_StatusBar->SetStatusText(label, m_StatusFieldCursor);
}
}
+
+ WXLO_TIMER_PRINT(LayoutTimer);
+ WXLO_TIMER_PRINT(BlitTimer);
+ WXLO_TIMER_PRINT(TmpTimer);
}
void
void
wxLayoutWindow::ResizeScrollbars(bool exact)
{
+ wxClientDC dc( this );
+ PrepareDC( dc );
+// m_llist->ForceTotalLayout();
if(! IsDirty())
+ {
+ // we are laying out just the minimum, but always up to the
+ // cursor line, so the cursor position is updated.
+ m_llist->Layout(dc, 0);
return;
-
- wxClientDC dc( this );
- PrepareDC( dc );
-// m_llist->ForceTotalLayout();
- m_llist->Layout(dc);
+ }
+ WXLO_TIMER_START(LayoutTimer);
+ m_llist->Layout(dc, -1);
+ WXLO_TIMER_STOP(LayoutTimer);
ResetDirty();
wxPoint max = m_llist->GetSize();
// TODO why do we set both at once? they're independent...
if( max.x > m_maxx - WXLO_ROFFSET
|| max.y > m_maxy - WXLO_BOFFSET
- || max.x < m_maxx - X_SCROLL_PAGE
- || max.y < m_maxy - Y_SCROLL_PAGE
+ || (max.x < m_maxx - X_SCROLL_PAGE)
+ || (max.y < m_maxy - Y_SCROLL_PAGE)
|| exact )
{
// text became too large
}
bool done = FALSE;
- if(max.x < X_SCROLL_PAGE)
+ if(max.x < X_SCROLL_PAGE && m_hasHScrollbar)
{
SetScrollbars(0,-1,0,-1,0,-1,true);
m_hasHScrollbar = FALSE;
done = TRUE;
}
- if(max.y < Y_SCROLL_PAGE)
+ if(max.y < Y_SCROLL_PAGE && m_hasVScrollbar)
{
SetScrollbars(-1,0,-1,0,-1,0,true);
m_hasVScrollbar = FALSE;
done = TRUE;
}
- if(! done)
+ if(! done &&
+// (max.x > X_SCROLL_PAGE || max.y > Y_SCROLL_PAGE)
+ (max.x > size.x - X_SCROLL_PAGE|| max.y > size.y - Y_SCROLL_PAGE)
+ )
{
- ViewStart(&m_ViewStartX, &m_ViewStartY);
+ GetViewStart(&m_ViewStartX, &m_ViewStartY);
SetScrollbars(X_SCROLL_PAGE,
Y_SCROLL_PAGE,
- max.x / X_SCROLL_PAGE + 1,
- max.y / Y_SCROLL_PAGE + 1,
- m_ViewStartX, m_ViewStartY,
+ max.x / X_SCROLL_PAGE + 2,
+ max.y / Y_SCROLL_PAGE + 2,
+ m_ViewStartX,
+ m_ViewStartY,
true);
m_hasHScrollbar =
m_hasVScrollbar = true;
+// ScrollToCursor();
}
-
+
m_maxx = max.x + X_SCROLL_PAGE;
m_maxy = max.y + Y_SCROLL_PAGE;
}
// ----------------------------------------------------------------------------
void
-wxLayoutWindow::Paste(bool primary)
+wxLayoutWindow::Paste(bool usePrivate, bool primary)
{
// this only has an effect under X11:
- if(primary) wxTheClipboard->UsePrimarySelection();
+ wxTheClipboard->UsePrimarySelection(primary);
// Read some text
if (wxTheClipboard->Open())
{
-#if wxUSE_PRIVATE_CLIPBOARD_FORMAT
- wxLayoutDataObject wxldo;
- if ( wxTheClipboard->GetData(wxldo) )
+ if(usePrivate)
+ {
+ wxLayoutDataObject wxldo;
+ if (wxTheClipboard->IsSupported( wxldo.GetFormat() ))
+ {
+ if(wxTheClipboard->GetData(wxldo))
+ {
+ wxTheClipboard->Close();
+ wxString str = wxldo.GetLayoutData();
+ m_llist->Read(str);
+ SetDirty();
+ RequestUpdate();
+ return;
+ }
+ }
+ }
+ wxTextDataObject data;
+ if (wxTheClipboard->IsSupported( data.GetFormat() )
+ && wxTheClipboard->GetData(data) )
{
- //FIXME: missing functionality m_llist->Insert(wxldo.GetList());
- wxLayoutImportText(m_llist, wxldo.GetLayoutData());
+ wxTheClipboard->Close();
+ wxString text = data.GetText();
+ wxLayoutImportText( m_llist, text);
SetDirty();
+ RequestUpdate();
+ return;
}
- else
-#endif
+ }
+ // if everything failed we can still try the primary:
+ wxTheClipboard->Close();
+ if(! primary) // not tried before
+ {
+ wxTheClipboard->UsePrimarySelection();
+ if (wxTheClipboard->Open())
{
wxTextDataObject data;
if (wxTheClipboard->IsSupported( data.GetFormat() )
wxString text = data.GetText();
wxLayoutImportText( m_llist, text);
SetDirty();
+ RequestUpdate();
}
+ wxTheClipboard->Close();
}
- wxTheClipboard->Close();
}
}
bool
-wxLayoutWindow::Copy(bool invalidate)
+wxLayoutWindow::Copy(bool invalidate, bool privateFormat, bool primary)
{
// Calling GetSelection() will automatically do an EndSelection()
// on the list, but we need to take a note of it, too:
m_llist->EndSelection();
}
-#if wxUSE_PRIVATE_CLIPBOARD_FORMAT
- // the data object which holds all different data objects, one for each
- // format we support
- wxDataObjectComposite *data = new wxDataObjectComposite;
-#endif
-
wxLayoutDataObject *wldo = new wxLayoutDataObject;
wxLayoutList *llist = m_llist->GetSelection(wldo, invalidate);
if(! llist)
text = text.Mid(0,len-1);
}
- if (!wxTheClipboard->Open())
- return FALSE;
-
-#if wxUSE_PRIVATE_CLIPBOARD_FORMAT
- data->Add(wldo, TRUE /* preferred */);
- data->Add(new wxTextDataObject(text));
-#else
- wxTextDataObject *data = new wxTextDataObject( text );
+#if 0
+if(! primary) // always copy as text-only to primary selection
+ {
+ wxTheClipboard->UsePrimarySelection();
+ if (wxTheClipboard->Open())
+ {
+ wxTextDataObject *data = new wxTextDataObject( text );
+ wxTheClipboard->SetData( data );
+ wxTheClipboard->Close();
+ }
+ }
#endif
- bool rc = wxTheClipboard->SetData( data );
+ wxTheClipboard->UsePrimarySelection(primary);
+ if (wxTheClipboard->Open())
+ {
+ wxTextDataObject *data = new wxTextDataObject( text );
+ bool rc;
- wxTheClipboard->Close();
- return rc;
+ rc = wxTheClipboard->SetData( data );
+ if(privateFormat)
+ rc |= wxTheClipboard->SetData( wldo );
+ wxTheClipboard->Close();
+ return rc;
+ }
+ else
+ delete wldo;
+
+ return FALSE;
}
bool
-wxLayoutWindow::Cut(void)
+wxLayoutWindow::Cut(bool privateFormat, bool usePrimary)
{
- if(Copy(false)) // do not invalidate selection after copy
+ if(Copy(false, privateFormat, usePrimary)) // do not invalidate selection after copy
{
m_llist->DeleteSelection();
SetDirty();