git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@1013 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Karsten Ballüder
1998-11-19 20:34:59 +00:00
parent 3bc755fc89
commit deb907884a
6 changed files with 209 additions and 122 deletions

View File

@@ -6,9 +6,22 @@
* $Id$ * * $Id$ *
* * * *
* $Log$ * $Log$
* Revision 1.2 1998/08/12 08:33:23 KB * Revision 1.3 1998/11/19 20:34:50 KB
* Cursor and insert/delete work much better now, code streamlined, still * fixes
* a minor problem left. *
* Revision 1.8 1998/09/23 08:57:27 KB
* changed deletion behaviour
*
* Revision 1.7 1998/08/16 21:21:29 VZ
*
* 1) fixed config file bug: it was never created (attempt to create ~/.M/config
* always failed, must mkdir("~/.M") first)
* 2) "redesign" of "Folder properties" dialog and bug corrected, small change to
* MInputBox (it was too wide)
* 3) bug in ProvFC when it didn't reckognize the books as being in the correct
* format (=> messages "can't reopen book") corrected
* 4) I tried to enhance MDialog_About(), but it didn't really work... oh well,
* I've never said I was an artist
* *
* Revision 1.6 1998/07/08 11:56:56 KB * Revision 1.6 1998/07/08 11:56:56 KB
* M compiles and runs on Solaris 2.5/gcc 2.8/c-client gso * M compiles and runs on Solaris 2.5/gcc 2.8/c-client gso
@@ -40,12 +53,9 @@
# pragma implementation "kbList.h" # pragma implementation "kbList.h"
#endif #endif
#ifdef M_BASEDIR
# include "Mconfig.h"
#endif
#include "kbList.h" #include "kbList.h"
kbListNode::kbListNode( void *ielement, kbListNode::kbListNode( void *ielement,
kbListNode *iprev, kbListNode *iprev,
kbListNode *inext) kbListNode *inext)
@@ -93,13 +103,13 @@ kbList::iterator::operator--()
return *this; return *this;
} }
kbList::iterator & kbList::iterator &
kbList::iterator::operator++(int foo) kbList::iterator::operator++(int /* foo */)
{ {
return operator++(); return operator++();
} }
kbList::iterator & kbList::iterator &
kbList::iterator::operator--(int bar) kbList::iterator::operator--(int /* bar */)
{ {
return operator--(); return operator--();
} }
@@ -194,7 +204,7 @@ kbList::insert(kbList::iterator & i, void *element)
} }
void void
kbList::erase(kbList::iterator & i) kbList::doErase(kbList::iterator & i)
{ {
kbListNode kbListNode
*node = i.Node(), *node = i.Node(),
@@ -219,8 +229,9 @@ kbList::erase(kbList::iterator & i)
next->prev = prev; next->prev = prev;
// delete this node and contents: // delete this node and contents:
if(ownsEntries) // now done separately
delete *i; //if(ownsEntries)
//delete *i;
delete i.Node(); delete i.Node();
// change the iterator to next element: // change the iterator to next element:

View File

@@ -31,7 +31,7 @@ struct kbListNode
struct kbListNode *next; struct kbListNode *next;
/// pointer to previous node or NULL /// pointer to previous node or NULL
struct kbListNode *prev; struct kbListNode *prev;
/// pointer to the actual data /// pointer to the actual data
void *element; void *element;
/** Constructor - it automatically links the node into the list, if /** Constructor - it automatically links the node into the list, if
the iprev, inext parameters are given. the iprev, inext parameters are given.
@@ -40,8 +40,8 @@ struct kbListNode
@param inext if not NULL, use this as next element in list @param inext if not NULL, use this as next element in list
*/ */
kbListNode( void *ielement, kbListNode( void *ielement,
kbListNode *iprev = (kbListNode *) NULL, kbListNode *iprev = NULL,
kbListNode *inext = (kbListNode *) NULL); kbListNode *inext = NULL);
/// Destructor. /// Destructor.
~kbListNode(); ~kbListNode();
}; };
@@ -63,13 +63,19 @@ public:
/** Constructor. /** Constructor.
@param n if not NULL, the node to which to point @param n if not NULL, the node to which to point
*/ */
iterator(kbListNode *n = (kbListNode *) NULL); iterator(kbListNode *n = NULL);
/** Dereference operator. /** Dereference operator.
@return the data pointer of the node belonging to this @return the data pointer of the node belonging to this
iterator iterator
*/ */
void * operator*(); void * operator*();
/** This operator allows us to write if(i). It is <em>not</em> a
dereference operator and the result is always useless apart
from its logical value!
*/
operator void*() const { return node == NULL ? (void*)0 : (void*)(-1); }
/** Increment operator - prefix, goes to next node in list. /** Increment operator - prefix, goes to next node in list.
@return itself @return itself
*/ */
@@ -93,12 +99,12 @@ public:
/** Comparison operator. /** Comparison operator.
@return true if not equal. @return true if not equal.
*/ */
bool operator !=(iterator const &) const; bool operator !=(iterator const &) const;
/* Comparison operator. /* Comparison operator.
@return true if equal @return true if equal
*/ */
bool operator ==(iterator const &) const; bool operator ==(iterator const &) const;
/** Returns a pointer to the node associated with this iterator. /** Returns a pointer to the node associated with this iterator.
This function is not for general use and should be This function is not for general use and should be
@@ -135,7 +141,7 @@ public:
*/ */
bool ownsObjects(void) bool ownsObjects(void)
{ return ownsEntries; } { return ownsEntries; }
/** Add an entry at the end of the list. /** Add an entry at the end of the list.
@param element pointer to data @param element pointer to data
*/ */
@@ -161,18 +167,22 @@ public:
void *pop_front(void); void *pop_front(void);
/** Insert an element into the list. /** Insert an element into the list.
@param i an iterator pointing to the element, before which the @param i an iterator pointing to the element, before which the new one should be inserted
new one should be inserted. After the insert operation i will
point to the newly inserted element.
@param element the element data @param element the element data
*/ */
void insert(iterator & i, void *element); void insert(iterator & i, void *element);
/** Remove an element from the list _without_ deleting the object.
@param i iterator pointing to the element to be deleted
@return the value of the element just removed
*/
void *remove(iterator& i) { void *p = *i; doErase(i); return p; }
/** Erase an element, move iterator to following element. /** Erase an element, move iterator to following element.
@param i iterator pointing to the element to be deleted @param i iterator pointing to the element to be deleted
*/ */
void erase(iterator & i); void erase(iterator & i) { deleteContent(i); doErase(i); }
/* Get head of list. /* Get head of list.
@return iterator pointing to head of list @return iterator pointing to head of list
*/ */
@@ -200,7 +210,7 @@ public:
/* Query whether list is empty. /* Query whether list is empty.
@return true if list is empty @return true if list is empty
*/ */
bool empty(void) const inline bool empty(void) const
{ return first == NULL ; } { return first == NULL ; }
protected: protected:
@@ -210,6 +220,18 @@ protected:
kbListNode *first; kbListNode *first;
/// pointer to last element in list /// pointer to last element in list
kbListNode *last; kbListNode *last;
protected:
/** Erase an element, move iterator to following element.
@param i iterator pointing to the element to be deleted
*/
void doErase(iterator & i);
/** Deletes the actual content if ownsflag is set.
param iterator i
*/
inline void deleteContent(iterator i)
{ if(ownsEntries) delete *i; }
private: private:
/// forbid copy construction /// forbid copy construction
@@ -240,32 +262,25 @@ public: \
{ node = i.Node(); } \ { node = i.Node(); } \
friend class name; \ friend class name; \
public: \ public: \
inline iterator(kbListNode *n = (kbListNode *) NULL) \ inline iterator(kbListNode *n = NULL) \
: kbList::iterator(n) {} \ : kbList::iterator(n) {} \
inline type * operator*() \ inline type * operator*() \
/* the cast is needed for MS VC++ 5.0 */ \ /* the cast is needed for MS VC++ 5.0 */ \
{ return (type *)((kbList::iterator *)this)->operator*() ; } \ { return (type *)((kbList::iterator *)this)->operator*() ; } \
}; \ }; \
inline name(bool ownsEntriesFlag = FALSE) \ inline name(bool ownsEntriesFlag = TRUE) \
: kbList(ownsEntriesFlag) {} \ : kbList(ownsEntriesFlag) {} \
\ \
inline void push_back(type *element) \
{ kbList::push_back((void *)element); } \
\
inline void push_front(type *element) \
{ kbList::push_front((void *)element); } \
\
inline type *pop_back(void) \ inline type *pop_back(void) \
{ return (type *) kbList::pop_back(); } \ { return (type *) kbList::pop_back(); } \
\ \
inline type *pop_front(void) \ inline type *pop_front(void) \
{ return (type *) kbList::pop_front(); } \ { return (type *) kbList::pop_front(); } \
\ \
inline void insert(iterator & i, type *element) \ type *remove(iterator& i) \
{ kbList::insert(i, (void *) element); } \ { return (type *)kbList::remove(i); } \
\
inline void erase(iterator & i) \ inline void erase(iterator & i) \
{ kbList::erase(i); } \ { deleteContent(i); kbList::erase(i); } \
\ \
inline iterator begin(void) const \ inline iterator begin(void) const \
{ return kbList::begin(); } \ { return kbList::begin(); } \
@@ -278,19 +293,19 @@ public: \
~name() \ ~name() \
{ \ { \
kbListNode *next; \ kbListNode *next; \
while ( first != (kbListNode *) NULL ) \ while ( first != NULL ) \
{ \ { \
next = first->next; \ next = first->next; \
if(ownsEntries) \ if(ownsEntries) \
delete typecast(first->element); \ delete (type *)first->element; \
delete first; \ delete first; \
first = next; \ first = next; \
} \ } \
} \ } \
private: \ protected: \
inline type * typecast(void *ptr) \ inline void deleteContent(iterator i) \
{ return (type *) ptr; } \ { if(ownsEntries) delete *i; } \
} }
#ifdef MCONFIG_H #ifdef MCONFIG_H
/// define the most commonly used list type once: /// define the most commonly used list type once:

