home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C Programming Starter Kit 2.0
/
SamsPublishing-CProgrammingStarterKit-v2.0-Win31.iso
/
bc45
/
owlsrc.pak
/
LISTBOX.CPP
< prev
next >
Wrap
C/C++ Source or Header
|
1997-07-23
|
21KB
|
902 lines
//----------------------------------------------------------------------------
// ObjectWindows
// (C) Copyright 1991, 1994 by Borland International, All Rights Reserved
//
// Implementation of class TListBox and TlistBoxData.
//----------------------------------------------------------------------------
#pragma hdrignore SECTION
#include <owl/owlpch.h>
#include <owl/listbox.h>
#include <stdlib.h>
#include <cstring.h>
#if !defined(SECTION) || SECTION == 1
#define MULTIPLESEL (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)
//
// TListBoxData constructor
//
TListBoxData::TListBoxData()
:
Strings(10, 0, 10),
ItemDatas(10, 0, 10),
SelIndices(1, 0, 10)
{
}
//
// TListBoxData destructor
//
TListBoxData::~TListBoxData()
{
}
//
// adds "str" to "Strings"
//
// if "isSelected" is true, marks it as selected
//
void
TListBoxData::AddString(const char* str, bool isSelected)
{
Strings.Add(str);
if (isSelected)
Select(Strings.GetItemsInContainer()-1);
}
//
// adds str and associated item data to strings and datas
//
void
TListBoxData::AddStringItem(const char* str, uint32 itemData, bool isSelected)
{
ItemDatas.Add(itemData);
AddString(str, isSelected);
}
//
// selects an item at a given index.
//
void
TListBoxData::Select(int index)
{
if (index != LB_ERR)
SelIndices.Add(index);
}
//
// adds "str" to selection lists if it is in Strings
//
void
TListBoxData::SelectString(const char far* str)
{
for (int i = 0; i < Strings.GetItemsInContainer(); i++)
if (strcmp(Strings[i].c_str(), str) == 0) {
Select(i);
break;
}
}
//
// returns the length of the string at the passed selection index
// excluding the terminating 0
//
int
TListBoxData::GetSelStringLength(int index) const
{
if (index >= 0 && index < GetSelCount())
return Strings[SelIndices[index]].length();
return -1;
}
//
// copies the string at the passed selection index into buffer
//
// bufferSize includes the terminating 0
//
void
TListBoxData::GetSelString(char far* buffer, int bufferSize, int index) const
{
if (bufferSize > 0) {
if (index < 0 || index >= GetSelCount())
*buffer = 0;
else {
strncpy(buffer, Strings[SelIndices[index]].c_str(), bufferSize-1);
buffer[bufferSize - 1] = 0;
}
}
}
//
// copies the string at the passed index in SelStrings into str
//
void
TListBoxData::GetSelString(string& str, int index) const
{
if (index >= 0 && index < GetSelCount())
str = Strings[SelIndices[index]];
else
str = "";
}
//----------------------------------------------------------------------------
TStringArray::TStringArray(int upper, int lower, int delta)
:
Data(upper, lower, delta)
{
}
int TStringArray::LowerBound() const
{
return Data.LowerBound();
}
int TStringArray::UpperBound() const
{
return Data.UpperBound();
}
unsigned TStringArray::ArraySize() const
{
return Data.ArraySize();
}
int TStringArray::IsFull() const
{
return Data.IsFull();
}
int TStringArray::IsEmpty() const
{
return Data.IsEmpty();
}
unsigned TStringArray::GetItemsInContainer() const
{
return Data.GetItemsInContainer();
}
int TStringArray::Add(const string& t)
{
return Data.Add(t);
}
int TStringArray::Detach(const string& t)
{
return Data.Detach(t);
}
int TStringArray::Detach(int loc)
{
return Data.Detach(loc);
}
int TStringArray::Destroy(const string& t)
{
return Detach(t);
}
int TStringArray::Destroy(int loc)
{
return Detach(loc);
}
int TStringArray::HasMember(const string& t) const
{
return Data.HasMember(t);
}
int TStringArray::Find(const string& t) const
{
return Data.Find(t);
}
string& TStringArray::operator [](int loc)
{
return Data[loc];
}
string& TStringArray::operator [](int loc) const
{
return Data[loc];
}
void TStringArray::ForEach(IterFunc iter, void* args)
{
Data.ForEach(iter, args);
}
string* TStringArray::FirstThat(CondFunc cond, void* args) const
{
return Data.FirstThat(cond, args);
}
string* TStringArray::LastThat(CondFunc cond, void* args) const
{
return Data.LastThat(cond, args);
}
void TStringArray::Flush()
{
Data.Flush();
}
//----------------------------------------------------------------------------
TIntArray::TIntArray(int upper, int lower, int delta)
:
Data(upper, lower, delta)
{
}
int TIntArray::LowerBound() const
{
return Data.LowerBound();
}
int TIntArray::UpperBound() const
{
return Data.UpperBound();
}
unsigned TIntArray::ArraySize() const
{
return Data.ArraySize();
}
int TIntArray::IsFull() const
{
return Data.IsFull();
}
int TIntArray::IsEmpty() const
{
return Data.IsEmpty();
}
unsigned TIntArray::GetItemsInContainer() const
{
return Data.GetItemsInContainer();
}
int TIntArray::Add(const TInt& t)
{
return Data.Add(t);
}
int TIntArray::Detach(const TInt& t)
{
return Data.Detach(t);
}
int TIntArray::Detach(int loc)
{
return Data.Detach(loc);
}
int TIntArray::Destroy(const TInt& t)
{
return Detach(t);
}
int TIntArray::Destroy(int loc)
{
return Detach(loc);
}
int TIntArray::HasMember(const TInt& t) const
{
return Data.HasMember(t);
}
int TIntArray::Find(const TInt& t) const
{
return Data.Find(t);
}
TInt& TIntArray::operator [](int loc)
{
return Data[loc];
}
TInt& TIntArray::operator [](int loc) const
{
return Data[loc];
}
void TIntArray::ForEach(IterFunc iter, void* args)
{
Data.ForEach(iter, args);
}
TInt* TIntArray::FirstThat(CondFunc cond, void* args) const
{
return Data.FirstThat(cond, args);
}
TInt* TIntArray::LastThat(CondFunc cond, void* args) const
{
return Data.LastThat(cond, args);
}
void TIntArray::Flush()
{
Data.Flush();
}
//----------------------------------------------------------------------------
TDwordArray::TDwordArray(int upper, int lower, int delta)
:
Data(upper, lower, delta)
{
}
int TDwordArray::LowerBound() const
{
return Data.LowerBound();
}
int TDwordArray::UpperBound() const
{
return Data.UpperBound();
}
unsigned TDwordArray::ArraySize() const
{
return Data.ArraySize();
}
int TDwordArray::IsFull() const
{
return Data.IsFull();
}
int TDwordArray::IsEmpty() const
{
return Data.IsEmpty();
}
unsigned TDwordArray::GetItemsInContainer() const
{
return Data.GetItemsInContainer();
}
int TDwordArray::Add(const uint32& t)
{
return Data.Add(t);
}
int TDwordArray::Detach(const uint32& t)
{
return Data.Detach(t);
}
int TDwordArray::Detach(int loc)
{
return Data.Detach(loc);
}
int TDwordArray::Destroy(const uint32& t)
{
return Detach(t);
}
int TDwordArray::Destroy(int loc)
{
return Detach(loc);
}
int TDwordArray::HasMember(const uint32& t) const
{
return Data.HasMember(t);
}
int TDwordArray::Find(const uint32& t) const
{
return Data.Find(t);
}
uint32& TDwordArray::operator [](int loc)
{
return Data[loc];
}
uint32& TDwordArray::operator [](int loc) const
{
return Data[loc];
}
void TDwordArray::ForEach(IterFunc iter, void* args)
{
Data.ForEach(iter, args);
}
uint32* TDwordArray::FirstThat(CondFunc cond, void* args) const
{
return Data.FirstThat(cond, args);
}
uint32* TDwordArray::LastThat(CondFunc cond, void* args) const
{
return Data.LastThat(cond, args);
}
void TDwordArray::Flush()
{
Data.Flush();
}
//----------------------------------------------------------------------------
//
// constructor for TListBox
//
// initializes its data fields using parameters passed and default values
//
// by default, an MS-Windows listbox associated with the TListBox will:
// - be visible upon creation
// - have a border and a vertical scrollbar
// - maintain entries in alphabetical order
// - notify its parent when a selection is made
//
TListBox::TListBox(TWindow* parent,
int id,
int x, int y, int w, int h,
TModule* module)
:
TControl(parent, id, 0, x, y, w, h, module)
{
Attr.Style |= LBS_STANDARD;
}
TListBox::TListBox(TWindow* parent,
int resourceId,
TModule* module)
:
TControl(parent, resourceId, module)
{
}
char far*
TListBox::GetClassName()
{
return "LISTBOX";
}
//
// transfers state information for a TListBox
//
// transfers the items and selection of the list to or from a transfer
// buffer if tdSetData or tdGetData, respectively, is passed as the
// direction
//
// buffer should point to a TListBoxData which points to the data to be
// transferred
//
// Transfer returns the size of TListBoxData
//
// to retrieve the size without transferring data, pass tdSizeData as the
// direction
//
uint
TListBox::Transfer(void* buffer, TTransferDirection direction)
{
long style = GetWindowLong(GWL_STYLE);
TListBoxData* listBoxData = (TListBoxData*)buffer;
if (direction == tdGetData) {
//
// first, clear out Strings array and fill with contents of list box
//
listBoxData->Clear();
//
// pre-calculate max string length so that one big buffer can be used
//
int count = GetCount();
int maxStrLen = 0;
for (int i = 0; i < count; i++) {
int strLen = GetStringLen(i);
if (strLen > maxStrLen)
maxStrLen = strLen;
}
//
// Get each string and item data in the listbox & add to listboxdata
//
char* tmpStr = new char[maxStrLen+1];
for (i = 0; i < GetCount(); i++) {
GetString(tmpStr, i);
listBoxData->AddStringItem(tmpStr, GetItemData(i), false);
}
delete tmpStr;
//
// update transfer data with new selected item(s)
//
listBoxData->ResetSelections();
if (!(style & MULTIPLESEL)) {
//
// single selection
//
listBoxData->Select(GetSelIndex());
}
else {
//
// multiple selection
//
int selCount = GetSelCount();
if (selCount > 0) {
int* selections = new int[selCount];
GetSelIndexes(selections, selCount);
// Select each item by index
//
for (int selIndex = 0; selIndex < selCount; selIndex++)
listBoxData->Select(selections[selIndex]);
delete selections;
}
}
}
else if (direction == tdSetData) {
ClearList();
//
// add each string, item data and selections in listBoxData to list box
//
const int noSelection = -1;
int selCount = listBoxData->GetSelCount(); // for multi selection
int selIndex = noSelection; // for single selection
for (int i = 0; i < listBoxData->GetStrings().GetItemsInContainer(); i++) {
// index may be different from i when the listbox is sorted.
//
int index = AddString(listBoxData->GetStrings()[i].c_str());
SetItemData(index, listBoxData->GetItemDatas()[i]);
if (style & MULTIPLESEL) {
for (int j = 0; j < selCount; j++)
if (listBoxData->GetSelIndices()[j] == i) {
SetSel(index, true);
break;
}
}
else {
if (listBoxData->GetSelIndices()[0] == i)
selIndex = index;
else
// inserted something before item and the item to select has been
// pushed further down in the list.
//
if (selIndex != noSelection && index <= selIndex)
selIndex++;
}
}
if (selIndex != noSelection && !(style & MULTIPLESEL))
SetSelIndex(selIndex);
}
return sizeof(TListBoxData);
}
//
// returns the index of the first string in the associated listbox
// which is the same as the passed string
//
// searches for a match beginning at the passed indexStart
//
// if a match is not found after the last string has been compared,
// the search continues from the beginning of the list until a match
// is found or until the list has been completely traversed
//
// searches from beginning of list when -1 is passed as the index
//
// returns the index of the selected string; a negative value is returned
// if an error occurs
//
// for single or multiple-selection list boxes
//
int
TListBox::FindExactString(const char far* findStr, int indexStart) const
{
bool found = false;
int firstMatch = indexStart = FindString(findStr, indexStart);
do {
if (indexStart > -1) {
char* tmpStr = new char[GetStringLen(indexStart) + 1];
GetString(tmpStr, indexStart);
if (strcmp(tmpStr, findStr) == 0)
found = true;
else
indexStart = FindString(findStr, indexStart);
delete tmpStr;
}
} while (!found && indexStart != firstMatch);
return found ? indexStart : -1;
}
//
// for use with single-selection list boxes (and combo boxes)
//
// retrieves the text of the string which is selected in the associated
// listbox
//
// returns the number of characters copied; -1 is returned if no string
// is selected or this is a multiple-selection list box
//
// since the Windows function is not passed a size parameter, we have to
// allocate a string to hold the largest string (gotten from a query), and
// copy a part of it
//
int
TListBox::GetSelString(char far* str, int maxChars) const
{
int index = GetSelIndex();
if (index > -1) {
int length = GetStringLen(index);
if (maxChars >= length)
return GetString(str, index);
else {
char* tmpStr = new char[length + 1];
if (tmpStr) {
GetString(tmpStr, index);
strncpy(str, tmpStr, maxChars);
delete tmpStr;
return maxChars;
}
}
}
return -1;
}
//
// returns the number of selected items in the list box. For
// multiple-selection list boxes only
//
int
TListBox::GetSelCount() const
{
if (!(GetWindowLong(GWL_STYLE) & MULTIPLESEL))
return GetSelIndex() < 0 ? 0 : 1;
//
// multiple-selection list box
//
return (int)CONST_CAST(TListBox*,this)->HandleMessage(LB_GETSELCOUNT);
}
//
// retrieves the text of the strings which are selected in the
// associated listbox
//
// returns the number of items put into Strings. -1 is returned if this is
// not a multiple-selection list box
//
// since the Windows function is not passed a size parameter, we have to
// allocate a string to hold the largest string (gotten from a query), and
// copy a part of it
//
// only for use with multiple-selection list boxes
//
int
TListBox::GetSelStrings(char far** strs, int maxCount, int maxChars) const
{
if (!(GetWindowLong(GWL_STYLE) & MULTIPLESEL))
return -1;
int i = GetSelCount();
if (i < maxCount)
maxCount = i;
if (maxCount > 0) {
int* selections = new int[maxCount];
GetSelIndexes(selections, maxCount);
for (int selIndex = 0; selIndex < maxCount; selIndex++) {
int tmpStrLen = GetStringLen(selections[selIndex]);
if (maxChars >= tmpStrLen)
GetString(strs[selIndex], selections[selIndex]);
else {
char* tmpStr = new char[tmpStrLen+1];
if (tmpStr) {
GetString(tmpStr, selections[selIndex]);
strncpy(strs[selIndex], tmpStr, maxChars);
delete tmpStr;
}
}
}
delete selections;
}
return maxCount;
}
//
// selects the first string in the associated listbox following the
// passed index which begins with the passed string
//
// searches for a match beginning at the passed Index. if a match is not
// found after the last string has been compared, the search continues
// from the beginning of the list until a match is found or until the list
// has been completely traversed
//
// searches from beginning of list when -1 is passed as the index
//
// returns the index of the selected string. a negative value is returned
// if an error occurs
//
// only for single-selection list boxes
//
int
TListBox::SetSelString(const char far* findStr, int indexStart)
{
if (!(GetWindowLong(GWL_STYLE) & MULTIPLESEL))
return (int)HandleMessage(LB_SELECTSTRING, indexStart, (LPARAM)findStr);
return -1;
}
//
// selects the strings in the associated list box which begin with
// the passed prefixes
//
// for each string the search begins at the beginning of the list
// and continues until a match is found or until the list has been
// completely traversed
//
// if ShouldSet is true, the matched strings are selected and highlighted;
// otherwise the highlight is removed from the matched strings and they
// are no longer selected
//
// returns the number of strings successfully selected or deselected
//
// if NumSelections is less than zero, all strings are selected or deselected
// and a negative value is returned on failure
//
// only for multiple-selection list boxes (-1 is returned if this is not
// a multiple-selection list box)
//
int
TListBox::SetSelStrings(const char far** strs, int numSelections, bool shouldSet)
{
if (!(GetWindowLong(GWL_STYLE) & MULTIPLESEL))
return -1;
if (numSelections < 0)
return SetSel(-1, shouldSet);
int successes = 0;
for (int i = 0; i < numSelections; i++) {
int selIndex;
if ((selIndex = FindString(strs[i], -1)) > -1)
if (SetSel(selIndex, shouldSet) > -1)
successes++;
}
return successes;
}
//
// returns the index of the selected string in the associated listbox
//
// a negative value is returned if no string is selected or this
// is a multiple-selection list box
//
// only for single-selection list boxes
//
int
TListBox::GetSelIndex() const
{
if (!(GetWindowLong(GWL_STYLE) & MULTIPLESEL))
return (int)CONST_CAST(TListBox*,this)->HandleMessage(LB_GETCURSEL);
return -1;
}
//
// fills indexes with the indexes of up to maxCount selected strings
//
// returns number of items put in the array(-1 for single-selection
// list boxes)
//
int
TListBox::GetSelIndexes(int* indexes, int maxCount) const
{
if (!(GetWindowLong(GWL_STYLE) & MULTIPLESEL))
return -1;
return (int)CONST_CAST(TListBox*,this)->HandleMessage(LB_GETSELITEMS,
maxCount,
(LPARAM)indexes);
}
// selects the string at passed index in the associated listbox and
// forces the string into view
//
// clears selection when -1 is passed as the index. a negative value is
// returned if an error occurs
//
// only for single-selection list boxes
//
int
TListBox::SetSelIndex(int index)
{
if (!(GetWindowLong(GWL_STYLE) & MULTIPLESEL))
return (int)HandleMessage(LB_SETCURSEL, index);
return -1;
}
//
// selects/deselects the strings in the associated list box at the
// passed indexes
//
// if ShouldSet is true, the indexed strings are selected and highlighted;
// otherwise the highlight is removed and they are no longer selected
//
// returns the number of strings successfully selected or deselected(-1
// if not a multiple-selection list box)
//
// if NumSelections is less than zero, all strings are selected or deselected
// and a negative value is returned on failure
//
// only for multiple-selection list boxes
//
int
TListBox::SetSelIndexes(int* indexes, int numSelections, bool shouldSet)
{
int successes = 0;
if (!(GetWindowLong(GWL_STYLE) & MULTIPLESEL))
return -1; // including if it's a combobox
if (numSelections < 0)
return (int)HandleMessage(LB_SETSEL, shouldSet, -1);
else {
for (int i = 0; i < numSelections; i++)
if ((int)HandleMessage(LB_SETSEL, shouldSet, indexes[i]) > -1)
successes++;
}
return successes;
}
#endif
#if !defined(SECTION) || SECTION == 2
IMPLEMENT_STREAMABLE1(TListBox, TControl);
//
// reads an instance of TListBox from the supplied ipstream
//
void*
TListBox::Streamer::Read(ipstream& is, uint32 /*version*/) const
{
ReadBaseObject((TControl*)GetObject(), is);
return GetObject();
}
//
// writes the TListBox to the supplied opstream
//
void
TListBox::Streamer::Write(opstream& os) const
{
WriteBaseObject((TControl*)GetObject(), os);
}
#endif