Updated from Mahogany source

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/branches/WX_2_2_BRANCH@7378 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Karsten Ballüder
2000-05-10 20:00:53 +00:00
parent bf49fbcff9
commit 548812d9af
5 changed files with 382 additions and 129 deletions

View File

@@ -10,6 +10,14 @@ by Karsten Ballueder <ballueder@usa.net>.
This is still work in progress, so if you want to make any significant
changes, please get in touch with me before.
*** THIS SOURCE IS USUALLY OUTDATED AND FOR DEMONSTRATION ONLY ***
*** GET THE VERY LATEST VERSION OF THE WXLAYOUT CLASSES FROM ***
*** THE SOURCE OF THE MAHOGANY MAIL/NEWS CLIENT, AVAILABLE FROM ***
*** http://www.wxwindows.org/Mahogany/ ***
There are three building blocks for rich text editing:
wxllist :

View File

@@ -1,7 +1,7 @@
/*-*- c++ -*-********************************************************
* wxllist: wxLayoutList, a layout engine for text and graphics *
* *
* (C) 1998-1999 by Karsten Ball<6C>der (Ballueder@usa.net) *
* (C) 1998-2000 by Karsten Ball<6C>der (Ballueder@gmx.net) *
* *
* $Id$
*******************************************************************/
@@ -60,6 +60,7 @@
#include <ctype.h>
/// This should never really get created
#define WXLLIST_TEMPFILE "__wxllist.tmp"
@@ -72,16 +73,19 @@
{
"invalid", "text", "cmd", "icon"
};
void
wxLayoutObject::Debug(void)
wxString
wxLayoutObject::DebugDump(void) const
{
WXLO_DEBUG(("%s",g_aTypeStrings[GetType()]));
wxString str;
str.Printf("%s",g_aTypeStrings[GetType()]);
return str;
}
#else
# define TypeString(t) ""
# define WXLO_DEBUG(x)
#endif
// FIXME under MSW, this constant is needed to make the thing properly redraw
// itself - I don't know where the size calculation error is and I can't
// waste time looking for it right now. Search for occurences of
@@ -165,6 +169,7 @@ bool Contains(const wxRect &r, const wxPoint &p)
//@}
static
void ReadString(wxString &to, wxString &from)
{
to = "";
@@ -187,7 +192,7 @@ wxLayoutObject::Read(wxString &istr)
{
wxString tmp;
ReadString(tmp, istr);
int type = -1;
int type = WXLO_TYPE_INVALID;
sscanf(tmp.c_str(),"%d", &type);
switch(type)
@@ -370,11 +375,14 @@ wxLayoutObjectText::Layout(wxDC &dc, class wxLayoutList *llist)
#ifdef WXLAYOUT_DEBUG
void
wxLayoutObjectText::Debug(void)
wxString
wxLayoutObjectText::DebugDump(void) const
{
wxLayoutObject::Debug();
WXLO_DEBUG((" `%s`", m_Text.c_str()));
wxString str;
str = wxLayoutObject::DebugDump();
wxString str2;
str2.Printf(" `%s`", m_Text.c_str());
return str+str2;
}
#endif
@@ -412,7 +420,7 @@ wxLayoutObjectIcon::Write(wxString &ostr)
wxString file = wxGetTempFileName("wxloexport");
ostr << WXLO_TYPE_ICON << '\n'
ostr << (int) WXLO_TYPE_ICON << '\n'
<< file << '\n';
m_Icon->SaveFile(file, WXLO_BITMAP_FORMAT);
}
@@ -449,11 +457,7 @@ wxLayoutObjectIcon::wxLayoutObjectIcon(wxBitmap *icon)
{
m_Icon = icon;
if(! m_Icon)
#if wxICON_IS_BITMAP
m_Icon = new wxIcon;
#else
m_Icon = new wxBitmap;
#endif
}
void
@@ -557,25 +561,25 @@ wxLayoutObjectCmd::Copy(void)
void
wxLayoutObjectCmd::Write(wxString &ostr)
{
ostr << WXLO_TYPE_CMD << '\n'
<< m_StyleInfo->family << '\n'
<< m_StyleInfo->size << '\n'
<< m_StyleInfo->style << '\n'
<< m_StyleInfo->weight << '\n'
<< m_StyleInfo->underline << '\n'
<< m_StyleInfo->m_fg_valid << '\n'
<< m_StyleInfo->m_bg_valid << '\n';
ostr << (int) WXLO_TYPE_CMD << '\n'
<< (int) m_StyleInfo->family << '\n'
<< (int) m_StyleInfo->size << '\n'
<< (int) m_StyleInfo->style << '\n'
<< (int) m_StyleInfo->weight << '\n'
<< (int) m_StyleInfo->underline << '\n'
<< (int) m_StyleInfo->m_fg_valid << '\n'
<< (int) m_StyleInfo->m_bg_valid << '\n';
if(m_StyleInfo->m_fg_valid)
{
ostr << m_StyleInfo->m_fg.Red() << '\n'
<< m_StyleInfo->m_fg.Green() << '\n'
<< m_StyleInfo->m_fg.Blue() << '\n';
ostr << (int) m_StyleInfo->m_fg.Red() << '\n'
<< (int) m_StyleInfo->m_fg.Green() << '\n'
<< (int) m_StyleInfo->m_fg.Blue() << '\n';
}
if(m_StyleInfo->m_bg_valid)
{
ostr << m_StyleInfo->m_bg.Red() << '\n'
<< m_StyleInfo->m_bg.Green() << '\n'
<< m_StyleInfo->m_bg.Blue() << '\n';
ostr << (int) m_StyleInfo->m_bg.Red() << '\n'
<< (int) m_StyleInfo->m_bg.Green() << '\n'
<< (int) m_StyleInfo->m_bg.Blue() << '\n';
}
}
/* static */
@@ -665,10 +669,9 @@ wxLayoutLine::wxLayoutLine(wxLayoutLine *prev, wxLayoutList *llist)
m_Length = 0;
m_updateLeft = -1;
MarkDirty(0);
m_Previous = prev;
m_Next = NULL;
MarkDirty(0);
m_LineNumber = 0;
RecalculatePosition(llist);
@@ -1273,7 +1276,9 @@ wxLayoutLine::Break(CoordType xpos, wxLayoutList *llist)
wxLayoutLine *newLine = new wxLayoutLine(this, llist);
// split object at i:
if((**i).GetType() == WXLO_TYPE_TEXT && offset != 0)
if((**i).GetType() == WXLO_TYPE_TEXT
&& offset != 0
&& offset != (**i).GetLength() )
{
wxString left, right;
wxLayoutObjectText *tobj = (wxLayoutObjectText *) *i;
@@ -1304,6 +1309,130 @@ wxLayoutLine::Break(CoordType xpos, wxLayoutList *llist)
return newLine;
}
bool
wxLayoutLine::Wrap(CoordType wrapmargin, wxLayoutList *llist)
{
if(GetLength() < wrapmargin)
return FALSE; // nothing to do
// find the object which covers the wrapmargin:
CoordType offset;
wxLOiterator i = FindObject(wrapmargin, &offset);
wxCHECK_MSG( i != NULLIT, FALSE, "Cannot find object covering wrapmargin.");
// from this object on, the rest of the line must be copied to the
// next one:
wxLOiterator copyObject = NULLIT;
// if we split a text-object, we must pre-pend some text to the
// next line later on, remember it here:
wxString prependText = "";
// we might need to adjust the cursor position later, so remember it
size_t xpos = llist->GetCursorPos().x;
// by how much did we shorten the current line:
size_t shorter = 0;
// remember cursor location of object
size_t objectCursorPos = 0;
size_t breakpos = offset;
if( (**i).GetType() != WXLO_TYPE_TEXT )
{
// break before a non-text object
copyObject = i;
}
else
{
bool foundSpace = FALSE;
do
{
// while(i != NULLIT && (**i).GetType() != WXLO_TYPE_TEXT)
// i--;
// try to find a suitable place to split the object:
wxLayoutObjectText *tobj = (wxLayoutObjectText *)*i;
if((**i).GetType() == WXLO_TYPE_TEXT
&& tobj->GetText().Length() >= breakpos)
{
do
{
foundSpace = isspace(tobj->GetText()[breakpos]) != 0;
if ( foundSpace )
break;
}
while ( breakpos-- > 0 );
}
else
{
breakpos = 0;
}
if(! foundSpace) // breakpos == 0!
{
if(i == m_ObjectList.begin())
return FALSE; // could not break line
else
{
i--;
while(i != m_ObjectList.begin()
&& (**i).GetType() != WXLO_TYPE_TEXT )
{
i--;
}
breakpos = (**i).GetLength();
}
}
}while(! foundSpace);
// before we actually break the object, we need to know at which
// cursorposition it starts, so we can restore the cursor if needed:
if( this == llist->GetCursorLine() && xpos >= breakpos )
{
for(wxLOiterator j = m_ObjectList.begin();
j != NULLIT && j != i; j++)
objectCursorPos += (**j).GetLength();
}
// now we know where to break it:
wxLayoutObjectText *tobj = (wxLayoutObjectText *)*i;
shorter = tobj->GetLength() - breakpos;
// remember text to copy from this object
prependText = tobj->GetText().Mid(breakpos+1);
tobj->SetText(tobj->GetText().Left(breakpos));
// copy every following object:
copyObject = i; copyObject ++;
}
// make sure there is an empty m_Next line:
(void) new wxLayoutLine(this, llist);
wxASSERT(m_Next);
// We need to move this and all following objects to the next
// line. Starting from the end of line, to keep the order right.
if(copyObject != NULLIT)
{
wxLOiterator j;
for(j = m_ObjectList.tail(); j != copyObject; j--)
m_Next->Prepend(*j);
m_Next->Prepend(*copyObject);
// and now remove them from this list:
while( copyObject != m_ObjectList.end() )
{
shorter += (**copyObject).GetLength();
m_ObjectList.remove(copyObject); // remove without deleting it
}
}
m_Length -= shorter;
if(prependText.Length() > 0)
m_Next->Insert(0, prependText);
// do we need to adjust the cursor position?
if( this == llist->GetCursorLine() && xpos >= breakpos)
{
xpos = objectCursorPos + (xpos - objectCursorPos - breakpos -
((xpos > breakpos) ? 1 : 0 ));
wxASSERT(xpos >= 0);
llist->MoveCursorTo( wxPoint( xpos, m_Next->GetLineNumber()) );
}
return TRUE; // we wrapped the line
}
void
wxLayoutLine::ReNumber(void)
{
@@ -1418,25 +1547,23 @@ wxLayoutLine::GetWrapPosition(CoordType column)
i++;
}
if(i == NULLIT) return -1; //why should this happen?
pos += (**i).GetLength();
i++;
while(i != NULLIT && (**i).GetType() != WXLO_TYPE_TEXT)
// now we are behind the one long text object and need to find the
// first space in it
for(offset = 0; offset < (**i).GetLength(); offset++)
if( isspace(((wxLayoutObjectText*)*i)->GetText().c_str()[(size_t)offset]))
{
pos += (**i).GetLength();
i++;
return pos+offset;
}
if(i == NULLIT) return -1; //this is possible, if there is only one text object
// now we are at the second text object:
pos -= (**i).GetLength();
return pos; // in front of it
pos += (**i).GetLength();
return pos;
}
#ifdef WXLAYOUT_DEBUG
void
wxLayoutLine::Debug(void)
wxLayoutLine::Debug(void) const
{
wxString tmp;
wxPoint pos = GetPosition();
WXLO_DEBUG(("Line %ld, Pos (%ld,%ld), Height %ld, BL %ld, Font: %d",
(long int) GetLineNumber(),
@@ -1445,7 +1572,9 @@ wxLayoutLine::Debug(void)
(long int) m_BaseLine,
(int) m_StyleInfo.family));
if(m_ObjectList.begin() != NULLIT)
(**m_ObjectList.begin()).Debug();
{
WXLO_DEBUG(((**m_ObjectList.begin()).DebugDump().c_str()));
}
}
#endif
@@ -1591,11 +1720,24 @@ wxLayoutList::Read(wxString &istr)
wxLayoutStyleInfo current_si = GetStyleInfo();
while(istr.Length())
{
// check for a linebreak:
wxString tmp;
tmp = istr.BeforeFirst('\n');
int type = WXLO_TYPE_INVALID;
sscanf(tmp.c_str(),"%d", &type);
if(type == WXLO_TYPE_LINEBREAK)
{
LineBreak();
istr = istr.AfterFirst('\n');
}
else
{
wxLayoutObject *obj = wxLayoutObject::Read(istr);
if(obj)
Insert(obj);
}
}
/* Now we use the current_si to restore our last font settings: */
Insert(new wxLayoutObjectCmd(current_si));
}
@@ -1746,6 +1888,7 @@ wxLayoutList::MoveCursorVertically(int n)
{
n--;
m_CursorPos.y ++;
last = m_CursorLine;
m_CursorLine = m_CursorLine->GetNextLine();
}
if(! m_CursorLine)
@@ -1983,9 +2126,10 @@ wxLayoutList::Insert(wxString const &text)
AddCursorPosToUpdateRect();
wxASSERT(m_CursorLine->GetLength() >= m_CursorPos.x);
if ( !m_CursorLine->Insert(m_CursorPos.x, text) )
return false;
m_CursorPos.x += text.Length();
m_movedCursor = true;
@@ -2076,29 +2220,22 @@ wxLayoutList::LineBreak(void)
bool
wxLayoutList::WrapLine(CoordType column)
{
if(m_CursorPos.x <= column || column < 1)
return false; // do nothing yet
else
{
CoordType xpos = m_CursorLine->GetWrapPosition(column);
if(xpos == -1)
return false; // cannot break line
//else:
CoordType newpos = m_CursorPos.x - xpos - 1;
m_CursorPos.x = xpos;
AddCursorPosToUpdateRect();
LineBreak();
Delete(1); // delete the space
m_CursorPos.x = newpos;
m_CursorLine->MarkDirty();
m_movedCursor = true;
return true;
return m_CursorLine->Wrap(column, this);
}
bool
wxLayoutList::WrapAll(CoordType column)
{
wxLayoutLine *line = m_FirstLine;
if(! line)
return FALSE;
bool rc = TRUE;
while(line && rc)
{
rc &= line->Wrap(column, this);
line = line->GetNextLine();
}
return rc;
}
bool
@@ -2262,6 +2399,9 @@ wxLayoutList::Layout(wxDC &dc, CoordType bottom, bool forceAll,
// If one line was dirty, we need to re-calculate all
// following lines, too.
bool wasDirty = forceAll;
// we need to layout until we reach at least the cursor line,
// otherwise we won't be able to scroll to it
bool cursorReached = false;
wxLayoutLine *line = m_FirstLine;
while(line)
{
@@ -2271,6 +2411,8 @@ wxLayoutList::Layout(wxDC &dc, CoordType bottom, bool forceAll,
// if any previous line was dirty, we need to layout all
// following lines:
wasDirty
// go on until we find the cursorline
|| ! cursorReached
// layout dirty lines:
|| line->IsDirty()
// always layout the cursor line toupdate the cursor
@@ -2278,6 +2420,9 @@ wxLayoutList::Layout(wxDC &dc, CoordType bottom, bool forceAll,
|| line == m_CursorLine
// or if it's the line we are asked to look for:
|| (cpos && line->GetLineNumber() == cpos->y)
// layout at least the desired region:
|| (bottom == -1 )
|| (line->GetPosition().y <= bottom)
)
{
if(line->IsDirty())
@@ -2299,17 +2444,20 @@ wxLayoutList::Layout(wxDC &dc, CoordType bottom, bool forceAll,
if ( csize )
*csize = m_CursorSize;
}
cursorReached = TRUE;
}
else
{
if(cpos && line->GetLineNumber() == cpos->y)
{
line->Layout(dc, this,
cpos,
csize, NULL, cpos->x);
cursorReached = TRUE;
}
else
line->Layout(dc, this);
// little condition to speed up redrawing:
if(bottom != -1 && line->GetPosition().y > bottom)
break;
}
}
line = line->GetNextLine();
}
@@ -2385,7 +2533,7 @@ wxLayoutList::Draw(wxDC &dc,
}
InvalidateUpdateRect();
WXLO_DEBUG(("Selection is %s : l%d,%ld/%ld,%ld",
WXLO_DEBUG(("Selection is %s : %ld,%ld/%ld,%ld",
m_Selection.m_valid ? "valid" : "invalid",
m_Selection.m_CursorA.x, m_Selection.m_CursorA.y,
m_Selection.m_CursorB.x, m_Selection.m_CursorB.y));
@@ -2522,7 +2670,8 @@ wxLayoutList::DrawCursor(wxDC &dc, bool active, wxPoint const &translate)
dc.DrawRectangle(coords.x, coords.y,
m_CursorSize.x, m_CursorSize.y);
SetUpdateRect(coords.x, coords.y);
SetUpdateRect(coords.x+m_CursorSize.x, coords.y+m_CursorSize.y);
SetUpdateRect(coords.x+m_CursorSize.x,
coords.y+m_CursorSize.y);
}
else
{
@@ -2883,7 +3032,7 @@ wxLayoutList::GetSelection(wxLayoutDataObject *wxlo, bool invalidate)
while((exp = wxLayoutExport( &status, WXLO_EXPORT_AS_OBJECTS)) != NULL)
{
if(exp->type == WXLO_EXPORT_EMPTYLINE)
; //FIXME missing support for linebreaks in string format
string << (int) WXLO_TYPE_LINEBREAK << '\n';
else
exp->content.object->Write(string);
delete exp;

View File

@@ -1,7 +1,7 @@
/*-*- c++ -*-********************************************************
* wxLayoutList.h - a formatted text rendering engine for wxWindows *
* *
* (C) 1999 by Karsten Ball<6C>der (ballueder@gmx.net) *
* (C) 1999-2000 by Karsten Ball<6C>der (ballueder@gmx.net) *
* *
* $Id$
*******************************************************************/
@@ -38,17 +38,38 @@
# define WXLAYOUT_USE_CARET 1
#endif // __WXMSW__
// do not enable debug mode within Mahogany
#if defined(__WXDEBUG__) && ! defined(M_BASEDIR)
// do not enable debug mode within Mahogany unless in debug mode
#if defined(__WXDEBUG__) && (( ! defined(M_BASEDIR) )|| defined(DEBUG))
# define WXLAYOUT_DEBUG
#endif
#ifdef WXLAYOUT_DEBUG
# define WXLO_TRACE(x) wxLogDebug(x)
// activate profiling: # define WXLO_PROFILE
#else
# define WXLO_TRACE(x)
#endif
/* Some profiling code: */
#if defined (WXLO_PROFILE)
#include <sys/time.h>
#include <unistd.h>
# define WXLO_TIMER_DEFINE(x) static struct timeval x
# define WXLO_TIMER_START(x) gettimeofday(&x,NULL)
# define WXLO_TIMER_STOP(x) { struct timeval y; \
gettimeofday(&y,NULL); \
x.tv_sec -= y.tv_sec; x.tv_usec -= y.tv_usec; }
# define WXLO_TIMER_PRINT(x) wxLogDebug("Timer " #x " elapsed: %ld", \
(long)(x.tv_sec * -1000 - x.tv_usec));
#else
# define WXLO_TIMER_DEFINE(x)
# define WXLO_TIMER_START(x)
# define WXLO_TIMER_STOP(x)
# define WXLO_TIMER_PRINT(x)
#endif
#define WXLO_DEBUG_URECT 0
#ifndef WXLO_DEFAULTFONTSIZE
@@ -71,7 +92,9 @@ enum wxLayoutObjectType
/// command object, containing font or colour changes
WXLO_TYPE_CMD,
/// icon object, any kind of image
WXLO_TYPE_ICON
WXLO_TYPE_ICON,
/// a linebreak, does not exist as an object
WXLO_TYPE_LINEBREAK
};
/// Type used for coordinates in drawing. Must be signed.
@@ -171,7 +194,7 @@ public:
virtual ~wxLayoutObject() { if(m_UserData) m_UserData->DecRef(); }
#ifdef WXLAYOUT_DEBUG
virtual void Debug(void);
virtual wxString DebugDump(void) const;
#endif
/** Tells the object about some user data. This data is associated
@@ -266,7 +289,7 @@ public:
static wxLayoutObjectText *Read(wxString &istr);
#ifdef WXLAYOUT_DEBUG
virtual void Debug(void);
virtual wxString DebugDump(void) const;
#endif
virtual CoordType GetLength(void) const { return strlen(m_Text.c_str()); }
@@ -475,11 +498,18 @@ public:
void Append(wxLayoutObject * obj)
{
wxASSERT(obj);
m_ObjectList.push_back(obj);
m_Length += obj->GetLength();
}
/** This function prepends an object to the line. */
void Prepend(wxLayoutObject * obj)
{
wxASSERT(obj);
m_ObjectList.push_front(obj);
m_Length += obj->GetLength();
}
/** This function appens the next line to this, i.e. joins the two
lines into one.
*/
@@ -498,6 +528,13 @@ public:
*/
wxLayoutLine *Break(CoordType xpos, wxLayoutList *llist);
/** This function wraps the line: breaks it at a suitable point
and merges it with the next.
@param wrapmargin
@return TRUE if broken
*/
bool Wrap(CoordType wrapmargin, wxLayoutList *llist);
/** Deletes the next word from this position, including leading
whitespace.
This function does not delete over font changes, i.e. a word
@@ -662,7 +699,7 @@ public:
CoordType to = -1);
#ifdef WXLAYOUT_DEBUG
void Debug(void);
void Debug(void) const;
#endif
wxLayoutStyleInfo const & GetStyleInfo() const { return m_StyleInfo; }
@@ -680,6 +717,7 @@ public:
}
m_Dirty = true;
if(m_Next) m_Next->MarkDirty();
}
/// Reset the dirty flag
void MarkClean() { m_Dirty = false; m_updateLeft = -1; }
@@ -815,6 +853,7 @@ public:
/// Returns current cursor position.
const wxPoint &GetCursorPos(wxDC &dc) const { return m_CursorPos; }
const wxPoint &GetCursorPos() const { return m_CursorPos; }
wxLayoutLine * GetCursorLine(void) { return m_CursorLine; }
/// move cursor to the end of text
void MoveCursorToEnd(void)
@@ -845,6 +884,12 @@ public:
@return true if line got broken
*/
bool WrapLine(CoordType column);
/** Wraps the complete buffer.
@param column the break position for the line, maximum length
@return true if line got broken
*/
bool WrapAll(CoordType column);
/** This function deletes npos cursor positions.
@param npos how many positions
@return true if everything got deleted
@@ -1142,7 +1187,8 @@ public:
/// get the line by number
wxLayoutLine *GetLine(CoordType index) const;
/** Reads objects from a string and inserts them.
/** Reads objects from a string and inserts them. Returns NULL if
string is empty or a linebreak was found.
@param istr stream to read from, will bee changed
*/
void Read(wxString &istr);

View File

@@ -1,7 +1,7 @@
/*-*- c++ -*-********************************************************
* wxLwindow.h : a scrolled Window for displaying/entering rich text*
* *
* (C) 1998, 1999 by Karsten Ball<6C>der (karsten@phy.hw.ac.uk) *
* (C) 1998-2000 by Karsten Ball<6C>der (ballueder@gmx.net) *
* *
* $Id$
*******************************************************************/
@@ -56,6 +56,7 @@
#include <ctype.h>
// ----------------------------------------------------------------------------
// macros
// ----------------------------------------------------------------------------
@@ -66,6 +67,13 @@
# 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
// ----------------------------------------------------------------------------
@@ -160,6 +168,7 @@ wxLayoutWindow::wxLayoutWindow(wxWindow *parent)
#ifndef __WXMSW__
m_FocusFollowMode = false;
#endif
SetWordWrap(false);
SetWrapMargin(0);
// no scrollbars initially
@@ -230,10 +239,11 @@ wxLayoutWindow::OnMouse(int eventId, wxMouseEvent& event)
{
wxClientDC dc( this );
PrepareDC( dc );
if ( eventId != WXLOWIN_MENU_MOUSEMOVE
if ( (eventId != WXLOWIN_MENU_MOUSEMOVE
#ifndef __WXMSW__
|| m_FocusFollowMode
#endif
) && (wxWindow::FindFocus() != this)
)
SetFocus();
@@ -479,6 +489,7 @@ wxLayoutWindow::OnChar(wxKeyEvent& event)
bool deletedSelection = false;
// pressing any non-arrow key optionally replaces the selection:
if(m_AutoDeleteSelection
&& IsEditable()
&& !m_Selecting
&& m_llist->HasSelection()
&& ! IsDirectionKey(keyCode)
@@ -635,10 +646,21 @@ wxLayoutWindow::OnChar(wxKeyEvent& event)
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?
@@ -688,7 +710,9 @@ wxLayoutWindow::OnChar(wxKeyEvent& event)
}
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();
@@ -713,15 +737,11 @@ wxLayoutWindow::OnChar(wxKeyEvent& event)
&& (keyCode < 256 && keyCode >= 32)
)
{
if(m_WrapMargin > 0 && isspace(keyCode))
{
bool wrapped = m_llist->WrapLine(m_WrapMargin);
// don<6F>t insert space as first thing in line
// after wrapping:
if(! wrapped || m_llist->GetCursorPos().x != 0)
m_llist->Insert((char)keyCode);
}
else
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();
}
@@ -765,7 +785,10 @@ wxLayoutWindow::ScrollToCursor(void)
{
//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;
@@ -836,6 +859,7 @@ wxLayoutWindow::RequestUpdate(const wxRect *updateRect)
void
wxLayoutWindow::InternalPaint(const wxRect *updateRect)
{
wxPaintDC dc( this );
PrepareDC( dc );
@@ -864,9 +888,9 @@ wxLayoutWindow::InternalPaint(const wxRect *updateRect)
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)
@@ -887,6 +911,7 @@ wxLayoutWindow::InternalPaint(const wxRect *updateRect)
0,wxTRANSPARENT));
m_memDC->SetLogicalFunction(wxCOPY);
m_memDC->Clear();
WXLO_TIMER_STOP(TmpTimer);
// fill the background with the background bitmap
if(m_BGbitmap)
@@ -922,7 +947,7 @@ wxLayoutWindow::InternalPaint(const wxRect *updateRect)
// 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,
@@ -930,6 +955,7 @@ wxLayoutWindow::InternalPaint(const wxRect *updateRect)
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
@@ -955,6 +981,8 @@ wxLayoutWindow::InternalPaint(const wxRect *updateRect)
// 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
@@ -979,6 +1007,10 @@ wxLayoutWindow::InternalPaint(const wxRect *updateRect)
m_StatusBar->SetStatusText(label, m_StatusFieldCursor);
}
}
WXLO_TIMER_PRINT(LayoutTimer);
WXLO_TIMER_PRINT(BlitTimer);
WXLO_TIMER_PRINT(TmpTimer);
}
void
@@ -999,14 +1031,20 @@ as needed.
void
wxLayoutWindow::ResizeScrollbars(bool exact)
{
if(! IsDirty())
return;
wxClientDC dc( this );
PrepareDC( dc );
// m_llist->ForceTotalLayout();
m_llist->Layout(dc);
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;
}
WXLO_TIMER_START(LayoutTimer);
m_llist->Layout(dc, -1);
WXLO_TIMER_STOP(LayoutTimer);
ResetDirty();
wxPoint max = m_llist->GetSize();
@@ -1025,8 +1063,8 @@ wxLayoutWindow::ResizeScrollbars(bool exact)
// 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
@@ -1038,29 +1076,34 @@ wxLayoutWindow::ResizeScrollbars(bool exact)
}
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);
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;