View File

@@ -33,7 +33,7 @@ IMPLEMENT_APP(MyApp)
enum ids{ ID_EDIT = 1, ID_ADD_SAMPLE, ID_CLEAR, ID_PRINT, enum ids{ ID_EDIT = 1, ID_ADD_SAMPLE, ID_CLEAR, ID_PRINT,
ID_PRINT_SETUP, ID_PAGE_SETUP, ID_PREVIEW, ID_PRINT_PS, ID_PRINT_SETUP, ID_PAGE_SETUP, ID_PREVIEW, ID_PRINT_PS,
ID_PRINT_SETUP_PS, ID_PAGE_SETUP_PS,ID_PREVIEW_PS, ID_PRINT_SETUP_PS, ID_PAGE_SETUP_PS,ID_PREVIEW_PS,
ID_DPRINT, ID_DPRINT, ID_WRAP, ID_NOWRAP,
ID_WXLAYOUT_DEBUG, ID_QUIT, ID_CLICK, ID_HTML, ID_TEXT, ID_TEST }; ID_WXLAYOUT_DEBUG, ID_QUIT, ID_CLICK, ID_HTML, ID_TEXT, ID_TEST };
@@ -81,7 +81,10 @@ MyFrame::MyFrame(void) :
file_menu->Append(ID_PREVIEW_PS, "Print Preview PostScript", "Preview (PostScript)"); file_menu->Append(ID_PREVIEW_PS, "Print Preview PostScript", "Preview (PostScript)");
#endif #endif
file_menu->AppendSeparator(); file_menu->AppendSeparator();
file_menu->Append(ID_WRAP, "Wrap mode", "Activate wrapping at pixel 200.");
file_menu->Append(ID_NOWRAP, "No-wrap mode", "Deactivate wrapping.");
file_menu->AppendSeparator();
// file_menu->Append( ID_DPRINT, "Direct Print"); // file_menu->Append( ID_DPRINT, "Direct Print");
file_menu->Append( ID_TEXT, "Export Text"); file_menu->Append( ID_TEXT, "Export Text");
file_menu->Append( ID_HTML, "Export HTML"); file_menu->Append( ID_HTML, "Export HTML");
@@ -222,6 +225,11 @@ void MyFrame::OnCommand( wxCommandEvent &event )
case ID_PRINT: case ID_PRINT:
m_lwin->Print(); m_lwin->Print();
break; break;
case ID_NOWRAP:
case ID_WRAP:
m_lwin->GetLayoutList().SetWrapMargin(
event.GetId() == ID_NOWRAP ? -1 : 40);
break;
case ID_DPRINT: case ID_DPRINT:
{ {
wxLayoutList llist; wxLayoutList llist;

View File

@@ -25,20 +25,14 @@
/* /*
TODO: TODO:
- new cursor movement calculations - cursor redraw problems
- moving lines and moving across linebreaks still broken
- word wrap
- blinking cursor - blinking cursor
- mouse click positions cursor - mouse click positions cursor
- selection (SetMark(), GetSelection()) - selection (SetMark(), GetSelection())
- DND acceptance of text - DND acceptance of text / clipboard support
- wxlwindow: formatting menu: problem with checked/unchecked consistency gtk bug? - wxlwindow: formatting menu: problem with checked/unchecked consistency gtk bug?
*/ */
#define USE_NEW_CURSORCODE 1
/* /*
Known wxGTK bugs: Known wxGTK bugs:
- MaxX()/MaxY() don't get set - MaxX()/MaxY() don't get set
@@ -248,6 +242,7 @@ wxLayoutObjectCmd::Layout(wxDC &dc, wxPoint p, CoordType baseline)
wxLayoutList::wxLayoutList() wxLayoutList::wxLayoutList()
{ {
m_DefaultSetting = NULL; m_DefaultSetting = NULL;
m_WrapMargin = -1;
Clear(); Clear();
} }
@@ -409,20 +404,8 @@ wxLayoutList::Layout(wxDC &dc, wxLayoutMargins *margins)
headOfLine++; headOfLine++;
position_HeadOfLine = position; position_HeadOfLine = position;
} }
#if defined( USE_NEW_CURSORCODE )
if(i == m_CursorObject) if(i == m_CursorObject)
CalculateCursor(dc); CalculateCursor(dc);
#else
if(cursorObject == NULL && cursorPos.y == m_CursorPos.y) // look for cursor
{
if(cursorPos.x >= m_CursorPos.x &&
m_CursorPos.x-cursorPos.x+(**i).CountPositions()) // cursor is in current object
{
cursorObject = *i;
CalculateCursor(dc);
}
}
#endif
i++; i++;
} }
while(i != end()); while(i != end());
@@ -493,25 +476,21 @@ wxLayoutList::CalculateCursor(wxDC &dc)
CoordType width, height, descent; CoordType width, height, descent;
CoordType baseLineSkip = 20; //FIXME CoordType baseLineSkip = 20; //FIXME
CoordType offset; if( m_CursorObject == iterator(NULL)) // empty list
if( FindCurrentObject() == iterator(NULL)) // empty list
{ {
DrawCursor(dc,true); // erase it
m_CursorCoords = wxPoint(0,0); m_CursorCoords = wxPoint(0,0);
m_CursorSize = wxPoint(2,baseLineSkip); m_CursorSize = wxPoint(2,baseLineSkip);
m_CursorMoved = false; // coords are valid m_CursorMoved = false; // coords are valid
return; return;
} }
wxLayoutObjectBase &obj = **FindCurrentObject(&offset); wxLayoutObjectBase &obj = **m_CursorObject;
DrawCursor(dc,true); // erase it
m_CursorCoords = obj.GetPosition(); m_CursorCoords = obj.GetPosition();
if(obj.GetType() == WXLO_TYPE_TEXT) if(obj.GetType() == WXLO_TYPE_TEXT)
{ {
wxLayoutObjectText *tobj = (wxLayoutObjectText *)&obj; wxLayoutObjectText *tobj = (wxLayoutObjectText *)&obj;
String & str = tobj->GetText(); String & str = tobj->GetText();
String sstr = str.substr(0,offset); String sstr = str.substr(0,m_CursorOffset);
dc.GetTextExtent(sstr,&width,&height,&descent); dc.GetTextExtent(sstr,&width,&height,&descent);
m_CursorCoords = wxPoint(m_CursorCoords.x+width, m_CursorCoords = wxPoint(m_CursorCoords.x+width,
m_CursorCoords.y); m_CursorCoords.y);
@@ -596,23 +575,22 @@ wxLayoutList::Debug(void)
void void
wxLayoutList::ShowCurrentObject() wxLayoutList::ShowCurrentObject()
{ {
CoordType offs;
wxLayoutObjectList::iterator i = FindCurrentObject(&offs);
wxLayoutDebug("CursorPos (%d, %d)", (int) m_CursorPos.x, (int) m_CursorPos.y); wxLayoutDebug("CursorPos (%d, %d)", (int) m_CursorPos.x, (int) m_CursorPos.y);
wxLayoutDebug("CursorOffset = %d", (int) m_CursorOffset); wxLayoutDebug("CursorOffset = %d", (int) m_CursorOffset);
wxLayoutDebug("CursorObject = %p", m_CursorObject); wxLayoutDebug("CursorObject = %p", m_CursorObject);
wxLayoutDebug("Line length: %d", GetLineLength(i)); if(m_CursorObject == iterator(NULL))
if(i == iterator(NULL))
wxLayoutDebug("<<no object found>>"); wxLayoutDebug("<<no object found>>");
else else
{ {
if((*i)->GetType() == WXLO_TYPE_TEXT) if((*m_CursorObject)->GetType() == WXLO_TYPE_TEXT)
wxLayoutDebug(" \"%s\", offs: %d", ((wxLayoutObjectText *)(*i))->GetText().c_str(), offs); wxLayoutDebug(" \"%s\", offs: %d",
((wxLayoutObjectText *)(*m_CursorObject))->GetText().c_str(),
m_CursorOffset);
else else
wxLayoutDebug(" %s", TypeString((*i)->GetType())); wxLayoutDebug(" %s", TypeString((*m_CursorObject)->GetType()));
} }
wxLayoutDebug("Line length: %d", GetLineLength(m_CursorObject));
} }
#endif #endif
@@ -715,14 +693,6 @@ wxLayoutList::FindObjectCursor(wxPoint *cpos, CoordType *offset)
return m_FoundIterator = i; // not found return m_FoundIterator = i; // not found
} }
wxLayoutObjectList::iterator
wxLayoutList::FindCurrentObject(CoordType *offset)
{
if(offset)
*offset = m_CursorOffset;
return m_CursorObject;
}
bool bool
wxLayoutList::MoveCursor(int dx, int dy) wxLayoutList::MoveCursor(int dx, int dy)
{ {
@@ -746,7 +716,8 @@ wxLayoutList::MoveCursor(int dx, int dy)
direction = down; direction = down;
else else
direction = up; direction = up;
wxASSERT(m_CursorObject);
// now move cursor forwards until at the new position: // now move cursor forwards until at the new position:
// first, go to the right line: // first, go to the right line:
@@ -863,16 +834,16 @@ wxLayoutList::Delete(CoordType count)
do do
{ {
i = FindCurrentObject(&offs); i = m_CursorObject;
startover: // ugly, but easiest way to do it startover: // ugly, but easiest way to do it
if(i == end()) if(i == end())
return; // we cannot delete anything more return; // we cannot delete anything more
/* Here we need to treat linebreaks differently. /* Here we need to treat linebreaks differently.
If offs==0 we are before the linebreak, otherwise behind. */ If m_CursorOffset==0 we are before the linebreak, otherwise behind. */
if((*i)->GetType() == WXLO_TYPE_LINEBREAK) if((*i)->GetType() == WXLO_TYPE_LINEBREAK)
{ {
if(offs == 0) if(m_CursorOffset == 0)
{ {
m_MaxLine--; m_MaxLine--;
erase(i); erase(i);
@@ -884,7 +855,7 @@ wxLayoutList::Delete(CoordType count)
else // delete the object behind the linebreak else // delete the object behind the linebreak
{ {
i++; // we increment and continue as normal i++; // we increment and continue as normal
offs=0; m_CursorOffset=0;
goto startover; goto startover;
} }
} }
@@ -894,10 +865,10 @@ wxLayoutList::Delete(CoordType count)
CoordType len = tobj->CountPositions(); CoordType len = tobj->CountPositions();
// If we find the end of a text object, this means that we // If we find the end of a text object, this means that we
// have to delete from the object following it. // have to delete from the object following it.
if(len == offs) if(len == m_CursorOffset)
{ {
i++; i++;
offs = 0; m_CursorOffset = 0;
goto startover; goto startover;
} }
else if(len <= count) // delete this object else if(len <= count) // delete this object
@@ -911,7 +882,7 @@ wxLayoutList::Delete(CoordType count)
else else
{ {
len = count; len = count;
tobj->GetText().erase(offs,len); tobj->GetText().erase(m_CursorOffset,len);
// cursor unchanged // cursor unchanged
return; // we are done return; // we are done
} }
@@ -933,7 +904,7 @@ wxLayoutList::Delete(CoordType count)
else // delete the following object else // delete the following object
{ {
i++; // we increment and continue as normal i++; // we increment and continue as normal
offs=0; m_CursorOffset=0;
goto startover; goto startover;
} }
} }
@@ -948,31 +919,31 @@ wxLayoutList::Insert(wxLayoutObjectBase *obj)
m_bModified = true; m_bModified = true;
CoordType offs; wxLayoutObjectList::iterator i = m_CursorObject;
wxLayoutObjectList::iterator i = FindCurrentObject(&offs);
// if(i != iterator(NULL) && (*obj).GetType() == WXLO_TYPE_LINEBREAK) if(i != iterator(NULL) && (*obj).GetType() == WXLO_TYPE_LINEBREAK)
// { {
// m_CursorPos.x = 0; m_CursorPos.y ++; m_CursorPos.x = 0; m_CursorPos.y ++;
// } }
if(i == end()) if(i == end())
{ {
push_back(obj); push_back(obj);
m_CursorObject = tail(); m_CursorObject = tail();
} }
else if(offs == 0) else if(m_CursorOffset == 0)
{ {
insert(i,obj); insert(i,obj);
m_CursorObject = i; m_CursorObject = i;
} }
// do we have to split a text object? // do we have to split a text object?
else if((*i)->GetType() == WXLO_TYPE_TEXT && offs != (*i)->CountPositions()) else if((*i)->GetType() == WXLO_TYPE_TEXT && m_CursorOffset != (*i)->CountPositions())
{ {
wxLayoutObjectText *tobj = (wxLayoutObjectText *) *i; wxLayoutObjectText *tobj = (wxLayoutObjectText *) *i;
String left = tobj->GetText().substr(0,offs); // get part before cursor String left = tobj->GetText().substr(0,m_CursorOffset); // get part before cursor
tobj->GetText() = tobj->GetText().substr(offs,(*i)->CountPositions()-offs); // keeps the right half tobj->GetText() = tobj->GetText().substr(m_CursorOffset,(*i)->CountPositions()-m_CursorOffset); // keeps the right half
insert(i,obj); insert(i,obj);
m_CursorObject = i; // == obj
insert(i,new wxLayoutObjectText(left)); // inserts before insert(i,new wxLayoutObjectText(left)); // inserts before
} }
else else
@@ -1015,8 +986,7 @@ wxLayoutList::Insert(String const &text)
m_bModified = true; m_bModified = true;
CoordType offs; wxLayoutObjectList::iterator i = m_CursorObject;
wxLayoutObjectList::iterator i = FindCurrentObject(&offs);
if(i == end()) if(i == end())
{ {
@@ -1024,26 +994,21 @@ wxLayoutList::Insert(String const &text)
return; return;
} }
if(i != iterator(NULL) && (**i).GetType() == WXLO_TYPE_LINEBREAK)
{
m_CursorPos.x = 0; m_CursorPos.y ++;
}
switch((**i).GetType()) switch((**i).GetType())
{ {
case WXLO_TYPE_TEXT: case WXLO_TYPE_TEXT:
// insert into an existing text object: // insert into an existing text object:
tobj = (wxLayoutObjectText *)*i ; tobj = (wxLayoutObjectText *)*i ;
wxASSERT(tobj); wxASSERT(tobj);
tobj->GetText().insert(offs,text); tobj->GetText().insert(m_CursorOffset,text);
m_CursorObject = i; m_CursorObject = i;
m_CursorOffset = offs + text.length(); m_CursorOffset = m_CursorOffset + text.length();
m_CursorPos.x += text.length(); m_CursorPos.x += text.length();
break; break;
case WXLO_TYPE_LINEBREAK: case WXLO_TYPE_LINEBREAK:
default: default:
j = i; j = i;
if(offs == 0) // try to append to previous object if(m_CursorOffset == 0) // try to append to previous object
{ {
j--; j--;
if(j != end() && (**j).GetType() == WXLO_TYPE_TEXT) if(j != end() && (**j).GetType() == WXLO_TYPE_TEXT)
@@ -1156,7 +1121,7 @@ wxLayoutList::Clear(int family, int size, int style, int weight,
m_CursorOffset = 0; m_CursorOffset = 0;
m_CursorSize = wxPoint(2,(BASELINESTRETCH*m_FontPtSize)/10); m_CursorSize = wxPoint(2,(BASELINESTRETCH*m_FontPtSize)/10);
m_MaxLine = 0; m_MaxLine = 1;
m_LineHeight = (BASELINESTRETCH*m_FontPtSize)/10; m_LineHeight = (BASELINESTRETCH*m_FontPtSize)/10;
m_MaxX = 0; m_MaxY = 0; m_MaxX = 0; m_MaxY = 0;
@@ -1199,6 +1164,73 @@ wxLayoutList::Find(wxPoint coords) const
} }
void
wxLayoutList::SetWrapMargin(long n = -1)
{
m_WrapMargin = n;
}
void
wxLayoutList::WrapLine(void)
{
wxASSERT(m_CursorObject);
iterator i = m_CursorObject;
if(!DoWordWrap() || !i ) // empty list
return;
int cursorpos = m_CursorPos.x, cpos, offset;
if(cursorpos < m_WrapMargin)
return;
// else: break line
// find the right object to break:
// is it the current one?
i = m_CursorObject;
cpos = cursorpos-m_CursorOffset;
while(i != begin() && cpos >= m_WrapMargin)
{
i--;
cpos -= (**i).CountPositions();
}
// now i is the object to break and cpos its position
offset = m_WrapMargin - cpos;
wxASSERT(offset <= (**i).CountPositions());
// split it
if((**i).GetType() == WXLO_TYPE_TEXT)
{
wxLayoutObjectText &t = *(wxLayoutObjectText *)*i;
for(; offset > 0; offset--)
if(t.GetText().c_str()[offset] == ' ' || t.GetText().c_str()[offset] == '\t')
{
String left = t.GetText().substr(0,offset-1); // get part before cursor
t.GetText() = t.GetText().substr(offset,t.CountPositions()-offset); // keeps the right halve
insert(i,new wxLayoutObjectLineBreak);
insert(i,new wxLayoutObjectText(left)); // inserts before
break;
}
if(offset == 0)
{
// only insert a line break if there isn't already one
iterator j = i; j--;
if(j && j != begin() && (**j).GetType() != WXLO_TYPE_LINEBREAK)
insert(i,new wxLayoutObjectLineBreak);
else
return; // do nothing
}
}
else
insert(i,new wxLayoutObjectLineBreak);
m_MaxLine++;
m_CursorPos.y++;
m_CursorPos.x -= offset;
m_CursorOffset -= offset;
}
/******************** printing stuff ********************/ /******************** printing stuff ********************/
wxLayoutPrintout::wxLayoutPrintout(wxLayoutList &llist, wxLayoutPrintout::wxLayoutPrintout(wxLayoutList &llist,
@@ -1277,7 +1309,7 @@ void wxLayoutPrintout::GetPageInfo(int *minPage, int *maxPage, int *selPageFrom,
bool wxLayoutPrintout::HasPage(int pageNum) bool wxLayoutPrintout::HasPage(int pageNum)
{ {
return pageNum < m_NumOfPages; return pageNum <= m_NumOfPages;
} }

View File

@@ -301,6 +301,13 @@ public:
/// set font colours by name /// set font colours by name
inline void SetFontColour(char const *fg, char const *bg = NULL) { SetFont(-1,-1,-1,-1,-1,fg,bg); } inline void SetFontColour(char const *fg, char const *bg = NULL) { SetFont(-1,-1,-1,-1,-1,fg,bg); }
/** Sets the wrap margin in cursor positions.
@param n the wrap margin, -1 to disable auto wrap
*/
void SetWrapMargin(long n = -1);
/// Wraps the current line if word wrap is enabled.
void WrapLine(void);
/** Re-layouts the list on a DC. /** Re-layouts the list on a DC.
@param dc the dc to layout for @param dc the dc to layout for
@@ -371,7 +378,11 @@ public:
/// return a pointer to the default settings (dangerous, why?) FIXME: /// return a pointer to the default settings (dangerous, why?) FIXME:
wxLayoutObjectCmd const *GetDefaults(void) const { return m_DefaultSetting ; } wxLayoutObjectCmd const *GetDefaults(void) const { return m_DefaultSetting ; }
wxLayoutObjectList::iterator FindCurrentObject(CoordType *offset = NULL); /// returns the iterator for the object under the cursor
wxLayoutObjectList::iterator GetCurrentObject(CoordType *offset =
NULL)
{ if(offset) *offset = m_CursorOffset; return m_CursorObject; }
// get the length of the line with the object pointed to by i, offs // get the length of the line with the object pointed to by i, offs
// only used to decide whether we are before or after linebreak // only used to decide whether we are before or after linebreak
CoordType GetLineLength(wxLayoutObjectList::iterator i, CoordType GetLineLength(wxLayoutObjectList::iterator i,
@@ -432,6 +443,10 @@ protected:
/// find the object to the cursor position and returns the offset /// find the object to the cursor position and returns the offset
/// in there /// in there
wxLayoutObjectList::iterator FindObjectCursor(wxPoint *cpos, CoordType *offset = NULL); wxLayoutObjectList::iterator FindObjectCursor(wxPoint *cpos, CoordType *offset = NULL);
/// get the wrap margin
inline long GetWrapMargin(void) const { return m_WrapMargin; }
/// do we do wrapping?
inline bool DoWordWrap(void) const { return m_WrapMargin != -1; }
private: private:
/// Resets the font settings etc to default values /// Resets the font settings etc to default values
void ResetSettings(wxDC &dc); void ResetSettings(wxDC &dc);
@@ -441,6 +456,8 @@ private:
wxPoint m_FoundCursor; wxPoint m_FoundCursor;
/// remembers the iterator to the object related to m_FoundCursor /// remembers the iterator to the object related to m_FoundCursor
wxLayoutObjectList::iterator m_FoundIterator; wxLayoutObjectList::iterator m_FoundIterator;
/// the wrap margin
long m_WrapMargin;
}; };
class wxLayoutPrintout: public wxPrintout class wxLayoutPrintout: public wxPrintout

View File

@@ -168,14 +168,14 @@ wxLayoutWindow::OnChar(wxKeyEvent& event)
break; break;
case WXK_END: case WXK_END:
p = m_llist.GetCursor(); p = m_llist.GetCursor();
p.x = m_llist.GetLineLength(m_llist.FindCurrentObject(NULL)); p.x = m_llist.GetLineLength(m_llist.GetCurrentObject());
m_llist.SetCursor(p); m_llist.SetCursor(p);
break; break;
case WXK_DELETE : case WXK_DELETE :
if(event.ControlDown()) // delete to end of line if(event.ControlDown()) // delete to end of line
{ {
help = m_llist.GetLineLength( help = m_llist.GetLineLength(
m_llist.FindCurrentObject(NULL)) m_llist.GetCurrentObject())
- m_llist.GetCursor().x; - m_llist.GetCursor().x;
m_llist.Delete(help ? help : 1); m_llist.Delete(help ? help : 1);
} }
@@ -195,6 +195,9 @@ wxLayoutWindow::OnChar(wxKeyEvent& event)
case WXK_F1: case WXK_F1:
m_llist.Debug(); m_llist.Debug();
break; break;
case WXK_F2:
m_llist.WrapLine();
break;
#endif #endif
default: default:
@@ -203,6 +206,7 @@ wxLayoutWindow::OnChar(wxKeyEvent& event)
String tmp; String tmp;
tmp += keyCode; tmp += keyCode;
m_llist.Insert(tmp); m_llist.Insert(tmp);
m_llist.WrapLine();
} }
break; break;
} }