MSW fixes for wxLayout, part II: now breaking and merging line works too.

Scrolling still doesn't :-(


git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@2662 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin 1999-06-03 22:36:01 +00:00
parent 239bca2e6d
commit bcf4a975e4
6 changed files with 270 additions and 160 deletions

View File

@ -38,7 +38,7 @@ IMPLEMENT_APP(MyApp)
ID_PRINT_SETUP_PS, ID_PAGE_SETUP_PS,ID_PREVIEW_PS,
ID_WRAP, ID_NOWRAP, ID_PASTE, ID_COPY, ID_CUT, ID_FIND,
ID_WXLAYOUT_DEBUG, ID_QUIT, ID_CLICK, ID_HTML, ID_TEXT,
ID_TEST, ID_LONG_TEST };
ID_TEST, ID_LINEBREAKS_TEST, ID_LONG_TEST, ID_URL_TEST };
IMPLEMENT_DYNAMIC_CLASS( MyFrame, wxFrame )
@ -59,7 +59,8 @@ IMPLEMENT_DYNAMIC_CLASS( MyFrame, wxFrame )
MyFrame::MyFrame(void) :
wxFrame( (wxFrame *) NULL, -1, (char *) "wxLayout", wxPoint(20,20), wxSize(600,360) )
wxFrame( (wxFrame *) NULL, -1, "wxLayout",
wxPoint(880,100), wxSize(256,256) )
{
CreateStatusBar( 2 );
@ -80,24 +81,27 @@ MyFrame::MyFrame(void) :
file_menu->Append(ID_PREVIEW_PS, "Print Preview PostScript", "Preview (PostScript)");
#endif
file_menu->AppendSeparator();
file_menu->Append( ID_TEXT, "Export Text");
file_menu->Append( ID_HTML, "Export HTML");
file_menu->Append( ID_QUIT, "Exit");
menu_bar->Append(file_menu, "File" );
file_menu->Append( ID_TEXT, "Export &Text");
file_menu->Append( ID_HTML, "Export &HTML");
file_menu->Append( ID_QUIT, "E&xit");
menu_bar->Append(file_menu, "&File" );
wxMenu *edit_menu = new wxMenu;
edit_menu->Append( ID_CLEAR, "Clear");
edit_menu->Append( ID_ADD_SAMPLE, "Example");
edit_menu->Append( ID_LONG_TEST, "Add many lines");
edit_menu->Append( ID_CLEAR, "C&lear");
edit_menu->Append( ID_ADD_SAMPLE, "&Example");
edit_menu->Append( ID_LONG_TEST, "Add &many lines");
edit_menu->AppendSeparator();
edit_menu->Append(ID_WRAP, "Wrap mode", "Activate wrapping at pixel 200.");
edit_menu->Append(ID_NOWRAP, "No-wrap mode", "Deactivate wrapping.");
edit_menu->Append( ID_LINEBREAKS_TEST, "Add &several lines");
edit_menu->Append( ID_URL_TEST, "Insert an &URL");
edit_menu->AppendSeparator();
edit_menu->Append(ID_COPY, "Copy", "Copy text to clipboard.");
edit_menu->Append(ID_CUT, "Cut", "Cut text to clipboard.");
edit_menu->Append(ID_PASTE,"Paste", "Paste text from clipboard.");
edit_menu->Append(ID_FIND, "Find", "Find text.");
menu_bar->Append(edit_menu, "Edit" );
edit_menu->Append(ID_WRAP, "&Wrap mode", "Activate wrapping at pixel 200.");
edit_menu->Append(ID_NOWRAP, "&No-wrap mode", "Deactivate wrapping.");
edit_menu->AppendSeparator();
edit_menu->Append(ID_COPY, "&Copy", "Copy text to clipboard.");
edit_menu->Append(ID_CUT, "Cu&t", "Cut text to clipboard.");
edit_menu->Append(ID_PASTE,"&Paste", "Paste text from clipboard.");
edit_menu->Append(ID_FIND, "&Find", "Find text.");
menu_bar->Append(edit_menu, "&Edit" );
#ifndef __WXMSW__
menu_bar->Show( TRUE );
@ -191,8 +195,7 @@ MyFrame::AddSampleText(wxLayoutList *llist)
fgets(buffer,1024,in);
if(feof(in))
break;
llist->Insert(buffer);
llist->LineBreak();
wxLayoutImportText(llist, buffer);
}
}
llist->MoveCursorTo(wxPoint(0,0));
@ -300,6 +303,19 @@ void MyFrame::OnCommand( wxCommandEvent &event )
m_lwin->Refresh();
break;
}
case ID_LINEBREAKS_TEST:
wxLayoutImportText(m_lwin->GetLayoutList(),
"This is a text\n"
"with embedded line\n"
"breaks.\n");
break;
case ID_URL_TEST:
// VZ: this doesn't work, of course, but I think it should -
// wxLayoutWindow should have a flag m_highlightUrls and do it itself
// (instead of doing it manually like M does now)
m_lwin->GetLayoutList()->Insert("http://www.wxwindows.org/");
}
};

