From bcf4a975e4eedf899004cf629f5b61ea718e94c0 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Thu, 3 Jun 1999 22:36:01 +0000 Subject: [PATCH] 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 --- user/wxLayout/wxLayout.cpp | 52 +++++--- user/wxLayout/wxllist.cpp | 244 +++++++++++++++++++++++++----------- user/wxLayout/wxllist.h | 38 +++--- user/wxLayout/wxlparser.cpp | 49 ++++---- user/wxLayout/wxlparser.h | 23 ++-- user/wxLayout/wxlwindow.cpp | 22 ++-- 6 files changed, 269 insertions(+), 159 deletions(-) diff --git a/user/wxLayout/wxLayout.cpp b/user/wxLayout/wxLayout.cpp index 41431fbe24..75459b8f59 100644 --- a/user/wxLayout/wxLayout.cpp +++ b/user/wxLayout/wxLayout.cpp @@ -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/"); } }; diff --git a/user/wxLayout/wxllist.cpp b/user/wxLayout/wxllist.cpp index 906aead71a..f0e15342f6 100644 --- a/user/wxLayout/wxllist.cpp +++ b/user/wxLayout/wxllist.cpp @@ -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; - CoordType - topHeight, bottomHeight; // above and below baseline + topHeight = 0, + bottomHeight = 0; // 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; + + CoordType heightOld = m_Height; + + m_Height = 0; m_Width = 0; - topHeight = 0; bottomHeight = 0; - wxPoint size; - bool cursorFound = false; + m_BaseLine = 0; - m_Dirty = false; + 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) diff --git a/user/wxLayout/wxllist.h b/user/wxLayout/wxllist.h index 630596b8df..c354b2ffb3 100644 --- a/user/wxLayout/wxllist.h +++ b/user/wxLayout/wxllist.h @@ -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. diff --git a/user/wxLayout/wxlparser.cpp b/user/wxLayout/wxlparser.cpp index 3370fd5fc7..022a9c7954 100644 --- a/user/wxLayout/wxlparser.cpp +++ b/user/wxLayout/wxlparser.cpp @@ -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 += "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 += ""; else @@ -151,9 +154,9 @@ wxString wxLayoutExportCmdAsHTML(wxLayoutObjectCmd const & cmd, else if(si->underline == false && ( styleInfo && styleInfo->underline)) html += ""; - + *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; diff --git a/user/wxLayout/wxlparser.h b/user/wxLayout/wxlparser.h index 571a8749d9..a594885d08 100644 --- a/user/wxLayout/wxlparser.h +++ b/user/wxLayout/wxlparser.h @@ -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 diff --git a/user/wxLayout/wxlwindow.cpp b/user/wxLayout/wxlwindow.cpp index 093db74fa4..0cd45c2c93 100644 --- a/user/wxLayout/wxlwindow.cpp +++ b/user/wxLayout/wxlwindow.cpp @@ -28,10 +28,7 @@ # include "gui/wxlparser.h" #else # ifdef __WXMSW__ -# include -# undef FindWindow -# undef GetCharWidth -# undef StartDoc +# include # 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(); } -- 2.45.2