UPLOAD - DOSUIT07.ZIP - LIST.CPP

 
Output of file : LIST.CPP contained in archive : DOSUIT07.ZIP

#ifdef ALL
#define LISTA
#define LISTB
#define LISTC
#define LISTD
#define LISTE
#define LISTF
#define LISTG
#define LISTH
#define LISTI
#define LISTJ
#define LISTK
#define LISTL
#define LISTM
#define LISTN
#endif
#ifndef LISTA
#define LIBRARY_MODULE
#endif

#include "list.hpp"
#include "window.hpp"
#include "event.hpp"
#include
#include

#ifdef LISTA
static ListCollection *sortedCollection;

static int cdecl scompare(const void *v1,const void *v2)
{
return sortedCollection->compare((ListElement *)*((void **)v1),(ListElement *)*((void **)v2));
}

void ListCollection::resort()
{
if(size() > 0)
{
ASSERT(sortedCollection == 0 /* Recursive call to Collection::sort() */);
sortedCollection = this;
qsort(list,size(),sizeof(void**),scompare);
sortedCollection = 0;
}
}

int ListCollection::compare(const ListElement *v1, const ListElement *v2) const
{
return compfn ? compfn(v1,v2) : 0;
}

int ListCollection::add(ListElement *c)
{
if(!expand())
return -1;
for(int i = 0; i < size() && compare(c,(ListElement *)list[i]) >= 0; i++)
; // find where to put it
Collection::add(c,i);
return i;
}
#endif

#ifdef LISTB
ListCollection::ListCollection(int hintSize)
: Collection(hintSize), compfn(0)
{
}
#endif

#ifdef LISTC
ListCollection::ListCollection(const ListCollection& c)
: Collection(c), compfn(c.compfn)
{
}
#endif

#ifdef LISTD
void ListCollection::deleteall()
{
ListElement *v;

while((v = getlast()) != 0)
delete v;
}
#endif

#ifdef LISTE
ListIterator::ListIterator(const ListCollection& s,int bk)
: Iterator(s,bk)
{
}
#endif

#ifdef LISTF
ListIterator::ListIterator(const ListCollection& s,const ListElement *e,int bk)
: Iterator(s,e,bk)
{
}
#endif

#ifdef LISTG
List::List(ListCollection &c, const char *n, const BorderFlag b)
: Control(3,3,n), collection(c), topItem(0), selected(-1),
bflags(BorderFlag(b & ~BFtabstop))
{
if(b & BFtabstop)
setFlag(StateFlag(SFshowfocus|SFtabstop));
}
#endif

#ifdef LISTH
List::List(ListCollection &c,coord width,coord height,
const char *n,const BorderFlag b)
: Control(width+2,height+2,n), collection(c), topItem(0), selected(-1),
bflags(BorderFlag(b & ~BFtabstop))
{
if(b & BFtabstop)
setFlag(StateFlag(SFshowfocus|SFtabstop));
}
#endif

#ifdef LISTI
int List::select(const int s)
{
if(s < 0 || s >= collection.size())
return 0;
if(line() == s)
return 1;
if(line() >= 0)
deselect();
dirtyItem();
selected = s;
dirtyItem();
makeVisible(s);
return 1;
}

void List::deselect()
{
if(line() >= 0)
{
dirtyItem();
selected = -1;
}
}

int List::pick()
{
return 0;
}

int List::escape()
{
return 0;
}

void List::setheight(const coord w)
{
if(w == height())
return;
Control::setheight(w);
if(line() >= 0)
makeVisible(line());
}

coord List::minwidth() const
{
ListElement *o;
ListIterator next(collection);

coord mw = (bflags & BFtitle) ? strlen(name()) : 0;
while((o = next()) != 0)
{
coord w = o->minwidth();
if(mw < w)
mw = w;
}
if(!mw)
mw = 1;
return mw + 2;
}

