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 >
C/C++ Source or Header  |  1997-07-23  |  21KB  |  902 lines

  1. //----------------------------------------------------------------------------
  2. // ObjectWindows
  3. // (C) Copyright 1991, 1994 by Borland International, All Rights Reserved
  4. //
  5. //   Implementation of class TListBox and TlistBoxData.
  6. //----------------------------------------------------------------------------
  7. #pragma hdrignore SECTION
  8. #include <owl/owlpch.h>
  9. #include <owl/listbox.h>
  10. #include <stdlib.h>
  11. #include <cstring.h>
  12.  
  13. #if !defined(SECTION) || SECTION == 1
  14.  
  15. #define MULTIPLESEL    (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)
  16.  
  17. //
  18. // TListBoxData constructor
  19. //
  20. TListBoxData::TListBoxData()
  21. :
  22.   Strings(10, 0, 10),
  23.   ItemDatas(10, 0, 10),
  24.   SelIndices(1, 0, 10)
  25. {
  26. }
  27.  
  28. //
  29. // TListBoxData destructor
  30. //
  31. TListBoxData::~TListBoxData()
  32. {
  33. }
  34.  
  35. //
  36. // adds "str" to "Strings"
  37. //
  38. // if "isSelected" is true, marks it as selected
  39. //
  40. void
  41. TListBoxData::AddString(const char* str, bool isSelected)
  42. {
  43.   Strings.Add(str);
  44.   if (isSelected)
  45.     Select(Strings.GetItemsInContainer()-1);
  46. }
  47.  
  48. //
  49. // adds str and associated item data to strings and datas
  50. //
  51. void
  52. TListBoxData::AddStringItem(const char* str, uint32 itemData, bool isSelected)
  53. {
  54.   ItemDatas.Add(itemData);
  55.   AddString(str, isSelected);
  56. }
  57.  
  58. //
  59. // selects an item at a given index.
  60. //
  61. void
  62. TListBoxData::Select(int index)
  63. {
  64.   if (index != LB_ERR)
  65.     SelIndices.Add(index);
  66. }
  67.  
  68. //
  69. // adds "str" to selection lists if it is in Strings
  70. //
  71. void
  72. TListBoxData::SelectString(const char far* str)
  73. {
  74.   for (int i = 0; i < Strings.GetItemsInContainer(); i++)
  75.     if (strcmp(Strings[i].c_str(), str) == 0) {
  76.       Select(i);
  77.       break;
  78.     }
  79. }
  80.  
  81. //
  82. // returns the length of the string at the passed selection index
  83. // excluding the terminating 0
  84. //
  85. int
  86. TListBoxData::GetSelStringLength(int index) const
  87. {
  88.   if (index >= 0 && index < GetSelCount())
  89.     return Strings[SelIndices[index]].length();
  90.   return -1;
  91. }
  92.  
  93. //
  94. // copies the string at the passed selection index into buffer
  95. //
  96. // bufferSize includes the terminating 0
  97. //
  98. void
  99. TListBoxData::GetSelString(char far* buffer, int bufferSize, int index) const
  100. {
  101.   if (bufferSize > 0) {
  102.     if (index < 0 || index >= GetSelCount())
  103.       *buffer = 0;
  104.  
  105.     else {
  106.       strncpy(buffer, Strings[SelIndices[index]].c_str(), bufferSize-1);
  107.       buffer[bufferSize - 1] = 0;
  108.     }
  109.   }
  110. }
  111.  
  112. //
  113. // copies the string at the passed index in SelStrings into str
  114. //
  115. void
  116. TListBoxData::GetSelString(string& str, int index) const
  117. {
  118.   if (index >= 0 && index < GetSelCount())
  119.     str = Strings[SelIndices[index]];
  120.   else
  121.     str = "";
  122. }
  123.  
  124. //----------------------------------------------------------------------------
  125.  
  126. TStringArray::TStringArray(int upper, int lower, int delta)
  127. :
  128.   Data(upper, lower, delta)
  129. {
  130. }
  131.  
  132. int TStringArray::LowerBound() const
  133. {
  134.   return Data.LowerBound();
  135. }
  136.  
  137. int TStringArray::UpperBound() const
  138. {
  139.   return Data.UpperBound();
  140. }
  141.  
  142. unsigned TStringArray::ArraySize() const
  143. {
  144.   return Data.ArraySize();
  145. }
  146.  
  147. int TStringArray::IsFull() const
  148. {
  149.   return Data.IsFull();
  150. }
  151.  
  152. int TStringArray::IsEmpty() const
  153. {
  154.   return Data.IsEmpty();
  155. }
  156.  
  157. unsigned TStringArray::GetItemsInContainer() const
  158. {
  159.   return Data.GetItemsInContainer();
  160. }
  161.  
  162. int TStringArray::Add(const string& t)
  163. {
  164.   return Data.Add(t);
  165. }
  166.  
  167. int TStringArray::Detach(const string& t)
  168. {
  169.   return Data.Detach(t);
  170. }
  171.  
  172. int TStringArray::Detach(int loc)
  173. {
  174.   return Data.Detach(loc);
  175. }
  176.  
  177. int TStringArray::Destroy(const string& t)
  178. {
  179.   return Detach(t);
  180. }
  181.  
  182. int TStringArray::Destroy(int loc)
  183. {
  184.   return Detach(loc);
  185. }
  186.  
  187. int TStringArray::HasMember(const string& t) const
  188. {
  189.   return Data.HasMember(t);
  190. }
  191.  
  192. int TStringArray::Find(const string& t) const
  193. {
  194.   return Data.Find(t);
  195. }
  196.  
  197. string& TStringArray::operator [](int loc)
  198. {
  199.   return Data[loc];
  200. }
  201.  
  202. string& TStringArray::operator [](int loc) const
  203. {
  204.   return Data[loc];
  205. }
  206.  
  207. void TStringArray::ForEach(IterFunc iter, void* args)
  208. {
  209.   Data.ForEach(iter, args);
  210. }
  211.  
  212. string* TStringArray::FirstThat(CondFunc cond, void* args) const
  213. {
  214.   return Data.FirstThat(cond, args);
  215. }
  216.  
  217. string* TStringArray::LastThat(CondFunc cond, void* args) const
  218. {
  219.   return Data.LastThat(cond, args);
  220. }
  221.  
  222. void TStringArray::Flush()
  223. {
  224.   Data.Flush();
  225. }
  226.  
  227. //----------------------------------------------------------------------------
  228.  
  229. TIntArray::TIntArray(int upper, int lower, int delta)
  230. :
  231.   Data(upper, lower, delta)
  232. {
  233. }
  234.  
  235. int TIntArray::LowerBound() const
  236. {
  237.   return Data.LowerBound();
  238. }
  239.  
  240. int TIntArray::UpperBound() const
  241. {
  242.   return Data.UpperBound();
  243. }
  244.  
  245. unsigned TIntArray::ArraySize() const
  246. {
  247.   return Data.ArraySize();
  248. }
  249.  
  250. int TIntArray::IsFull() const
  251. {
  252.   return Data.IsFull();
  253. }
  254.  
  255. int TIntArray::IsEmpty() const
  256. {
  257.   return Data.IsEmpty();
  258. }
  259.  
  260. unsigned TIntArray::GetItemsInContainer() const
  261. {
  262.   return Data.GetItemsInContainer();
  263. }
  264.  
  265. int TIntArray::Add(const TInt& t)
  266. {
  267.   return Data.Add(t);
  268. }
  269.  
  270. int TIntArray::Detach(const TInt& t)
  271. {
  272.   return Data.Detach(t);
  273. }
  274.  
  275. int TIntArray::Detach(int loc)
  276. {
  277.   return Data.Detach(loc);
  278. }
  279.  
  280. int TIntArray::Destroy(const TInt& t)
  281. {
  282.   return Detach(t);
  283. }
  284.  
  285. int TIntArray::Destroy(int loc)
  286. {
  287.   return Detach(loc);
  288. }
  289.  
  290. int TIntArray::HasMember(const TInt& t) const
  291. {
  292.   return Data.HasMember(t);
  293. }
  294.  
  295. int TIntArray::Find(const TInt& t) const
  296. {
  297.   return Data.Find(t);
  298. }
  299.  
  300. TInt& TIntArray::operator [](int loc)
  301. {
  302.   return Data[loc];
  303. }
  304.  
  305. TInt& TIntArray::operator [](int loc) const
  306. {
  307.   return Data[loc];
  308. }
  309.  
  310. void TIntArray::ForEach(IterFunc iter, void* args)
  311. {
  312.   Data.ForEach(iter, args);
  313. }
  314.  
  315. TInt* TIntArray::FirstThat(CondFunc cond, void* args) const
  316. {
  317.   return Data.FirstThat(cond, args);
  318. }
  319.  
  320. TInt* TIntArray::LastThat(CondFunc cond, void* args) const
  321. {
  322.   return Data.LastThat(cond, args);
  323. }
  324.  
  325. void TIntArray::Flush()
  326. {
  327.   Data.Flush();
  328. }
  329.  
  330. //----------------------------------------------------------------------------
  331.  
  332. TDwordArray::TDwordArray(int upper, int lower, int delta)
  333. :
  334.   Data(upper, lower, delta)
  335. {
  336. }
  337.  
  338. int TDwordArray::LowerBound() const
  339. {
  340.   return Data.LowerBound();
  341. }
  342.  
  343. int TDwordArray::UpperBound() const
  344. {
  345.   return Data.UpperBound();
  346. }
  347.  
  348. unsigned TDwordArray::ArraySize() const
  349. {
  350.   return Data.ArraySize();
  351. }
  352.  
  353. int TDwordArray::IsFull() const
  354. {
  355.   return Data.IsFull();
  356. }
  357.  
  358. int TDwordArray::IsEmpty() const
  359. {
  360.   return Data.IsEmpty();
  361. }
  362.  
  363. unsigned TDwordArray::GetItemsInContainer() const
  364. {
  365.   return Data.GetItemsInContainer();
  366. }
  367.  
  368. int TDwordArray::Add(const uint32& t)
  369. {
  370.   return Data.Add(t);
  371. }
  372.  
  373. int TDwordArray::Detach(const uint32& t)
  374. {
  375.   return Data.Detach(t);
  376. }
  377.  
  378. int TDwordArray::Detach(int loc)
  379. {
  380.   return Data.Detach(loc);
  381. }
  382.  
  383. int TDwordArray::Destroy(const uint32& t)
  384. {
  385.   return Detach(t);
  386. }
  387.  
  388. int TDwordArray::Destroy(int loc)
  389. {
  390.   return Detach(loc);
  391. }
  392.  
  393. int TDwordArray::HasMember(const uint32& t) const
  394. {
  395.   return Data.HasMember(t);
  396. }
  397.  
  398. int TDwordArray::Find(const uint32& t) const
  399. {
  400.   return Data.Find(t);
  401. }
  402.  
  403. uint32& TDwordArray::operator [](int loc)
  404. {
  405.   return Data[loc];
  406. }
  407.  
  408. uint32& TDwordArray::operator [](int loc) const
  409. {
  410.   return Data[loc];
  411. }
  412.  
  413. void TDwordArray::ForEach(IterFunc iter, void* args)
  414. {
  415.   Data.ForEach(iter, args);
  416. }
  417.  
  418. uint32* TDwordArray::FirstThat(CondFunc cond, void* args) const
  419. {
  420.   return Data.FirstThat(cond, args);
  421. }
  422.  
  423. uint32* TDwordArray::LastThat(CondFunc cond, void* args) const
  424. {
  425.   return Data.LastThat(cond, args);
  426. }
  427.  
  428. void TDwordArray::Flush()
  429. {
  430.   Data.Flush();
  431. }
  432.  
  433. //----------------------------------------------------------------------------
  434.  
  435. //
  436. // constructor for TListBox
  437. //
  438. // initializes its data fields using parameters passed and default values
  439. //
  440. // by default, an MS-Windows listbox associated with the TListBox will:
  441. //   - be visible upon creation
  442. //   - have a border and a vertical scrollbar
  443. //   - maintain entries in alphabetical order
  444. //   - notify its parent when a selection is made
  445. //
  446. TListBox::TListBox(TWindow*   parent,
  447.                    int        id,
  448.                    int x, int y, int w, int h,
  449.                    TModule*   module)
  450. :
  451.   TControl(parent, id, 0, x, y, w, h, module)
  452. {
  453.   Attr.Style |= LBS_STANDARD;
  454. }
  455.  
  456. TListBox::TListBox(TWindow*   parent,
  457.                    int        resourceId,
  458.                    TModule*   module)
  459. :
  460.   TControl(parent, resourceId, module)
  461. {
  462. }
  463.  
  464. char far*
  465. TListBox::GetClassName()
  466. {
  467.   return "LISTBOX";
  468. }
  469.  
  470. //
  471. // transfers state information for a TListBox
  472. //
  473. // transfers the items and selection of the list to or from a transfer
  474. // buffer if tdSetData or tdGetData, respectively, is passed as the
  475. // direction
  476. //
  477. // buffer should point to a TListBoxData which points to the data to be
  478. // transferred
  479. //
  480. // Transfer returns the size of TListBoxData
  481. //
  482. // to retrieve the size without transferring data, pass tdSizeData as the
  483. // direction
  484. //
  485. uint
  486. TListBox::Transfer(void* buffer, TTransferDirection direction)
  487. {
  488.   long           style = GetWindowLong(GWL_STYLE);
  489.   TListBoxData*  listBoxData = (TListBoxData*)buffer;
  490.  
  491.   if (direction == tdGetData) {
  492.     //
  493.     // first, clear out Strings array and fill with contents of list box
  494.     //
  495.     listBoxData->Clear();
  496.  
  497.     //
  498.     // pre-calculate max string length so that one big buffer can be used
  499.     //
  500.     int  count = GetCount();
  501.     int  maxStrLen = 0;
  502.     for (int i = 0; i < count; i++) {
  503.       int  strLen = GetStringLen(i);
  504.       if (strLen > maxStrLen)
  505.         maxStrLen = strLen;
  506.     }
  507.     //
  508.     // Get each string and item data in the listbox & add to listboxdata
  509.     //
  510.     char*  tmpStr = new char[maxStrLen+1];
  511.     for (i = 0; i < GetCount(); i++) {
  512.       GetString(tmpStr, i);
  513.       listBoxData->AddStringItem(tmpStr, GetItemData(i), false);
  514.     }
  515.     delete tmpStr;
  516.  
  517.     //
  518.     // update transfer data with new selected item(s)
  519.     //
  520.     listBoxData->ResetSelections();
  521.  
  522.     if (!(style & MULTIPLESEL)) {
  523.       //
  524.       // single selection
  525.       //
  526.       listBoxData->Select(GetSelIndex());
  527.     }
  528.     else {
  529.       //
  530.       // multiple selection
  531.       //
  532.       int  selCount = GetSelCount();
  533.       if (selCount > 0) {
  534.         int*  selections = new int[selCount];
  535.  
  536.         GetSelIndexes(selections, selCount);
  537.  
  538.         // Select each item by index
  539.         //
  540.         for (int selIndex = 0; selIndex < selCount; selIndex++)
  541.           listBoxData->Select(selections[selIndex]);
  542.  
  543.         delete selections;
  544.       }
  545.     }
  546.   }
  547.   else if (direction == tdSetData) {
  548.     ClearList();
  549.  
  550.     //
  551.     // add each string, item data and selections in listBoxData to list box
  552.     //
  553.     const int noSelection = -1;
  554.     int  selCount = listBoxData->GetSelCount();  // for multi selection
  555.     int  selIndex = noSelection;                 // for single selection
  556.     for (int i = 0; i < listBoxData->GetStrings().GetItemsInContainer(); i++) {
  557.       // index may be different from i when the listbox is sorted.
  558.       //
  559.       int index = AddString(listBoxData->GetStrings()[i].c_str());
  560.       SetItemData(index, listBoxData->GetItemDatas()[i]);
  561.       if (style & MULTIPLESEL) {
  562.         for (int j = 0; j < selCount; j++)
  563.           if (listBoxData->GetSelIndices()[j] == i) {
  564.             SetSel(index, true);
  565.             break;
  566.           }
  567.       }
  568.       else {
  569.         if (listBoxData->GetSelIndices()[0] == i)
  570.           selIndex = index;
  571.         else
  572.           // inserted something before item and the item to select has been
  573.           // pushed further down in the list.
  574.           //
  575.           if (selIndex != noSelection && index <= selIndex)
  576.             selIndex++;
  577.       }
  578.     }
  579.     if (selIndex != noSelection && !(style & MULTIPLESEL))
  580.       SetSelIndex(selIndex);
  581.   }
  582.  
  583.   return sizeof(TListBoxData);
  584. }
  585.  
  586. //
  587. // returns the index of the first string in the associated listbox
  588. // which is the same as the passed string
  589. //
  590. // searches for a match beginning at the passed indexStart
  591. //
  592. // if a match is not found after the last string has been compared,
  593. // the search continues from the beginning of the list until a match
  594. // is found or until the list has been completely traversed
  595. //
  596. // searches from beginning of list when -1 is passed as the index
  597. //
  598. // returns the index of the selected string; a negative value is returned
  599. // if an error occurs
  600. //
  601. // for single or multiple-selection list boxes
  602. //
  603. int
  604. TListBox::FindExactString(const char far* findStr, int indexStart) const
  605. {
  606.   bool  found = false;
  607.   int   firstMatch = indexStart = FindString(findStr, indexStart);
  608.   do {
  609.     if (indexStart > -1) {
  610.       char*  tmpStr = new char[GetStringLen(indexStart) + 1];
  611.  
  612.       GetString(tmpStr, indexStart);
  613.  
  614.       if (strcmp(tmpStr, findStr) == 0)
  615.         found = true;
  616.  
  617.       else
  618.         indexStart = FindString(findStr, indexStart);
  619.  
  620.       delete tmpStr;
  621.     }
  622.   } while (!found && indexStart != firstMatch);
  623.  
  624.   return found ? indexStart : -1;
  625. }
  626.  
  627. //
  628. // for use with single-selection list boxes (and combo boxes)
  629. //
  630. // retrieves the text of the string which is selected in the associated
  631. // listbox
  632. //
  633. // returns the number of characters copied; -1 is returned if no string
  634. // is selected or this is a multiple-selection list box
  635. //
  636. // since the Windows function is not passed a size parameter, we have to
  637. // allocate a string to hold the largest string (gotten from a query), and
  638. // copy a part of it
  639. //
  640. int
  641. TListBox::GetSelString(char far* str, int maxChars) const
  642. {
  643.   int  index = GetSelIndex();
  644.  
  645.   if (index > -1) {
  646.     int  length = GetStringLen(index);
  647.  
  648.     if (maxChars >= length)
  649.       return GetString(str, index);
  650.  
  651.     else {
  652.       char*  tmpStr = new char[length + 1];
  653.  
  654.       if (tmpStr) {
  655.         GetString(tmpStr, index);
  656.         strncpy(str, tmpStr, maxChars);
  657.         delete tmpStr;
  658.         return maxChars;
  659.       }
  660.     }
  661.   }
  662.   return -1;
  663. }
  664.  
  665. //
  666. // returns the number of selected items in the list box. For
  667. // multiple-selection list boxes only
  668. //
  669. int
  670. TListBox::GetSelCount() const
  671. {
  672.   if (!(GetWindowLong(GWL_STYLE) & MULTIPLESEL))
  673.     return GetSelIndex() < 0 ? 0 : 1;
  674.  
  675.   //
  676.   // multiple-selection list box
  677.   //
  678.   return (int)CONST_CAST(TListBox*,this)->HandleMessage(LB_GETSELCOUNT);
  679. }
  680.  
  681. //
  682. // retrieves the text of the strings which are selected in the
  683. // associated listbox
  684. //
  685. // returns the number of items put into Strings.  -1 is returned if this is
  686. // not a multiple-selection list box
  687. //
  688. // since the Windows function is not passed a size parameter, we have to
  689. // allocate a string to hold the largest string (gotten from a query), and
  690. // copy a part of it
  691. //
  692. // only for use with multiple-selection list boxes
  693. //
  694. int
  695. TListBox::GetSelStrings(char far** strs, int maxCount, int maxChars) const
  696. {
  697.   if (!(GetWindowLong(GWL_STYLE) & MULTIPLESEL))
  698.     return -1;
  699.  
  700.   int i = GetSelCount();
  701.  
  702.   if (i < maxCount)
  703.     maxCount = i;
  704.  
  705.   if (maxCount > 0) {
  706.     int*  selections = new int[maxCount];
  707.  
  708.     GetSelIndexes(selections, maxCount);
  709.  
  710.     for (int selIndex = 0; selIndex < maxCount; selIndex++) {
  711.       int  tmpStrLen = GetStringLen(selections[selIndex]);
  712.  
  713.       if (maxChars >= tmpStrLen)
  714.         GetString(strs[selIndex], selections[selIndex]);
  715.  
  716.       else {
  717.         char*  tmpStr = new char[tmpStrLen+1];
  718.  
  719.         if (tmpStr) {
  720.           GetString(tmpStr, selections[selIndex]);
  721.           strncpy(strs[selIndex], tmpStr, maxChars);
  722.           delete tmpStr;
  723.         }
  724.       }
  725.     }
  726.     delete selections;
  727.   }
  728.   return maxCount;
  729. }
  730.  
  731. //
  732. // selects the first string in the associated listbox following the
  733. // passed index which begins with the passed string
  734. //
  735. // searches for a match beginning at the passed Index. if a match is not
  736. // found after the last string has been compared, the search continues
  737. // from the beginning of the list until a match is found or until the list
  738. // has been completely traversed
  739. //
  740. // searches from beginning of list when -1 is passed as the index
  741. //
  742. // returns the index of the selected string. a negative value is returned
  743. // if an error occurs
  744. //
  745. // only for single-selection list boxes
  746. //
  747. int
  748. TListBox::SetSelString(const char far* findStr, int indexStart)
  749. {
  750.   if (!(GetWindowLong(GWL_STYLE) & MULTIPLESEL))
  751.     return (int)HandleMessage(LB_SELECTSTRING, indexStart, (LPARAM)findStr);
  752.   return -1;
  753. }
  754.  
  755. //
  756. // selects the strings in the associated list box which begin with
  757. // the passed prefixes
  758. //
  759. // for each string the search begins at the beginning of the list
  760. // and continues until a match is found or until the list has been
  761. // completely traversed
  762. //
  763. // if ShouldSet is true, the matched strings are selected and highlighted;
  764. // otherwise the highlight is removed from the matched strings and they
  765. // are no longer selected
  766. //
  767. // returns the number of strings successfully selected or deselected
  768. //
  769. // if NumSelections is less than zero, all strings are selected or deselected
  770. // and a negative value is returned on failure
  771. //
  772. // only for multiple-selection list boxes (-1 is returned if this is not
  773. // a multiple-selection list box)
  774. //
  775. int
  776. TListBox::SetSelStrings(const char far** strs, int numSelections, bool shouldSet)
  777. {
  778.   if (!(GetWindowLong(GWL_STYLE) & MULTIPLESEL))
  779.     return -1;
  780.  
  781.   if (numSelections < 0)
  782.     return SetSel(-1, shouldSet);
  783.  
  784.   int  successes = 0;
  785.   for (int i = 0; i < numSelections; i++) {
  786.     int  selIndex;
  787.     if ((selIndex = FindString(strs[i], -1)) > -1)
  788.       if (SetSel(selIndex, shouldSet) > -1)
  789.         successes++;
  790.   }
  791.   return successes;
  792. }
  793.  
  794. //
  795. // returns the index of the selected string in the associated listbox
  796. //
  797. // a negative value is returned if no string is selected or this
  798. // is a multiple-selection list box
  799. //
  800. // only for single-selection list boxes
  801. //
  802. int
  803. TListBox::GetSelIndex() const
  804. {
  805.   if (!(GetWindowLong(GWL_STYLE) & MULTIPLESEL))
  806.     return (int)CONST_CAST(TListBox*,this)->HandleMessage(LB_GETCURSEL);
  807.   return -1;
  808. }
  809.  
  810. //
  811. // fills indexes with the indexes of up to maxCount selected strings
  812. //
  813. // returns number of items put in the array(-1 for single-selection
  814. // list boxes)
  815. //
  816. int
  817. TListBox::GetSelIndexes(int* indexes, int maxCount) const
  818. {
  819.   if (!(GetWindowLong(GWL_STYLE) & MULTIPLESEL))
  820.     return -1;
  821.   return (int)CONST_CAST(TListBox*,this)->HandleMessage(LB_GETSELITEMS,
  822.                                                         maxCount,
  823.                                                         (LPARAM)indexes);
  824. }
  825.  
  826. // selects the string at passed index in the associated listbox and
  827. // forces the string into view
  828. //
  829. // clears selection when -1 is passed as the index. a negative value is
  830. // returned if an error occurs
  831. //
  832. // only for single-selection list boxes
  833. //
  834. int
  835. TListBox::SetSelIndex(int index)
  836. {
  837.   if (!(GetWindowLong(GWL_STYLE) & MULTIPLESEL))
  838.     return (int)HandleMessage(LB_SETCURSEL, index);
  839.   return -1;
  840. }
  841.  
  842. //
  843. // selects/deselects the strings in the associated list box at the
  844. // passed indexes
  845. //
  846. // if ShouldSet is true, the indexed strings are selected and highlighted;
  847. // otherwise the highlight is removed and they are no longer selected
  848. //
  849. // returns the number of strings successfully selected or deselected(-1
  850. // if not a multiple-selection list box)
  851. //
  852. // if NumSelections is less than zero, all strings are selected or deselected
  853. // and a negative value is returned on failure
  854. //
  855. // only for multiple-selection list boxes
  856. //
  857. int
  858. TListBox::SetSelIndexes(int* indexes, int numSelections, bool shouldSet)
  859. {
  860.   int  successes = 0;
  861.  
  862.   if (!(GetWindowLong(GWL_STYLE) & MULTIPLESEL))
  863.     return -1;  // including if it's a combobox
  864.  
  865.   if (numSelections < 0)
  866.     return (int)HandleMessage(LB_SETSEL, shouldSet, -1);
  867.  
  868.   else {
  869.     for (int i = 0; i < numSelections; i++)
  870.       if ((int)HandleMessage(LB_SETSEL, shouldSet, indexes[i]) > -1)
  871.         successes++;
  872.   }
  873.   return successes;
  874. }
  875.  
  876. #endif
  877. #if !defined(SECTION) || SECTION == 2
  878.  
  879. IMPLEMENT_STREAMABLE1(TListBox, TControl);
  880.  
  881. //
  882. // reads an instance of TListBox from the supplied ipstream
  883. //
  884. void*
  885. TListBox::Streamer::Read(ipstream& is, uint32 /*version*/) const
  886. {
  887.   ReadBaseObject((TControl*)GetObject(), is);
  888.   return GetObject();
  889. }
  890.  
  891. //
  892. // writes the TListBox to the supplied opstream
  893. //
  894. void
  895. TListBox::Streamer::Write(opstream& os) const
  896. {
  897.   WriteBaseObject((TControl*)GetObject(), os);
  898. }
  899.  
  900. #endif
  901.  
  902.