X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/4e16881a084fda0bb6672b71dfe3c12eaa9e6a37..9398120d298d745763f253d87d774be3b134b43f:/samples/richedit/wxllist.cpp diff --git a/samples/richedit/wxllist.cpp b/samples/richedit/wxllist.cpp index ac6046b184..3a2ff3a604 100644 --- a/samples/richedit/wxllist.cpp +++ b/samples/richedit/wxllist.cpp @@ -1,7 +1,7 @@ /*-*- c++ -*-******************************************************** * wxllist: wxLayoutList, a layout engine for text and graphics * * * - * (C) 1998-1999 by Karsten Ballüder (Ballueder@usa.net) * + * (C) 1998-2000 by Karsten Ballüder (Ballueder@gmx.net) * * * * $Id$ *******************************************************************/ @@ -25,7 +25,7 @@ # pragma implementation "wxllist.h" #endif -#include +#include "wx/wxprec.h" #ifdef __BORLANDC__ # pragma hdrstop @@ -45,7 +45,11 @@ #endif #ifndef USE_PCH -# include +#if wxUSE_IOSTREAMH + #include +#else + #include +#endif # include # include @@ -60,6 +64,7 @@ #include + /// This should never really get created #define WXLLIST_TEMPFILE "__wxllist.tmp" @@ -72,16 +77,19 @@ { "invalid", "text", "cmd", "icon" }; - void - wxLayoutObject::Debug(void) + wxString + wxLayoutObject::DebugDump(void) const { - WXLO_DEBUG(("%s",g_aTypeStrings[GetType()])); + wxString str; + str.Printf(wxT("%s"), g_aTypeStrings[GetType()]); + return str; } #else -# define TypeString(t) "" -# define WXLO_DEBUG(x) +# 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,14 +173,20 @@ bool Contains(const wxRect &r, const wxPoint &p) //@} +static void ReadString(wxString &to, wxString &from) { - to = ""; - const char *cptr = from.c_str(); - while(*cptr && *cptr != '\n') - to += *cptr++; - if(*cptr) cptr++; - from = cptr; + to = wxT(""); + const wxChar *cptr = from.c_str(); + while(*cptr && *cptr != wxT('\n')) + { + to += cptr; + cptr++; + } + + if(*cptr) cptr++; + + from = cptr; } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * @@ -185,22 +199,23 @@ void ReadString(wxString &to, wxString &from) wxLayoutObject * wxLayoutObject::Read(wxString &istr) { - wxString tmp; - ReadString(tmp, istr); - int type = -1; - sscanf(tmp.c_str(),"%d", &type); - - switch(type) - { - case WXLO_TYPE_TEXT: - return wxLayoutObjectText::Read(istr); - case WXLO_TYPE_CMD: - return wxLayoutObjectCmd::Read(istr); - case WXLO_TYPE_ICON: - return wxLayoutObjectIcon::Read(istr); - default: - return NULL; - } + wxString tmp; + ReadString(tmp, istr); + long l = WXLO_TYPE_INVALID; + tmp.ToLong(&l); + int type = (int) l; + + switch(type) + { + case WXLO_TYPE_TEXT: + return wxLayoutObjectText::Read(istr); + case WXLO_TYPE_CMD: + return wxLayoutObjectCmd::Read(istr); + case WXLO_TYPE_ICON: + return wxLayoutObjectIcon::Read(istr); + default: + return NULL; + } } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * @@ -329,6 +344,16 @@ wxLayoutObjectText::Layout(wxDC &dc, class wxLayoutList *llist) heightOld = m_Height; #endif // 0 +#ifdef __WXDEBUG__ + CoordType a,b,c,d,e,f; + dc.GetTextExtent("test ", &a, &b, &c); + dc.GetTextExtent("test", &d, &e, &f); + wxASSERT(a != d); + wxASSERT(b == e); + wxASSERT(c == f); + dc.GetTextExtent(" ", &d, &e, &f); + wxASSERT(a > 0); +#endif dc.GetTextExtent(m_Text, &m_Width, &m_Height, &descent); #if 0 @@ -360,11 +385,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(wxT(" `%s`"), m_Text.c_str()); + return str+str2; } #endif @@ -378,7 +406,7 @@ wxLayoutObjectIcon::wxLayoutObjectIcon(wxBitmap const &icon) { if ( !icon.Ok() ) { - wxFAIL_MSG("invalid icon"); + wxFAIL_MSG(wxT("invalid icon")); m_Icon = NULL; @@ -402,7 +430,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); } @@ -438,6 +466,8 @@ wxLayoutObjectIcon::Copy(void) wxLayoutObjectIcon::wxLayoutObjectIcon(wxBitmap *icon) { m_Icon = icon; + if(! m_Icon) + m_Icon = new wxBitmap; } void @@ -514,12 +544,19 @@ wxLayoutObjectCmd::wxLayoutObjectCmd(int family, int size, int style, int m_StyleInfo = new wxLayoutStyleInfo(family, size,style,weight,underline,fg,bg); } +wxLayoutObjectCmd::wxLayoutObjectCmd(const wxLayoutStyleInfo &si) + +{ + m_StyleInfo = new wxLayoutStyleInfo; + *m_StyleInfo = si; +} + wxLayoutObject * wxLayoutObjectCmd::Copy(void) { wxLayoutObjectCmd *obj = new wxLayoutObjectCmd( - m_StyleInfo->size, m_StyleInfo->family, + m_StyleInfo->size, m_StyleInfo->style, m_StyleInfo->weight, m_StyleInfo->underline, @@ -534,71 +571,101 @@ wxLayoutObjectCmd::Copy(void) void wxLayoutObjectCmd::Write(wxString &ostr) { - ostr << WXLO_TYPE_CMD << '\n' - << m_StyleInfo->size << '\n' - << m_StyleInfo->family << '\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 */ wxLayoutObjectCmd * wxLayoutObjectCmd::Read(wxString &istr) { - wxLayoutObjectCmd *obj = new wxLayoutObjectCmd; - - wxString tmp; - ReadString(tmp, istr); - sscanf(tmp.c_str(),"%d", &obj->m_StyleInfo->size); - ReadString(tmp, istr); - sscanf(tmp.c_str(),"%d", &obj->m_StyleInfo->family); - ReadString(tmp, istr); - sscanf(tmp.c_str(),"%d", &obj->m_StyleInfo->style); - ReadString(tmp, istr); - sscanf(tmp.c_str(),"%d", &obj->m_StyleInfo->weight); - ReadString(tmp, istr); - sscanf(tmp.c_str(),"%d", &obj->m_StyleInfo->underline); - ReadString(tmp, istr); - sscanf(tmp.c_str(),"%d", &obj->m_StyleInfo->m_fg_valid); - ReadString(tmp, istr); - sscanf(tmp.c_str(),"%d", &obj->m_StyleInfo->m_bg_valid); - if(obj->m_StyleInfo->m_fg_valid) - { - int red, green, blue; - ReadString(tmp, istr); - sscanf(tmp.c_str(),"%d", &red); - ReadString(tmp, istr); - sscanf(tmp.c_str(),"%d", &green); - ReadString(tmp, istr); - sscanf(tmp.c_str(),"%d", &blue); - obj->m_StyleInfo->m_fg = wxColour(red, green, blue); - } - if(obj->m_StyleInfo->m_bg_valid) - { - int red, green, blue; - ReadString(tmp, istr); - sscanf(tmp.c_str(),"%d", &red); - ReadString(tmp, istr); - sscanf(tmp.c_str(),"%d", &green); - ReadString(tmp, istr); - sscanf(tmp.c_str(),"%d", &blue); - obj->m_StyleInfo->m_bg = wxColour(red, green, blue); - } - return obj; + wxLayoutObjectCmd *obj = new wxLayoutObjectCmd; + + long l = 0; + wxString tmp; + ReadString(tmp, istr); + tmp.ToLong(&l); + obj->m_StyleInfo->family = (int) l; + + + ReadString(tmp, istr); + tmp.ToLong(&l); + obj->m_StyleInfo->size = (int) l; + + ReadString(tmp, istr); + tmp.ToLong(&l); + obj->m_StyleInfo->style = (int) l; + + ReadString(tmp, istr); + tmp.ToLong(&l); + obj->m_StyleInfo->weight = (int) l; + + ReadString(tmp, istr); + tmp.ToLong(&l); + obj->m_StyleInfo->underline = (int) l; + + ReadString(tmp, istr); + tmp.ToLong(&l); + obj->m_StyleInfo->m_fg_valid = (int) l; + + ReadString(tmp, istr); + tmp.ToLong(&l); + obj->m_StyleInfo->m_bg_valid = (int) l; + + if(obj->m_StyleInfo->m_fg_valid) + { + int red, green, blue; + ReadString(tmp, istr); + tmp.ToLong(&l); + red = (int) l; + + ReadString(tmp, istr); + tmp.ToLong(&l); + green = (int) l; + + ReadString(tmp, istr); + tmp.ToLong(&l); + blue = (int) l; + + obj->m_StyleInfo->m_fg = wxColour(red, green, blue); + } + + if(obj->m_StyleInfo->m_bg_valid) + { + int red, green, blue; + ReadString(tmp, istr); + tmp.ToLong(&l); + red = (int) l; + + ReadString(tmp, istr); + tmp.ToLong(&l); + green = (int) l; + + ReadString(tmp, istr); + tmp.ToLong(&l); + blue = (int) l; + + obj->m_StyleInfo->m_bg = wxColour(red, green, blue); + } + + return obj; } @@ -642,10 +709,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); @@ -951,49 +1017,51 @@ wxLayoutLine::Delete(CoordType xpos, CoordType npos) bool wxLayoutLine::DeleteWord(CoordType xpos) { - wxASSERT(xpos >= 0); - CoordType offset; - MarkDirty(xpos); + wxASSERT(xpos >= 0); + CoordType offset; + MarkDirty(xpos); + + wxLOiterator i = FindObject(xpos, &offset); + + for(;;) + { + if(i == NULLIT) return false; + if((**i).GetType() != WXLO_TYPE_TEXT) + { + // This should only happen when at end of line, behind a non-text + // object: + if(offset == (**i).GetLength()) return false; + m_Length -= (**i).GetLength(); // -1 + m_ObjectList.erase(i); + return true; // we are done + } + else + { // text object: + if(offset == (**i).GetLength()) // at end of object + { + i++; offset = 0; + continue; + } - wxLOiterator i = FindObject(xpos, &offset); + wxLayoutObjectText *tobj = (wxLayoutObjectText *)*i; + size_t count = 0; + wxString str = tobj->GetText(); + str = str.substr(offset,str.Length()-offset); + // Find out how many positions we need to delete: + // 1. eat leading space + while(isspace(str.c_str()[count])) count++; + // 2. eat the word itself: + while(isalnum(str.c_str()[count])) count++; + // now delete it: + wxASSERT(count+offset <= (size_t) (**i).GetLength()); + ((wxLayoutObjectText *)*i)->GetText().erase(offset,count); + m_Length -= count; - for(;;) - { - if(i == NULLIT) return false; - if((**i).GetType() != WXLO_TYPE_TEXT) - { - // This should only happen when at end of line, behind a non-text - // object: - if(offset == (**i).GetLength()) return false; - m_Length -= (**i).GetLength(); // -1 - m_ObjectList.erase(i); - return true; // we are done - } - else - { // text object: - if(offset == (**i).GetLength()) // at end of object - { - i++; offset = 0; - continue; - } - wxLayoutObjectText *tobj = (wxLayoutObjectText *)*i; - size_t count = 0; - wxString str = tobj->GetText(); - str = str.substr(offset,str.Length()-offset); - // Find out how many positions we need to delete: - // 1. eat leading space - while(isspace(str.c_str()[count])) count++; - // 2. eat the word itself: - while(isalnum(str.c_str()[count])) count++; - // now delete it: - wxASSERT(count+offset <= (size_t) (**i).GetLength()); - ((wxLayoutObjectText *)*i)->GetText().erase(offset,count); - m_Length -= count; - return true; - } - } + return true; + } + } - wxFAIL_MSG("unreachable"); + wxFAIL_MSG(wxT("unreachable")); } wxLayoutLine * @@ -1220,7 +1288,7 @@ wxLayoutLine::Layout(wxDC &dc, { // this might be the case if the cursor is at the end of the // line or on a command object: - if(cursorSize->y < WXLO_MINIMUM_CURSOR_WIDTH) + if(cursorSize->x < WXLO_MINIMUM_CURSOR_WIDTH) { CoordType width, height, descent; dc.GetTextExtent(WXLO_CURSORCHAR, &width, &height, &descent); @@ -1250,7 +1318,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; @@ -1281,6 +1351,131 @@ 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, + wxT("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) { @@ -1295,7 +1490,8 @@ wxLayoutLine::ReNumber(void) void wxLayoutLine::MergeNextLine(wxLayoutList *llist) { - wxCHECK_RET(GetNextLine(),"wxLayout internal error: no next line to merge"); + wxCHECK_RET( GetNextLine(), + wxT("wxLayout internal error: no next line to merge")); wxLayoutObjectList &list = GetNextLine()->m_ObjectList; wxLOiterator i; @@ -1366,7 +1562,7 @@ wxLayoutLine::GetWrapPosition(CoordType column) { do { - if( isspace(((wxLayoutObjectText*)*i)->GetText().c_str()[(size_t)offset])) + if(isspace(((wxLayoutObjectText*)*i)->GetText().c_str()[(size_t)offset])) return column; else { @@ -1395,34 +1591,34 @@ wxLayoutLine::GetWrapPosition(CoordType column) i++; } if(i == NULLIT) return -1; //why should this happen? + + // 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])) + { + return pos+offset; + } pos += (**i).GetLength(); - i++; - while(i != NULLIT && (**i).GetType() != WXLO_TYPE_TEXT) - { - pos += (**i).GetLength(); - i++; - } - 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 + 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", + WXLO_DEBUG((wxT("Line %ld, Pos (%ld,%ld), Height %ld, BL %ld, Font: %d"), (long int) GetLineNumber(), (long int) pos.x, (long int) pos.y, (long int) GetHeight(), (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 @@ -1519,7 +1715,7 @@ wxLayoutList::~wxLayoutList() Empty(); m_FirstLine->DeleteLine(false, this); - wxASSERT_MSG( m_numLines == 0, "line count calculation broken" ); + wxASSERT_MSG( m_numLines == 0, wxT("line count calculation broken")); } void @@ -1558,6 +1754,41 @@ wxLayoutList::InternalClear(void) m_CursorStyleInfo = m_DefaultStyleInfo; } +void +wxLayoutList::Read(wxString &istr) +{ + /* In order to handle input of formatted string "nicely", we need + to restore our current font settings after the string. So first + of all, we create a StyleInfo structure with our current + settings. */ + wxLayoutStyleInfo current_si = GetStyleInfo(); + + while(istr.Length()) + { + // check for a linebreak: + wxString tmp; + tmp = istr.BeforeFirst('\n'); + long l = WXLO_TYPE_INVALID; + tmp.ToLong(&l); + int type = (int) l; + + 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)); +} + + void wxLayoutList::SetFont(int family, int size, int style, int weight, int underline, wxColour *fg, @@ -1703,6 +1934,7 @@ wxLayoutList::MoveCursorVertically(int n) { n--; m_CursorPos.y ++; + last = m_CursorLine; m_CursorLine = m_CursorLine->GetNextLine(); } if(! m_CursorLine) @@ -1772,8 +2004,8 @@ wxLayoutList::MoveCursorHorizontally(int n) bool wxLayoutList::MoveCursorWord(int n, bool untilNext) { - wxCHECK_MSG( m_CursorLine, false, "no current line" ); - wxCHECK_MSG( n == -1 || n == +1, false, "not implemented yet" ); + wxCHECK_MSG( m_CursorLine, false, wxT("no current line") ); + wxCHECK_MSG( n == -1 || n == +1, false, wxT("not implemented yet") ); CoordType moveDistance = 0; CoordType offset; @@ -1862,9 +2094,9 @@ wxLayoutList::MoveCursorWord(int n, bool untilNext) if ( canAdvance ) { const wxString& text = tobj->GetText(); - const char *start = text.c_str(); - const char *end = start + text.length(); - const char *p = start + offset; + const wxChar *start = text.c_str(); + const wxChar *end = start + text.length(); + const wxChar *p = start + offset; if ( n < 0 ) { @@ -1933,16 +2165,18 @@ bool wxLayoutList::Insert(wxString const &text) { wxASSERT(m_CursorLine); - wxASSERT_MSG( text.Find('\n') == wxNOT_FOUND, "use wxLayoutImportText!" ); + wxASSERT_MSG( text.Find(wxT('\n')) == wxNOT_FOUND, + wxT("use wxLayoutImportText!") ); if ( !text ) return true; 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; @@ -2009,8 +2243,7 @@ wxLayoutList::LineBreak(void) m_CursorLine = m_CursorLine->Break(m_CursorPos.x, this); if(m_CursorLine->GetPreviousLine() == NULL) m_FirstLine = m_CursorLine; - if(m_CursorPos.x > 0) - m_CursorPos.y++; + m_CursorPos.y++; m_CursorPos.x = 0; // The following code will produce a height which is guaranteed to @@ -2034,35 +2267,28 @@ 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 m_CursorLine->Wrap(column, this); +} - return true; +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 wxLayoutList::Delete(CoordType npos) { - wxCHECK_MSG(m_CursorLine, false, "can't delete in non existing line"); + wxCHECK_MSG(m_CursorLine, false, wxT("can't delete in non existing line")); if ( npos == 0 ) return true; @@ -2117,7 +2343,7 @@ wxLayoutList::Delete(CoordType npos) } else { - wxFAIL_MSG("can't delete all this"); + wxFAIL_MSG(wxT("can't delete all this")); return false; } @@ -2220,6 +2446,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) { @@ -2229,6 +2458,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 @@ -2236,6 +2467,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()) @@ -2257,17 +2491,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); - else - line->Layout(dc, this); - // little condition to speed up redrawing: - if(bottom != -1 && line->GetPosition().y > bottom) - break; + cursorReached = TRUE; + } + else + line->Layout(dc, this); + } } line = line->GetNextLine(); } @@ -2343,8 +2580,8 @@ wxLayoutList::Draw(wxDC &dc, } InvalidateUpdateRect(); - WXLO_DEBUG(("Selection is %s : l%d,%ld/%ld,%ld", - m_Selection.m_valid ? "valid" : "invalid", + WXLO_DEBUG((wxT("Selection is %s : %ld,%ld/%ld,%ld"), + m_Selection.m_valid ? wxT("valid") : wxT("invalid"), m_Selection.m_CursorA.x, m_Selection.m_CursorA.y, m_Selection.m_CursorB.x, m_Selection.m_CursorB.y)); } @@ -2456,19 +2693,21 @@ wxLayoutList::DrawCursor(wxDC &dc, bool active, wxPoint const &translate) coords += translate; #ifdef WXLAYOUT_DEBUG - WXLO_DEBUG(("Drawing cursor (%ld,%ld) at %ld,%ld, size %ld,%ld, line: %ld, len %ld", + WXLO_DEBUG((wxT("Drawing cursor (%ld,%ld) at %ld,%ld, size %ld,%ld, line: %ld, len %ld"), (long)m_CursorPos.x, (long)m_CursorPos.y, - (long)coords.x, (long)coords.y, + (long)coords.x, (long)coords.y, (long)m_CursorSize.x, (long)m_CursorSize.y, (long)m_CursorLine->GetLineNumber(), (long)m_CursorLine->GetLength())); - wxLogStatus("Cursor is at (%d, %d)", m_CursorPos.x, m_CursorPos.y); + wxLogStatus(wxT("Cursor is at (%d, %d)"), m_CursorPos.x, m_CursorPos.y); #endif #ifdef WXLAYOUT_USE_CARET m_caret->Move(coords); #else // !WXLAYOUT_USE_CARET + + wxASSERT(m_CursorSize.x >= WXLO_MINIMUM_CURSOR_WIDTH); dc.SetBrush(*wxWHITE_BRUSH); //FIXME: wxGTK XOR is borken at the moment!!!dc.SetLogicalFunction(wxXOR); dc.SetPen(wxPen(*wxBLACK,1,wxSOLID)); @@ -2478,7 +2717,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 { @@ -2514,7 +2754,7 @@ wxLayoutList::StartSelection(const wxPoint& cposOrig, const wxPoint& spos) wxPoint cpos(cposOrig); if ( cpos.x == -1 ) cpos = m_CursorPos; - WXLO_DEBUG(("Starting selection at %ld/%ld", cpos.x, cpos.y)); + WXLO_DEBUG((wxT("Starting selection at %ld/%ld"), cpos.x, cpos.y)); m_Selection.m_CursorA = cpos; m_Selection.m_CursorB = cpos; m_Selection.m_ScreenA = spos; @@ -2532,19 +2772,19 @@ wxLayoutList::ContinueSelection(const wxPoint& cposOrig, const wxPoint& spos) wxASSERT(m_Selection.m_selecting == true); wxASSERT(m_Selection.m_valid == false); - WXLO_DEBUG(("Continuing selection at %ld/%ld", cpos.x, cpos.y)); + WXLO_DEBUG((wxT("Continuing selection at %ld/%ld"), cpos.x, cpos.y)); - m_Selection.m_ScreenB = spos; - m_Selection.m_CursorB = cpos;} + m_Selection.m_ScreenB = spos; + m_Selection.m_CursorB = cpos; +} void wxLayoutList::EndSelection(const wxPoint& cposOrig, const wxPoint& spos) { wxPoint cpos(cposOrig); - if(cpos.x == -1) - cpos = m_CursorPos; - ContinueSelection(cpos); - WXLO_DEBUG(("Ending selection at %ld/%ld", cpos.x, cpos.y)); + if(cpos.x == -1) cpos = m_CursorPos; + ContinueSelection(cpos, spos); + WXLO_DEBUG((wxT("Ending selection at %ld/%ld"), cpos.x, cpos.y)); // we always want m_CursorA <= m_CursorB! if( m_Selection.m_CursorA > m_Selection.m_CursorB ) { @@ -2733,7 +2973,7 @@ wxLayoutLine * wxLayoutList::GetLine(CoordType index) const { wxASSERT_MSG( (0 <= index) && (index < (CoordType)m_numLines), - "invalid index" ); + wxT("invalid index") ); wxLayoutLine *line; CoordType n = index; @@ -2839,12 +3079,11 @@ 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; } - wxlo->SetLayoutData(string); } return llist; @@ -2869,11 +3108,13 @@ wxLayoutList::ApplyStyle(wxLayoutStyleInfo const &si, wxDC &dc) if(si.m_fg_valid) { m_CurrentStyleInfo.m_fg = si.m_fg; + m_CurrentStyleInfo.m_fg_valid = true; dc.SetTextForeground(m_CurrentStyleInfo.m_fg); } if(si.m_bg_valid) { m_CurrentStyleInfo.m_bg = si.m_bg; + m_CurrentStyleInfo.m_bg_valid = true; dc.SetTextBackground(m_CurrentStyleInfo.m_bg); } } @@ -2884,7 +3125,7 @@ wxLayoutList::ApplyStyle(wxLayoutStyleInfo const &si, wxDC &dc) void wxLayoutList::Debug(void) { - WXLO_DEBUG(("Cursor is in line %d, screen pos = (%d, %d)", + WXLO_DEBUG((wxT("Cursor is in line %d, screen pos = (%d, %d)"), m_CursorLine->GetLineNumber(), m_CursorScreenPos.x, m_CursorScreenPos.y)); @@ -2984,7 +3225,7 @@ bool wxLayoutPrintout::OnPrintPage(int page) top = (page - 1)*m_PrintoutHeight; bottom = top + m_PrintoutHeight; - WXLO_DEBUG(("OnPrintPage(%d) printing from %d to %d", page, top, + WXLO_DEBUG((wxT("OnPrintPage(%d) printing from %d to %d"), page, top, bottom)); // SetDeviceOrigin() doesn't work here, so we need to manually // translate all coordinates. @@ -3002,7 +3243,7 @@ void wxLayoutPrintout::GetPageInfo(int *minPage, int *maxPage, int *selPageFrom, /* We allocate a temporary wxDC for printing, so that we can determine the correct paper size and scaling. We don't actually print anything on it. */ -#ifdef __WXMSW__ +#if defined(__WXMSW__) wxPrinterDC *psdc = new wxPrinterDC("","",WXLLIST_TEMPFILE,false); #else wxPostScriptDC *psdc = new wxPostScriptDC(WXLLIST_TEMPFILE,false);