Fix overrunning array

This commit is contained in:
Markus Gans 2017-09-16 01:21:16 +02:00
parent 0e4ba28544
commit 37f8ee81c9
4 changed files with 261 additions and 202 deletions

View File

@ -26,8 +26,17 @@ FListViewItem::FListViewItem (const FListViewItem& item)
{ {
FObject* parent = getParent(); FObject* parent = getParent();
if ( parent && parent->isInstanceOf("FListView") ) if ( ! parent )
return;
if ( parent->isInstanceOf("FListView") )
{
static_cast<FListView*>(parent)->insert (this); static_cast<FListView*>(parent)->insert (this);
}
else if ( parent->isInstanceOf("FListViewItem") )
{
static_cast<FListViewItem*>(parent)->insert (this);
}
} }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
@ -39,23 +48,7 @@ FListViewItem::FListViewItem (FObjectIterator parent_iter)
, expandable(false) , expandable(false)
, is_expand(false) , is_expand(false)
{ {
if ( *parent_iter ) insert (this, parent_iter);
{
if ( (*parent_iter)->isInstanceOf("FListView") )
{
// Add FListViewItem to a FListView parent
FListView* parent = static_cast<FListView*>(*parent_iter);
parent->addChild (this);
parent->insert (this);
}
else if ( (*parent_iter)->isInstanceOf("FListViewItem") )
{
// Add FListViewItem to a FListViewItem parent
FListViewItem* parent = static_cast<FListViewItem*>(*parent_iter);
parent->addChild (this);
parent->expandable = true;
}
}
} }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
@ -72,35 +65,8 @@ FListViewItem::FListViewItem ( const std::vector<FString>& cols
if ( cols.empty() ) if ( cols.empty() )
return; return;
// Replace the control codes characters replaceControlCodes();
std::vector<FString>::iterator iter = column_list.begin(); insert (this, parent_iter);
while ( iter != column_list.end() )
{
*iter = iter->replaceControlCodes();
++iter;
}
if ( parent_iter == FObjectIterator(0) )
return;
if ( *parent_iter )
{
if ( (*parent_iter)->isInstanceOf("FListView") )
{
// Add FListViewItem to a FListView parent
FListView* parent = static_cast<FListView*>(*parent_iter);
parent->addChild (this);
parent->insert (this);
}
else if ( (*parent_iter)->isInstanceOf("FListViewItem") )
{
// Add FListViewItem to a FListViewItem parent
FListViewItem* parent = static_cast<FListViewItem*>(*parent_iter);
parent->addChild (this);
parent->expandable = true;
}
}
} }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
@ -149,14 +115,39 @@ void FListViewItem::setText (int column, const FString& text)
} }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
void FListViewItem::insert (FListViewItem* child) FObject::FObjectIterator FListViewItem::insert (FListViewItem* child)
{ {
// Add a FListViewItem as child element // Add a FListViewItem as child element
if ( ! child || ! hasChildren() ) if ( ! child || ! hasChildren() )
return; return FObjectIterator(0);
addChild (child); return appendItem(child);
expandable = true; }
//----------------------------------------------------------------------
FObject::FObjectIterator FListViewItem::insert ( FListViewItem* child
, FObjectIterator parent_iter )
{
if ( parent_iter == FObjectIterator(0) )
return FObjectIterator(0);
if ( *parent_iter )
{
if ( (*parent_iter)->isInstanceOf("FListView") )
{
// Add FListViewItem to a FListView parent
FListView* parent = static_cast<FListView*>(*parent_iter);
return parent->insert (child);
}
else if ( (*parent_iter)->isInstanceOf("FListViewItem") )
{
// Add FListViewItem to a FListViewItem parent
FListViewItem* parent = static_cast<FListViewItem*>(*parent_iter);
return parent->insert (child);
}
}
return FObjectIterator(0);
} }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
@ -177,6 +168,29 @@ void FListViewItem::collapse()
is_expand = false; is_expand = false;
} }
// private methods of FListView
//----------------------------------------------------------------------
FObject::FObjectIterator FListViewItem::appendItem (FListViewItem* child)
{
expandable = true;
addChild (child);
FObjectList children = getChildren();
return --children.end();
}
//----------------------------------------------------------------------
void FListViewItem::replaceControlCodes()
{
// Replace the control codes characters
std::vector<FString>::iterator iter = column_list.begin();
while ( iter != column_list.end() )
{
*iter = iter->replaceControlCodes();
++iter;
}
}
//---------------------------------------------------------------------- //----------------------------------------------------------------------
int FListViewItem::getVisibleLines() int FListViewItem::getVisibleLines()
{ {
@ -379,32 +393,25 @@ FObject::FObjectIterator FListView::insert ( FListViewItem* item
if ( parent_iter == root ) if ( parent_iter == root )
{ {
addChild (item); item_iter = appendItem (item);
itemlist.push_back (item);
item_iter = --itemlist.end();
} }
else if ( *parent_iter ) else if ( *parent_iter )
{ {
if ( (*parent_iter)->isInstanceOf("FListView") ) if ( (*parent_iter)->isInstanceOf("FListView") )
{ {
// Add FListViewItem to a FListView parent // Add FListViewItem to a FListView parent
addChild (item);
FListView* parent = static_cast<FListView*>(*parent_iter); FListView* parent = static_cast<FListView*>(*parent_iter);
parent->itemlist.push_back (item); item_iter = parent->appendItem (item);
item_iter = --parent->itemlist.end();
} }
else if ( (*parent_iter)->isInstanceOf("FListViewItem") ) else if ( (*parent_iter)->isInstanceOf("FListViewItem") )
{ {
// Add FListViewItem to a FListViewItem parent // Add FListViewItem to a FListViewItem parent
FListViewItem* parent = static_cast<FListViewItem*>(*parent_iter); FListViewItem* parent = static_cast<FListViewItem*>(*parent_iter);
parent->expandable = true; item_iter = parent->appendItem (item);
parent->addChild (item);
FObjectList parent_obj = parent->getChildren();
item_iter = --parent_obj.end();
} }
} }
int element_count = int(itemlist.size()); int element_count = int(getCount());
recalculateVerticalBar (element_count); recalculateVerticalBar (element_count);
return item_iter; return item_iter;
} }
@ -416,6 +423,9 @@ FObject::FObjectIterator FListView::insert ( const std::vector<FString>& cols
{ {
FListViewItem* item; FListViewItem* item;
if ( cols.empty() || parent_iter == FObjectIterator(0) )
return FObjectIterator(0);
if ( ! *parent_iter ) if ( ! *parent_iter )
parent_iter = root; parent_iter = root;
@ -429,6 +439,7 @@ FObject::FObjectIterator FListView::insert ( const std::vector<FString>& cols
return FObjectIterator(0); return FObjectIterator(0);
} }
item->replaceControlCodes();
return insert(item, parent_iter); return insert(item, parent_iter);
} }
@ -454,7 +465,7 @@ FObject::FObjectIterator FListView::insert ( const std::vector<long>& cols
//---------------------------------------------------------------------- //----------------------------------------------------------------------
void FListView::onKeyPress (FKeyEvent* ev) void FListView::onKeyPress (FKeyEvent* ev)
{ {
int element_count = int(itemlist.size()); int element_count = int(getCount());
int current_before = current; int current_before = current;
int xoffset_before = xoffset; int xoffset_before = xoffset;
int xoffset_end = max_line_width - getClientWidth(); int xoffset_end = max_line_width - getClientWidth();
@ -564,6 +575,22 @@ void FListView::onKeyPress (FKeyEvent* ev)
ev->accept(); ev->accept();
break; break;
case int('+'):
{
FListViewItem* item = getCurrentItem();
item->expand();
ev->accept();
}
break;
case int('-'):
{
FListViewItem* item = getCurrentItem();
item->collapse();
ev->accept();
}
break;
default: default:
ev->ignore(); ev->ignore();
} }
@ -631,8 +658,8 @@ void FListView::onMouseDown (FMouseEvent* ev)
{ {
current = yoffset + mouse_y - 1; current = yoffset + mouse_y - 1;
if ( current > int(itemlist.size()) ) if ( current > int(getCount()) )
current = int(itemlist.size()); current = int(getCount());
if ( isVisible() ) if ( isVisible() )
drawList(); drawList();
@ -694,8 +721,8 @@ void FListView::onMouseMove (FMouseEvent* ev)
{ {
current = yoffset + mouse_y - 1; current = yoffset + mouse_y - 1;
if ( current > int(itemlist.size()) ) if ( current > int(getCount()) )
current = int(itemlist.size()); current = int(getCount());
if ( isVisible() ) if ( isVisible() )
drawList(); drawList();
@ -741,7 +768,7 @@ void FListView::onMouseMove (FMouseEvent* ev)
&& scroll_distance < getClientHeight() ) && scroll_distance < getClientHeight() )
scroll_distance++; scroll_distance++;
if ( ! scroll_timer && current < int(itemlist.size()) ) if ( ! scroll_timer && current < int(getCount()) )
{ {
scroll_timer = true; scroll_timer = true;
addTimer(scroll_repeat); addTimer(scroll_repeat);
@ -752,7 +779,7 @@ void FListView::onMouseMove (FMouseEvent* ev)
drag_scroll = fc::scrollDown; drag_scroll = fc::scrollDown;
} }
if ( current == int(itemlist.size()) ) if ( current == int(getCount()) )
{ {
delOwnTimer(); delOwnTimer();
drag_scroll = fc::noScroll; drag_scroll = fc::noScroll;
@ -782,7 +809,7 @@ void FListView::onMouseDoubleClick (FMouseEvent* ev)
if ( mouse_x > 1 && mouse_x < getWidth() if ( mouse_x > 1 && mouse_x < getWidth()
&& mouse_y > 1 && mouse_y < getHeight() ) && mouse_y > 1 && mouse_y < getHeight() )
{ {
if ( yoffset + mouse_y - 1 > int(itemlist.size()) ) if ( yoffset + mouse_y - 1 > int(getCount()) )
return; return;
processClick(); processClick();
@ -792,7 +819,7 @@ void FListView::onMouseDoubleClick (FMouseEvent* ev)
//---------------------------------------------------------------------- //----------------------------------------------------------------------
void FListView::onTimer (FTimerEvent*) void FListView::onTimer (FTimerEvent*)
{ {
int element_count = int(itemlist.size()); int element_count = int(getCount());
int current_before = current; int current_before = current;
int yoffset_before = yoffset; int yoffset_before = yoffset;
int yoffset_end = element_count - getClientHeight(); int yoffset_end = element_count - getClientHeight();
@ -863,7 +890,7 @@ void FListView::onTimer (FTimerEvent*)
void FListView::onWheel (FWheelEvent* ev) void FListView::onWheel (FWheelEvent* ev)
{ {
int element_count, current_before, yoffset_before, yoffset_end, wheel; int element_count, current_before, yoffset_before, yoffset_end, wheel;
element_count = int(itemlist.size()); element_count = int(getCount());
current_before = current; current_before = current;
yoffset_before = yoffset; yoffset_before = yoffset;
yoffset_end = element_count - getClientHeight(); yoffset_end = element_count - getClientHeight();
@ -964,7 +991,7 @@ void FListView::onFocusOut (FFocusEvent*)
//---------------------------------------------------------------------- //----------------------------------------------------------------------
void FListView::adjustYOffset() void FListView::adjustYOffset()
{ {
int element_count = int(itemlist.size()); int element_count = int(getCount());
if ( yoffset > element_count - getClientHeight() ) if ( yoffset > element_count - getClientHeight() )
yoffset = element_count - getClientHeight(); yoffset = element_count - getClientHeight();
@ -986,7 +1013,7 @@ void FListView::adjustSize()
FWidget::adjustSize(); FWidget::adjustSize();
adjustYOffset(); adjustYOffset();
element_count = int(itemlist.size()); element_count = int(getCount());
vbar->setMaximum (element_count - getClientHeight()); vbar->setMaximum (element_count - getClientHeight());
vbar->setPageSize (element_count, getClientHeight()); vbar->setPageSize (element_count, getClientHeight());
vbar->setX (getWidth()); vbar->setX (getWidth());
@ -1235,42 +1262,54 @@ void FListView::drawColumnLabels()
//---------------------------------------------------------------------- //----------------------------------------------------------------------
void FListView::drawList() void FListView::drawList()
{ {
uInt start, end; uInt page_height, y;
bool isFocus; bool is_focus;
constFObjectIterator iter; FObjectIterator iter;
if ( itemlist.empty() || getHeight() <= 2 || getWidth() <= 4 ) if ( itemlist.empty() || getHeight() <= 2 || getWidth() <= 4 )
return; return;
isFocus = ((flags & fc::focus) != 0); y = 0;
start = 0; page_height = uInt(getHeight() - 2);
end = uInt(getHeight() - 2); is_focus = ((flags & fc::focus) != 0);
iter = index2iterator(yoffset);
if ( end > itemlist.size() ) while ( iter != itemlist.end() && y < page_height )
end = uInt(itemlist.size());
iter = index2iterator(int(start) + yoffset);
for (uInt y = start; y < end; y++)
{ {
bool isCurrentLine = bool( y + uInt(yoffset) + 1 == uInt(current) ); bool is_current_line = bool( y + uInt(yoffset) + 1 == uInt(current) );
const FListViewItem* item = static_cast<FListViewItem*>(*iter);
setPrintPos (2, 2 + int(y)); setPrintPos (2, 2 + int(y));
setColor (wc.list_fg, wc.list_bg);
FListViewItem* item = static_cast<FListViewItem*>(*iter);
if ( isCurrentLine ) // Draw one FListViewItem
drawListLine (item, is_focus, is_current_line);
if ( is_focus && is_current_line )
setCursorPos (3, 2 + int(y)); // first character
y++;
nextElement(iter);
}
}
//----------------------------------------------------------------------
void FListView::drawListLine ( const FListViewItem* item
, bool is_focus
, bool is_current )
{
setColor (wc.list_fg, wc.list_bg);
if ( is_current )
{ {
if ( isFocus && getMaxColor() < 16 ) if ( is_focus && getMaxColor() < 16 )
setBold(); setBold();
if ( isMonochron() ) if ( isMonochron() )
unsetBold(); unsetBold();
if ( isFocus ) if ( is_focus )
{ {
setColor ( wc.current_element_focus_fg setColor ( wc.current_element_focus_fg
, wc.current_element_focus_bg ); , wc.current_element_focus_bg );
setCursorPos (3, 2 + int(y)); // first character
} }
else else
setColor ( wc.current_element_fg setColor ( wc.current_element_fg
@ -1283,7 +1322,7 @@ void FListView::drawList()
{ {
if ( isMonochron() ) if ( isMonochron() )
setReverse(true); setReverse(true);
else if ( isFocus && getMaxColor() < 16 ) else if ( is_focus && getMaxColor() < 16 )
unsetBold(); unsetBold();
} }
@ -1363,9 +1402,6 @@ void FListView::drawList()
for (; i < uInt(getWidth() - nf_offset - 2); i++) for (; i < uInt(getWidth() - nf_offset - 2); i++)
print (' '); print (' ');
++iter;
}
} }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
@ -1398,6 +1434,14 @@ void FListView::recalculateVerticalBar (int element_count)
vbar->setVisible(); vbar->setVisible();
} }
//----------------------------------------------------------------------
FObject::FObjectIterator FListView::appendItem (FListViewItem* item)
{
addChild (item);
itemlist.push_back (item);
return --itemlist.end();
}
//---------------------------------------------------------------------- //----------------------------------------------------------------------
void FListView::processClick() void FListView::processClick()
{ {
@ -1415,7 +1459,7 @@ void FListView::cb_VBarChange (FWidget*, data_ptr)
{ {
FScrollbar::sType scrollType; FScrollbar::sType scrollType;
int distance = 1; int distance = 1;
int element_count = int(itemlist.size()); int element_count = int(getCount());
int yoffset_before = yoffset; int yoffset_before = yoffset;
int yoffset_end = element_count - getClientHeight(); int yoffset_end = element_count - getClientHeight();
scrollType = vbar->getScrollType(); scrollType = vbar->getScrollType();

View File

@ -17,11 +17,11 @@
// ▕▁▁▁▁▁▁▁▁▏ // ▕▁▁▁▁▁▁▁▁▏
// ▲ // ▲
// │ // │
// ▕▔▔▔▔▔▔▔▔▔▏ // ▕▔▔▔▔▔▔▔▔▔▏ ▕▔▔▔▔▔▔▔▔▔▏
// ▕ FWidget ▏ // ▕ FWidget ▏ ▕ FObject ▏
// ▕▁▁▁▁▁▁▁▁▁▏ // ▕▁▁▁▁▁▁▁▁▁▏ ▕▁▁▁▁▁▁▁▁▁▏
// ▲ // ▲
// │ // │
// ▕▔▔▔▔▔▔▔▔▔▔▔▏1 *▕▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▏ // ▕▔▔▔▔▔▔▔▔▔▔▔▏1 *▕▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▏
// ▕ FListView ▏- - - -▕ FListViewItem ▏ // ▕ FListView ▏- - - -▕ FListViewItem ▏
// ▕▁▁▁▁▁▁▁▁▁▁▁▏ ▕▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▏ // ▕▁▁▁▁▁▁▁▁▁▁▁▏ ▕▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▏
@ -77,7 +77,8 @@ class FListViewItem : public FObject
bool isExpand(); bool isExpand();
// Methods // Methods
void insert (FListViewItem*); FObjectIterator insert (FListViewItem*);
FObjectIterator insert (FListViewItem*, FObjectIterator);
void expand(); void expand();
void collapse(); void collapse();
@ -86,6 +87,8 @@ class FListViewItem : public FObject
bool isExpandable(); bool isExpandable();
// Methods // Methods
FObjectIterator appendItem (FListViewItem*);
void replaceControlCodes();
int getVisibleLines(); int getVisibleLines();
// Data Member // Data Member
@ -140,6 +143,7 @@ class FListView : public FWidget
// Accessors // Accessors
const char* getClassName() const; const char* getClassName() const;
uInt getCount() const;
fc::text_alignment getColumnAlignment (int) const; fc::text_alignment getColumnAlignment (int) const;
FString getColumnText (int) const; FString getColumnText (int) const;
FListViewItem* getCurrentItem(); FListViewItem* getCurrentItem();
@ -225,11 +229,14 @@ class FListView : public FWidget
void draw(); void draw();
void drawColumnLabels(); void drawColumnLabels();
void drawList(); void drawList();
void drawListLine (const FListViewItem*, bool, bool);
void recalculateHorizontalBar (int); void recalculateHorizontalBar (int);
void recalculateVerticalBar (int); void recalculateVerticalBar (int);
FObjectIterator appendItem (FListViewItem*);
void processClick(); void processClick();
void processChanged(); void processChanged();
FObjectIterator index2iterator (int); FObjectIterator index2iterator (int);
void nextElement (FObjectIterator&);
// Callback methods // Callback methods
void cb_VBarChange (FWidget*, data_ptr); void cb_VBarChange (FWidget*, data_ptr);
@ -265,6 +272,10 @@ class FListView : public FWidget
inline const char* FListView::getClassName() const inline const char* FListView::getClassName() const
{ return "FListView"; } { return "FListView"; }
//----------------------------------------------------------------------
inline uInt FListView::getCount() const
{ return uInt(itemlist.size()); }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
inline FListViewItem* FListView::getCurrentItem() inline FListViewItem* FListView::getCurrentItem()
{ {
@ -319,4 +330,10 @@ inline FObject::FObjectIterator FListView::index2iterator (int index)
return iter; return iter;
} }
//----------------------------------------------------------------------
inline void FListView::nextElement (FObjectIterator& iter)
{
++iter;
}
#endif // FLISTVIEW_H #endif // FLISTVIEW_H

View File

@ -17,11 +17,9 @@ const FString* fc::empty_string = 0;
FObject::FObject (FObject* parent) FObject::FObject (FObject* parent)
: widget_object(false) : widget_object(false)
, parent_obj(parent) , parent_obj(parent)
, children_list() , children_list() // no children yet
, has_parent(false) , has_parent(false)
{ {
children_list.clear(); // no children yet
if ( parent_obj ) // add object to parent if ( parent_obj ) // add object to parent
parent_obj->addChild(this); parent_obj->addChild(this);

View File

@ -999,7 +999,7 @@ void FVTerm::resizeArea ( int offset_left, int offset_top
default_char.bg_color = fc::Default; default_char.bg_color = fc::Default;
default_char.attr.byte[0] = 0; default_char.attr.byte[0] = 0;
default_char.attr.byte[1] = 0; default_char.attr.byte[1] = 0;
default_char.attr.byte[3] = 0; default_char.attr.byte[2] = 0;
std::fill_n (area->text, area_size, default_char); std::fill_n (area->text, area_size, default_char);