coord List::maxwidth() const
{
ListElement *o;
ListIterator next(collection);

coord mw = (bflags & BFtitle) ? strlen(name()) : 0;
while((o = next()) != 0)
{
coord w = o->maxwidth();
if(mw < w)
mw = w;
}
if(!mw)
mw = 1;
return mw + 2;
}

coord List::minheight() const
{
return 3;
}

coord List::maxheight() const
{
coord h = collection.size();
if(!h)
h = 1;
h += 2;
if(h < minheight())
h = minheight();
return h;
}

void List::paint(Rectangle r)
{
r &= *this;
window->fillrect(r,getcolor() & ~SFfocus,' ');
window->drawbox(*this,r,getcolor(),bflags,name());

Rectangle p(left()+1,r.top(),right()-1,r.top());
int l = topItem;

if(!r.intersects(p))
return;
if(r.top() > top()) // only drawing part of list
l += r.top() - (top() + 1);
else // list items start at top() + 1
p.move(0,1);
int botline = r.bottom();
if(botline >= bottom())
botline = bottom() - 1;

for( ; p.top() <= botline; l++, p.move(0,1))
{
ListElement *o = collection[l];

if(!o)
break;

if(l == line())
{
if(r.left() <= left())
{
Point q = { left(), p.top() };
window->printstring(q,gethighlight(),RightArrow);
}
Rectangle c(p);
c &= r;
window->fillrect(c,SFhighlight,' ');
}
o->paint(p, window, r, (l == line()) ? SFhighlight : SFnormal);
}
}

int List::setfocus(int tabstop)
{
if(testcFlag(CFfocus))
return 1;
if(!Control::setfocus(tabstop))
return 0;
if(line() == -1)
select(topItem);
return 1;
}

void List::resetfocus()
{
if(!testcFlag(CFfocus))
return;
Control::resetfocus();
}

int List::leftdown(MouseEvent& e)
{
int r = mousemove(e);

if(r)
{
setfocus();
setmoufocus();
}
else
r = Control::leftdown(e);
return r;
}

int List::leftup(MouseEvent &)
{
resetmoufocus();
return 0;
}

int List::leftdoubleclick(MouseEvent &e)
{
if(selected >= topItem)
{
Rectangle r(left() + 1, top() + selected - topItem + 1,
right() - 1, top() + selected - topItem + 1);

if(r.encloses(e.at()) && pick())
return 1;
}
return Control::leftdoubleclick(e);
}

int List::rightclick(MouseEvent &e)
{
setfocus();
return escape() ? 1 : Control::rightclick(e);
}

int List::mousemove(MouseEvent &e)
{
if(!testFlag(SFmousein))
return Control::mousemove(e);
coord c = e.at().y;
if(c <= top())
{
if(topItem > 0)
{
select(topItem - 1); // scroll up
setmoufocus(1); // keep sending even if mouse not moved
}
else
setmoufocus(0); // don't keep sending once reached top
}
else if(c >= bottom())
{
int l = topItem + height() - 2;
if(l < collection.size())
{
select(l); // scroll down
setmoufocus(1); // keep sending even if mouse not moved
}
else
setmoufocus(0); // don't keep sending once reached top
}
else // inside - just select item
{
setmoufocus();
int l = topItem + c - (top() + 1);
if(l == line())
return 1;
select(topItem + c - (top() + 1));
}
return 1;
}

int List::mouseexit(MouseEvent &)
{
deselect();
return 0;
}

int List::kbdevent(KeyboardEvent& e)
{
switch(e.value())
{
case Kup:
select(line() - 1);
break;
case Kdown:
select(line() + 1);
break;
case Kpgup:
{
if(topItem == 0)
break; // already at top of list

int l = topItem;

deselect();
scrollup(height() - 3);
select(l);
}
break;
case Kpgdn:
{
int l = topItem + height() - 3;

if(l + 2 > collection.size())
break; // already at end of list

deselect();
scrolldown(height() - 3);
select(l);
}
break;
case Khome:
select(0);
break;
case Kend:
select(collection.size() - 1);
break;
case '\r':
case '\n':
if(line() >= 0 && pick())
break;
case Kesc:
if(escape())
break;
default:
return Control::kbdevent(e);
}
return 1;
}