View File

@@ -1,7 +1,7 @@
/*-*- c++ -*-********************************************************
* wxLwindow.h : a scrolled Window for displaying/entering rich text*
* *
* (C) 1998-1999 by Karsten Ball<6C>der (karsten@phy.hw.ac.uk) *
* (C) 1998-2000 by Karsten Ball<6C>der (ballueder@gmx.net) *
* *
* $Id$
*******************************************************************/
@@ -118,6 +118,11 @@ public:
*/
void SetWrapMargin(CoordType margin) { m_WrapMargin = margin; }
/** Toggle wordwrap as we type.
@param on true to activate word wrap
*/
void SetWordWrap(bool on = true) { m_DoWordWrap = on; }
/** Redraws the window.
Internally, this stores the parameter and calls a refresh on
wxMSW, draws directly on wxGTK.
@@ -230,6 +235,10 @@ protected:
int m_maxx;
int m_maxy;
int m_lineHeight;
/// do we want automatic word wrap?
bool m_DoWordWrap;
/// wrap margin
CoordType m_WrapMargin;
/// do we have the corresponding scrollbar?
bool m_hasHScrollbar,
@@ -253,8 +262,6 @@ private:
bool m_Editable;
/// Are we currently building a selection with the keyboard?
bool m_Selecting;
/// wrap margin
CoordType m_WrapMargin;
/// Has list changed since last redraw, e.g. in size?
bool m_Dirty;
/// Has the list ever been modified?