View File

@ -75,7 +75,7 @@
// waste time looking for it right now. Search for occurences of
// MSW_CORRECTION to find all the places where I did it.
#ifdef __WXMSW__
static const int MSW_CORRECTION = 10;
static const int MSW_CORRECTION = 5;
#else
static const int MSW_CORRECTION = 0;
#endif
@ -278,10 +278,16 @@ wxLayoutObjectText::Layout(wxDC &dc, class wxLayoutList *llist)
{
long descent = 0l;
// now this is done in wxLayoutLine::Layout(), but this code might be
// reenabled later - in principle, it's more efficient
#if 0
CoordType widthOld = m_Width,
heightOld = m_Height;
#endif // 0
dc.GetTextExtent(m_Text, &m_Width, &m_Height, &descent);
#if 0
if ( widthOld != m_Width || heightOld != m_Height )
{
// as the text length changed, it must be refreshed
@ -302,6 +308,7 @@ wxLayoutObjectText::Layout(wxDC &dc, class wxLayoutList *llist)
llist->SetUpdateRect(position.x + widthOld + MSW_CORRECTION,
position.y + heightOld + MSW_CORRECTION);
}
#endif // 0
m_Bottom = descent;
m_Top = m_Height - m_Bottom;
@ -582,7 +589,7 @@ wxLayoutLine::wxLayoutLine(wxLayoutLine *prev, wxLayoutList *llist)
m_LineNumber = 0;
m_Width = m_Height = 0;
m_Length = 0;
m_Dirty = true;
MarkDirty(0);
m_Previous = prev;
m_Next = NULL;
RecalculatePosition(llist);
@ -610,6 +617,8 @@ wxLayoutLine::RecalculatePosition(wxLayoutList *llist)
{
wxASSERT(m_Previous || GetLineNumber() == 0);
wxPoint posOld(m_Position);
if(m_Previous)
{
m_Position = m_Previous->GetPosition();
@ -617,7 +626,18 @@ wxLayoutLine::RecalculatePosition(wxLayoutList *llist)
}
else
m_Position = wxPoint(0,0);
llist->SetUpdateRect(m_Position);
if ( m_Position != posOld )
{
// the whole line moved and must be repainted
llist->SetUpdateRect(m_Position);
llist->SetUpdateRect(m_Position.x + GetWidth() + MSW_CORRECTION,
m_Position.y + GetHeight() + MSW_CORRECTION);
llist->SetUpdateRect(posOld);
llist->SetUpdateRect(posOld.x + GetWidth() + MSW_CORRECTION,
posOld.y + GetHeight() + MSW_CORRECTION);
}
return m_Position;
}
@ -740,11 +760,8 @@ wxLayoutLine::Insert(CoordType xpos, wxLayoutObject *obj)
wxASSERT(xpos >= 0);
wxASSERT(obj != NULL);
// in any case, the object is going to belong to this line
obj->AttachToLine(this);
MarkDirty(xpos);
//FIXME: this could be optimised, for now be prudent:
m_Dirty = true;
CoordType offset;
wxLOiterator i = FindObject(xpos, &offset);
if(i == NULLIT)
@ -796,11 +813,12 @@ wxLayoutLine::Insert(CoordType xpos, wxLayoutObject *obj)
}
bool
wxLayoutLine::Insert(CoordType xpos, wxString text)
wxLayoutLine::Insert(CoordType xpos, const wxString& text)
{
wxASSERT(xpos >= 0);
//FIXME: this could be optimised, for now be prudent:
m_Dirty = true;
MarkDirty(xpos);
CoordType offset;
wxLOiterator i = FindObject(xpos, &offset);
if(i != NULLIT && (**i).GetType() == WXLO_TYPE_TEXT)
@ -808,11 +826,14 @@ wxLayoutLine::Insert(CoordType xpos, wxString text)
wxLayoutObjectText *tobj = (wxLayoutObjectText *) *i;
tobj->GetText().insert(offset, text);
m_Length += text.Length();
return true;
}
else
return Insert(xpos, new wxLayoutObjectText(text));
{
if ( !Insert(xpos, new wxLayoutObjectText(text)) )
return false;
}
return true;
}
CoordType
@ -822,8 +843,7 @@ wxLayoutLine::Delete(CoordType xpos, CoordType npos)
wxASSERT(xpos >= 0);
wxASSERT(npos >= 0);
//FIXME: this could be optimised, for now be prudent:
m_Dirty = true;
MarkDirty(xpos);
wxLOiterator i = FindObject(xpos, &offset);
while(npos > 0)
{
@ -878,8 +898,7 @@ wxLayoutLine::DeleteWord(CoordType xpos)
{
wxASSERT(xpos >= 0);
CoordType offset;
//FIXME: this could be optimised, for now be prudent:
m_Dirty = true;
MarkDirty(xpos);
wxLOiterator i = FindObject(xpos, &offset);
@ -984,23 +1003,29 @@ wxLayoutLine::Layout(wxDC &dc,
{
wxLayoutObjectList::iterator i;
// when a line becomes dirty, we redraw it from the place where it was
// changed till the end of line (because the following wxLayoutObjects are
// moved when the preceding one changes) - calculate the update rectangle.
CoordType updateTop = m_Position.y,
updateLeft = -1,
updateWidth = m_Width,
updateHeight = m_Height;
CoordType
oldWidth = m_Width,
oldHeight = m_Height;
topHeight = 0,
bottomHeight = 0; // above and below baseline
CoordType
topHeight, bottomHeight; // above and below baseline
CoordType
objHeight = 0,
objTopHeight, objBottomHeight;
objTopHeight, objBottomHeight; // above and below baseline
CoordType
len, count = 0;
m_Height = 0; m_BaseLine = 0;
m_Width = 0;
topHeight = 0; bottomHeight = 0;
wxPoint size;
bool cursorFound = false;
m_Dirty = false;
CoordType heightOld = m_Height;
m_Height = 0;
m_Width = 0;
m_BaseLine = 0;
bool cursorFound = false;
if(cursorPos)
{
@ -1013,15 +1038,17 @@ wxLayoutLine::Layout(wxDC &dc,
//llist->ApplyStyle(&m_StyleInfo, dc);
for(i = m_ObjectList.begin(); i != NULLIT; i++)
{
(**i).Layout(dc, llist);
size = (**i).GetSize(&objTopHeight, &objBottomHeight);
wxLayoutObject *obj = *i;
obj->Layout(dc, llist);
wxPoint sizeObj = obj->GetSize(&objTopHeight, &objBottomHeight);
if(cursorPos && ! cursorFound)
{ // we need to check whether the text cursor is here
len = (**i).GetLength();
{
// we need to check whether the text cursor is here
len = obj->GetLength();
if(count <= cx && count+len > cx)
{
if((**i).GetType() == WXLO_TYPE_TEXT)
if(obj->GetType() == WXLO_TYPE_TEXT)
{
len = cx - count; // pos in object
CoordType width, height, descent;
@ -1030,7 +1057,7 @@ wxLayoutLine::Layout(wxDC &dc,
cursorPos->x += width;
cursorPos->y = m_Position.y;
wxString str;
if(len < (**i).GetLength())
if(len < obj->GetLength())
str = (*(wxLayoutObjectText*)*i).GetText().substr(len,1);
else
str = WXLO_CURSORCHAR;
@ -1038,15 +1065,16 @@ wxLayoutLine::Layout(wxDC &dc,
wxASSERT(cursorSize);
// Just in case some joker inserted an empty string object:
if(width == 0) width = WXLO_MINIMUM_CURSOR_WIDTH;
if(height == 0) height = objHeight;
if(height == 0) height = sizeObj.y;
cursorSize->x = width;
cursorSize->y = height;
cursorFound = true; // no more checks
}
else
{ // on some other object
{
// on some other object
CoordType top, bottom; // unused
*cursorSize = (**i).GetSize(&top,&bottom);
*cursorSize = obj->GetSize(&top,&bottom);
cursorPos->y = m_Position.y;
cursorFound = true; // no more checks
}
@ -1054,28 +1082,43 @@ wxLayoutLine::Layout(wxDC &dc,
else
{
count += len;
cursorPos->x += (**i).GetWidth();
cursorPos->x += obj->GetWidth();
}
} // cursor finding
objHeight = size.y;
m_Width += size.x;
if(objHeight > m_Height) m_Height = objHeight;
if(objTopHeight > topHeight) topHeight = objTopHeight;
if(objBottomHeight > bottomHeight) bottomHeight = objBottomHeight;
m_Width += sizeObj.x;
if(sizeObj.y > m_Height)
{
m_Height = sizeObj.y;
}
if(objTopHeight > topHeight)
topHeight = objTopHeight;
if(objBottomHeight > bottomHeight)
bottomHeight = objBottomHeight;
}
// special case of a line which becomes empty (after deletion, for example):
// we should invalidate the screen space it occupied (usually this happens
// from wxLayoutObject::Layout called in the loop above)
if ( m_ObjectList.empty() )
if ( IsDirty() )
{
wxPoint position(GetPosition());
llist->SetUpdateRect(position.x + oldWidth + MSW_CORRECTION,
position.y + oldHeight + MSW_CORRECTION);
if ( updateHeight < m_Height )
updateHeight = m_Height;
if ( updateWidth < m_Width )
updateWidth = m_Width;
// update all line if we don't know where to start from
if ( updateLeft == -1 )
updateLeft = 0;
llist->SetUpdateRect(updateLeft, updateTop);
llist->SetUpdateRect(updateLeft + updateWidth + MSW_CORRECTION,
updateTop + updateHeight + MSW_CORRECTION);
}
if(topHeight + bottomHeight > m_Height)
{
m_Height = topHeight+bottomHeight;
}
m_BaseLine = topHeight;
if(m_Height == 0)
@ -1086,10 +1129,12 @@ wxLayoutLine::Layout(wxDC &dc,
m_BaseLine = m_Height - descent;
}
// tell next line about coordinate change
if(m_Next && objHeight != oldHeight)
if(m_Next && m_Height != heightOld)
{
// FIXME isn't this done in RecalculatePositions() below anyhow?
m_Next->RecalculatePositions(0, llist);
}
// We need to check whether we found a valid cursor size:
if(cursorPos)
@ -1106,7 +1151,10 @@ wxLayoutLine::Layout(wxDC &dc,
if(m_BaseLine >= cursorSize->y) // the normal case anyway
cursorPos->y += m_BaseLine-cursorSize->y;
}
RecalculatePositions(1, llist);
MarkClean();
}
@ -1114,8 +1162,8 @@ wxLayoutLine *
wxLayoutLine::Break(CoordType xpos, wxLayoutList *llist)
{
wxASSERT(xpos >= 0);
//FIXME: this could be optimised, for now be prudent:
m_Dirty = true;
MarkDirty(xpos);
/* If we are at the begin of a line, we want to move all other
lines down and stay with the cursor where we are. However, if we
@ -1157,13 +1205,17 @@ wxLayoutLine::Break(CoordType xpos, wxLayoutList *llist)
i++; // don't move this object to the new list
}
else
{
if(offset > 0)
i++; // move objects from here to new list
}
while(i != m_ObjectList.end())
{
newLine->Append(*i);
m_Length -= (**i).GetLength();
wxLayoutObject *obj = *i;
newLine->Append(obj);
m_Length -= obj->GetLength();
m_ObjectList.remove(i); // remove without deleting it
}
if(m_Next)
@ -1178,8 +1230,8 @@ wxLayoutLine::MergeNextLine(wxLayoutList *llist)
wxCHECK_RET(GetNextLine(),"wxLayout internal error: no next line to merge");
wxLayoutObjectList &list = GetNextLine()->m_ObjectList;
wxLOiterator i;
//FIXME: this could be optimised, for now be prudent:
m_Dirty = true;
MarkDirty(GetWidth());
wxLayoutObject *last = NULL;
for(i = list.begin(); i != list.end();)
@ -1200,7 +1252,6 @@ wxLayoutLine::MergeNextLine(wxLayoutList *llist)
else
{
// just append the object "as was"
current->UnattachFromLine();
Append(current);
list.remove(i); // remove without deleting it
@ -1211,13 +1262,24 @@ wxLayoutLine::MergeNextLine(wxLayoutList *llist)
wxLayoutLine *oldnext = GetNextLine();
wxLayoutLine *nextLine = oldnext->GetNextLine();
SetNext(nextLine);
delete oldnext;
if ( nextLine )
{
nextLine->MoveLines(-1);
}
else
{
// this is now done in Delete(), but if this function is ever called
// from elsewhere, we might have to move refresh code back here (in
// order not to duplicate it)
#if 0
wxPoint pos(oldnext->GetPosition());
llist->SetUpdateRect(pos);
llist->SetUpdateRect(pos.x + oldnext->GetWidth() + MSW_CORRECTION,
pos.y + oldnext->GetHeight() + MSW_CORRECTION);
#endif // 0
}
// no RecalculatePositions needed - called from Delete() anyhow
delete oldnext;
}
CoordType
@ -1613,12 +1675,20 @@ bool
wxLayoutList::Insert(wxString const &text)
{
wxASSERT(m_CursorLine);
wxASSERT_MSG( text.Find('\n') == wxNOT_FOUND, "use wxLayoutImportText!" );
if ( !text )
return true;
AddCursorPosToUpdateRect();
m_CursorLine->Insert(m_CursorPos.x, text);
if ( !m_CursorLine->Insert(m_CursorPos.x, text) )
return false;
m_CursorPos.x += text.Length();
m_CursorLine->RecalculatePositions(true, this); //FIXME needed?
m_CursorLine->RecalculatePositions(0, this);
return true;
}
@ -1634,7 +1704,9 @@ wxLayoutList::Insert(wxLayoutObject *obj)
m_CursorLine->Insert(m_CursorPos.x, obj);
m_CursorPos.x += obj->GetLength();
m_CursorLine->RecalculatePositions(true, this); //FIXME needed?
m_CursorLine->RecalculatePositions(0, this);
return true;
}
@ -1710,7 +1782,9 @@ wxLayoutList::WrapLine(CoordType column)
LineBreak();
Delete(1); // delete the space
m_CursorPos.x = newpos;
m_CursorLine->RecalculatePositions(true, this); //FIXME needed?
m_CursorLine->RecalculatePositions(1, this);
return true;
}
}
@ -1762,9 +1836,19 @@ wxLayoutList::Delete(CoordType npos)
wasMerged = true;
wxLayoutLine *next = m_CursorLine->GetNextLine();
if ( next )
{
totalHeight += next->GetHeight();
m_CursorLine->MergeNextLine(this);
left--;
totalWidth += next->GetWidth();
m_CursorLine->MergeNextLine(this);
left--;
}
else
{
wxFAIL_MSG("can't delete all this");
return false;
}
}
}
}
@ -1776,6 +1860,7 @@ wxLayoutList::Delete(CoordType npos)
if ( wasMerged )
{
wxPoint position(m_CursorLine->GetPosition());
SetUpdateRect(position);
SetUpdateRect(position.x + totalWidth + MSW_CORRECTION,
position.y + totalHeight + MSW_CORRECTION);
}
@ -1850,11 +1935,13 @@ wxLayoutList::GetCursorScreenPos(wxDC &dc)
void
wxLayoutList::Layout(wxDC &dc, CoordType bottom, bool forceAll)
{
wxLayoutLine *line = m_FirstLine;
// first, make sure everything is calculated - this might not be
// needed, optimise it later
ApplyStyle(&m_DefaultSetting, dc);
// FIXME this is completely wrong - we should start by first *visible* line
// (and stop on the last one) instead of looping over all lines!!
wxLayoutLine *line = m_FirstLine;
while(line)
{
if(forceAll || line->IsDirty())
@ -1865,10 +1952,13 @@ wxLayoutList::Layout(wxDC &dc, CoordType bottom, bool forceAll)
(wxPoint *)&m_CursorSize, m_CursorPos.x);
else
line->Layout(dc, this);
// little condition to speed up redrawing:
if(bottom != -1 && line->GetPosition().y > bottom) break;
// little condition to speed up redrawing:
if(bottom != -1 && line->GetPosition().y > bottom)
break;
}
line->RecalculatePositions(1,this);
line->RecalculatePositions(1, this);
line = line->GetNextLine();
}
@ -1924,14 +2014,22 @@ wxLayoutList::FindObjectScreen(wxDC &dc, wxPoint const pos,
wxLayoutLine *line = m_FirstLine;
wxPoint p;
// we need to run a layout here to get font sizes right :-(
ApplyStyle(&m_DefaultSetting, dc);
while(line)
{
p = line->GetPosition();
if(p.y <= pos.y && p.y+line->GetHeight() >= pos.y)
break;
#if 0
// we need to run a layout here to get font sizes right :-(
// VZ: we can't call Layout() from here because it marks the line as
// clean and it is not refreshed when it's called from wxLayoutList::
// Layout() - if we really need to do this, we should introduce an
// extra argument to Layout() to prevent the line from MarkClean()ing
// itself here
line->Layout(dc, this);
#endif
line = line->GetNextLine();
}
if(line == NULL)

View File

@ -162,7 +162,7 @@ public:
virtual CoordType GetOffsetScreen(wxDC &dc, CoordType xpos) const { return 0; }
/// constructor
wxLayoutObject() { m_UserData = NULL; m_Line = NULL; }
wxLayoutObject() { m_UserData = NULL; }
/// delete the user data
virtual ~wxLayoutObject() { if(m_UserData) m_UserData->DecRef(); }
@ -183,20 +183,6 @@ public:
m_UserData->IncRef();
}
/// returns the line we belong to (or NULL)
wxLayoutLine *GetLine() const { return m_Line; }
/// attaches this object to the given line, it's an error to reattach us
void AttachToLine(wxLayoutLine *line)
{
wxASSERT_MSG( !m_Line, "this layout object already belongs to a line" );
m_Line = line;
}
/// unattaches the object (should reattach it immediately afterwards!)
void UnattachFromLine() { if ( m_Line ) m_Line = (wxLayoutLine *)NULL; }
/** Return the user data.
Increments the object's reference count. When no longer needed,
caller must call DecRef() on the pointer returned.
@ -221,9 +207,6 @@ public:
protected:
/// optional data for application's use
UserData *m_UserData;
/// the line of the text we belong to or NULL if we're not shown on screen
wxLayoutLine *m_Line;
};
/// Define a list type of wxLayoutObject pointers.
@ -472,7 +455,7 @@ public:
@param text the text to insert
@return true if that xpos existed and the object was inserted
*/
bool Insert(CoordType xpos, wxString text);
bool Insert(CoordType xpos, const wxString& text);
/** This function appends an object to the line.
@param obj the object to insert
@ -481,7 +464,6 @@ public:
{
wxASSERT(obj);
obj->AttachToLine(this);
m_ObjectList.push_back(obj);
m_Length += obj->GetLength();
}
@ -665,7 +647,19 @@ public:
/// Returns dirty state
bool IsDirty(void) const { return m_Dirty; }
/// Marks line as diry.
void MarkDirty(void) { m_Dirty = true; }
void MarkDirty(CoordType left = -1)
{
if ( left != -1 )
{
if ( m_updateLeft == -1 || left < m_updateLeft )
m_updateLeft = left;
}
m_Dirty = true;
}
/// Reset the dirty flag
void MarkClean() { m_Dirty = false; m_updateLeft = -1; }
private:
/// Destructor is private. Use DeleteLine() to remove it.
~wxLayoutLine();
@ -706,6 +700,8 @@ private:
wxLayoutObjectList m_ObjectList;
/// Have we been changed since the last layout?
bool m_Dirty;
/// The coordinate of the left boundary of the update rectangle (if m_Dirty)
CoordType m_updateLeft;
/// Pointer to previous line if it exists.
wxLayoutLine *m_Previous;
/// Pointer to next line if it exists.

View File

@ -28,29 +28,30 @@
#define BASE_SIZE 12
inline static bool IsEndOfLine(const char *p, int mode)
inline static bool IsEndOfLine(const char *p)
{
// in addition to Unix EOL convention we also (but not instead) understand
// the DOS one under Windows
return
(mode == WXLO_EXPORT_WITH_CRLF) ?
((*p == '\r') && (*(p + 1) == '\n'))
:
(((*p == '\r') && (*(p + 1) == '\n'))||(*p == '\n'));
// the end of line is either just '\n' or "\r\n" - we understand both (even
// though the second is used only under DOS/Windows) to be able to import
// DOS text files even under Unix
return (*p == '\n') || ((*p == '\r') && (*(p + 1) == '\n'));
}
void wxLayoutImportText(wxLayoutList *list, wxString const &str, int withflag)
void wxLayoutImportText(wxLayoutList *list, wxString const &str)
{
if(str.Length() == 0)
if ( !str )
return;
char * cptr = (char *)str.c_str(); // string gets changed only temporarily
// we change the string temporarily inside this function
wxString& s = (wxString &)str; // const_cast
char * cptr = s.GetWriteBuf(s.Len());
const char * begin = cptr;
char backup;
for(;;)
{
begin = cptr;
while( *cptr && !IsEndOfLine(cptr, withflag) )
while( *cptr && !IsEndOfLine(cptr) )
cptr++;
backup = *cptr;
*cptr = '\0';
@ -58,7 +59,7 @@ void wxLayoutImportText(wxLayoutList *list, wxString const &str, int withflag)
*cptr = backup;
// check if it's the end of this line
if ( IsEndOfLine(cptr, withflag) )
if ( IsEndOfLine(cptr) )
{
// if it was "\r\n", skip the following '\n'
if ( *cptr == '\r' )
@ -69,6 +70,8 @@ void wxLayoutImportText(wxLayoutList *list, wxString const &str, int withflag)
break;
cptr++;
}
s.UngetWriteBuf();
}
static
@ -77,11 +80,11 @@ wxString wxLayoutExportCmdAsHTML(wxLayoutObjectCmd const & cmd,
{
static char buffer[20];
wxString html;
wxLayoutStyleInfo *si = cmd.GetStyle();
int size, sizecount;
html += "<font ";
if(si->m_fg_valid)
@ -97,7 +100,7 @@ wxString wxLayoutExportCmdAsHTML(wxLayoutObjectCmd const & cmd,
sprintf(buffer,"\"#%02X%02X%02X\"", si->m_bg.Red(),si->m_bg.Green(),si->m_bg.Blue());
html += buffer;
}
switch(si->family)
{
case wxSWISS:
@ -139,7 +142,7 @@ wxString wxLayoutExportCmdAsHTML(wxLayoutObjectCmd const & cmd,
if(si->style == wxSLANT)
si->style = wxITALIC; // the same for html
if((si->style == wxITALIC) && ( (!styleInfo) || (styleInfo->style != wxITALIC)))
html += "<i>";
else
@ -151,9 +154,9 @@ wxString wxLayoutExportCmdAsHTML(wxLayoutObjectCmd const & cmd,
else if(si->underline == false && ( styleInfo && styleInfo->underline))
html += "</u>";
*styleInfo = *si; // update last style info
return html;
}
@ -165,7 +168,7 @@ wxLayoutExportStatus::wxLayoutExportStatus(wxLayoutList *list)
m_line = list->GetFirstLine();
m_iterator = m_line->GetFirstObject();
}
#define WXLO_IS_TEXT(type) \
@ -179,7 +182,7 @@ wxLayoutExportObject *wxLayoutExport(wxLayoutExportStatus *status,
{
wxASSERT(status);
wxLayoutExportObject * export;
if(status->m_iterator == NULLIT) // end of line
{
if(!status->m_line || status->m_line->GetNextLine() == NULL)
@ -234,7 +237,7 @@ wxLayoutExportObject *wxLayoutExport(wxLayoutExportStatus *status,
break; // end of list
}
if(! status->m_line) // reached end of list, fall through
break;
break;
type = (** status->m_iterator).GetType();
if(type == WXLO_TYPE_ICON)
break;

View File

@ -18,8 +18,8 @@
enum wxLayoutExportType
{
WXLO_EXPORT_TEXT,
WXLO_EXPORT_HTML,
WXLO_EXPORT_TEXT,
WXLO_EXPORT_HTML,
WXLO_EXPORT_OBJECT,
// this can be caused by empty lines:
WXLO_EXPORT_EMPTYLINE
@ -62,24 +62,17 @@ struct wxLayoutExportStatus
};
#ifdef OS_WIN
/// import text into a wxLayoutList (including linefeeds):
void wxLayoutImportText(wxLayoutList *list, wxString const &str,
int withflag = WXLO_EXPORT_WITH_CRLF);
#define WXLO_DEFAULT_EXPORT_MODE WXLO_EXPORT_WITH_CRLF
#else // Unix
#define WXLO_DEFAULT_EXPORT_MODE WXLO_EXPORT_WITH_LF_ONLY
#endif // Win/Unix
wxLayoutExportObject *wxLayoutExport(wxLayoutExportStatus *status,
int mode = WXLO_EXPORT_AS_TEXT,
int flags =
WXLO_EXPORT_WITH_CRLF);
#else
/// import text into a wxLayoutList (including linefeeds):
void wxLayoutImportText(wxLayoutList *list, wxString const &str,
int withflag = WXLO_EXPORT_WITH_LF_ONLY);
void wxLayoutImportText(wxLayoutList *list, wxString const &str);
/// export text in a given format
wxLayoutExportObject *wxLayoutExport(wxLayoutExportStatus *status,
int mode = WXLO_EXPORT_AS_TEXT,
int flags =
WXLO_EXPORT_WITH_LF_ONLY);
#endif
int flags = WXLO_DEFAULT_EXPORT_MODE);
#endif //WXLPARSER_H

View File

@ -28,10 +28,7 @@
# include "gui/wxlparser.h"
#else
# ifdef __WXMSW__
# include <windows.h>
# undef FindWindow
# undef GetCharWidth
# undef StartDoc
# include <wx/msw/private.h>
# endif
# include "wxlwindow.h"
@ -153,9 +150,13 @@ wxLayoutWindow::MSWGetDlgCode()
void
wxLayoutWindow::OnMouse(int eventId, wxMouseEvent& event)
{
wxPaintDC dc( this );
wxClientDC dc( this );
PrepareDC( dc );
SetFocus();
if ( eventId != WXLOWIN_MENU_MOUSEMOVE )
{
// moving the mouse in a window shouldn't give it the focus!
SetFocus();
}
wxPoint findPos;
findPos.x = dc.DeviceToLogicalX(event.GetX());
@ -512,10 +513,13 @@ wxLayoutWindow::OnPaint( wxPaintEvent &WXUNUSED(event)) // or: OnDraw(wxDC& dc)
void
wxLayoutWindow::DoPaint(const wxRect *updateRect)
{
#ifdef __WXGTK__
#ifndef __WXMSW__
InternalPaint(updateRect);
#else
Refresh(FALSE, updateRect); // Causes bad flicker under wxGTK!!!
if ( !::UpdateWindow(GetHwnd()) )
wxLogLastError("UpdateWindow");
#endif
}
@ -876,12 +880,12 @@ void
wxLayoutWindow::OnSetFocus(wxFocusEvent &ev)
{
m_HaveFocus = true;
//FIXME: need argument DoPaint(); // to repaint the cursor
ev.Skip();
}
void
wxLayoutWindow::OnKillFocus(wxFocusEvent &ev)
{
m_HaveFocus = false;
//FIXME: need argument DoPaint(); // to repaint the cursor
ev.Skip();
}