#ifdef NINSPECT
char *List::inspectinfo(char *buf,const char *s) const
{
return "";
}
#else
char *List::inspectinfo(char *buf,const char *s) const
{
if(!s)
s = "List";
buf = Control::inspectinfo(buf,s);
strcat(buf,form("%d items, top %d, selected = %d\n",
collection.size(),topItem,selected));
return buf;
}
#endif

void List::dirtyItem()
{
int l = line();
if(l < 0)
return;
l -= topItem;
if(l >= 0 && l <= height() - 2)
dirty(Rectangle(left(),top()+l+1,right()-1,top()+l+1));
}

void List::scrollup(int nlines)
{
if(nlines > topItem)
nlines = topItem;
if(nlines <= 0)
return; // can't scroll before start
topItem -= nlines;
if(testcFlag(CFdirty))
return; // don't bother updating now
if(nlines >= (height() - 2) / 2)
{ // got to update most lines, anyway
dirty();
return;
}

Rectangle r(left(),top()+1,right()-1,bottom()-1);

window->scroll(r,getcolor(),-nlines);
moveDirtyArea(0,nlines); // dirty area moved by scroll
r.setheight(nlines);
dirty(r);
}

void List::scrolldown(int nlines)
{
if(topItem + nlines + height() - 2 > collection.size())
nlines = collection.size() - (topItem + height() - 2);
if(nlines <= 0)
return;
topItem += nlines;
if(testcFlag(CFdirty))
return;
if(nlines >= (height() - 2) / 2)
{ // got to update most lines, anyway
dirty();
return;
}

Rectangle r(left(),top()+1,right()-1,bottom()-1);

window->scroll(r,getcolor(),nlines);
moveDirtyArea(0,-nlines); // dirty area moved by scroll
r.setheight(nlines);
r.position(r.left(),bottom()-nlines);
dirty(r);
}

void List::makeVisible(int item)
{
if(item < 0 || item >= size())
return;
if(item < topItem)
scrollup(topItem - item);
else if(item > topItem + height() - 3)
scrolldown(item - (topItem + height() - 3));
}
#endif

#ifdef LISTJ
void List::changeCollection()
{
if(topItem && topItem + height() - 2 > collection.size())
{
topItem = 0;
dirty();
}
if(line() >= collection.size())
deselect();
}
#endif

#ifdef LISTK
int List::remove(int itemno)
{
ListElement *o = collection[itemno];
int l = line();

if(!o)
return 0;
deselect();
if(!collection.remove(o))
return 0;
dirty();
if(l < 0)
return 1;
if(itemno < l || (itemno == l && l >= size()))
l--;
select(l);
return 1;
}
#endif

#ifdef LISTL
int List::add(ListElement *o)
{
int l = line();

deselect();

int a = collection.add(o);

if(a < 0)
return a;
if(l >= 0)
{
if(a <= l)
l++;
select(l);
}
dirty();
return a;
}
#endif

#ifdef LISTM
void List::resize(int changeheight)
{
setwidth(minwidth());
if(changeheight || height() > maxheight())
setheight(maxheight());
}
#endif

#ifdef LISTN
ListElement::ListElement(const char *name)
: namestring(name)
{
}

ListElement::~ListElement()
{
}

coord ListElement::minwidth() const
{
return strlen(name());
}

coord ListElement::maxwidth() const
{
return minwidth();
}

void ListElement::paint(const Rectangle &at, Window *w, const Rectangle &clip,
color col)
{
w->printstring(at.topleft(), clip, col, name());
}
#endif