/*-*- 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$
*******************************************************************/
# pragma implementation "wxllist.h"
#endif
-#include <wx/wxprec.h>
+#include "wx/wxprec.h"
#ifdef __BORLANDC__
# pragma hdrstop
#endif
#ifndef USE_PCH
-# include <iostream.h>
+#if wxUSE_IOSTREAMH
+ #include <iostream.h>
+#else
+ #include <iostream>
+#endif
# include <wx/dc.h>
# include <wx/dcps.h>
#include <ctype.h>
+
/// This should never really get created
#define WXLLIST_TEMPFILE "__wxllist.tmp"
{
"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
//@}
+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;
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
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;
+ }
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
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
#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
{
if ( !icon.Ok() )
{
- wxFAIL_MSG("invalid icon");
+ wxFAIL_MSG(wxT("invalid icon"));
m_Icon = NULL;
wxString file = wxGetTempFileName("wxloexport");
- ostr << WXLO_TYPE_ICON << '\n'
+ ostr << (int) WXLO_TYPE_ICON << '\n'
<< file << '\n';
m_Icon->SaveFile(file, WXLO_BITMAP_FORMAT);
}
wxLayoutObjectIcon::wxLayoutObjectIcon(wxBitmap *icon)
{
m_Icon = icon;
+ if(! m_Icon)
+ m_Icon = new wxBitmap;
}
void
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,
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;
}
m_Length = 0;
m_updateLeft = -1;
- MarkDirty(0);
-
m_Previous = prev;
m_Next = NULL;
+ MarkDirty(0);
m_LineNumber = 0;
RecalculatePosition(llist);
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 *
{
// 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);
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;
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)
{
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;
{
do
{
- if( isspace(((wxLayoutObjectText*)*i)->GetText().c_str()[(size_t)offset]))
+ if(isspace(((wxLayoutObjectText*)*i)->GetText().c_str()[(size_t)offset]))
return column;
else
{
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
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
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,
{
n--;
m_CursorPos.y ++;
+ last = m_CursorLine;
m_CursorLine = m_CursorLine->GetNextLine();
}
if(! m_CursorLine)
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;
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 )
{
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;
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
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;
}
else
{
- wxFAIL_MSG("can't delete all this");
+ wxFAIL_MSG(wxT("can't delete all this"));
return false;
}
// 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)
{
// 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
|| 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())
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();
}
}
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));
}
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));
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
{
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;
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 )
{
wxLayoutList::GetLine(CoordType index) const
{
wxASSERT_MSG( (0 <= index) && (index < (CoordType)m_numLines),
- "invalid index" );
+ wxT("invalid index") );
wxLayoutLine *line;
CoordType n = index;
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;
}
-#if 0 // FIXME: DnD/Clipboard API has changed, what should this be?
- wxlo->SetData(string.c_str(), string.Length()+1);
-#endif
+ wxlo->SetLayoutData(string);
}
return llist;
}
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);
}
}
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));
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.
/* 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);