home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / ool.zip / OOL / source / xcontain.cpp < prev    next >
C/C++ Source or Header  |  1997-04-04  |  23KB  |  587 lines

  1. #include "XContain.h"
  2. #include "XContInf.h"
  3. #include "XContObj.h"
  4. #include "XControl.h"
  5. #include "XString.h"
  6. #include "XMsgBox.h"
  7. #include "XContCol.h"
  8.  
  9. #include <string.h>
  10. #include <stdlib.h>
  11.  
  12.  
  13. /*@ 
  14. @class XContainerControl
  15. @parent XControl
  16. @type overview
  17. @symbol _
  18. @remarks XContainerControl represents a container with multiple views like tree-, list- or icon view for a large amount of objects.
  19. */
  20.  
  21.  
  22. /*@ XContainerControl :: SetObjectEmphasis( const XContainerObject * obj, const SHORT emph, const BOOL enableEmph)
  23. @group object settings
  24. @remarks Sets the emphasis of an object so displaying the objects icon is changed
  25. @parameters <t '°' c=2>
  26.                 °XContainerObject * theObject          °object to change
  27.             °SHORT emphasis                        °the needed emphasis, valid values are:
  28.                                                                     <t '°' c=2>
  29.                                                       °CON_CURSORED   °the object is cursored
  30.                                                       °CON_DISABLED   °the object is disabled
  31.                                                       °CON_INUSE      °the objects icon is displayed open
  32.                                                       °CON_PICKED     °the objects icon is displayed dragged
  33.                                                       °CON_SELECTED   °the object is selected
  34.                                                       °CON_SOURCE     °the object get source-emphasis
  35.                                                                     </t>
  36.                                                   (can be or-ed)
  37.             °BOOL enable                           °enable/disable emphasis
  38.                 </t>
  39. */
  40. void XContainerControl::SetObjectEmphasis(const XContainerObject * obj, const SHORT emph, const BOOL enableEmph) const
  41. {
  42.     WinSendMsg(winhandle, CM_SETRECORDEMPHASIS, MPFROMP(obj->core), MPFROM2SHORT(enableEmph, emph));
  43. }
  44.  
  45.  
  46. /*@ XContainerControl :: ExpandTreeObject( const XContainerObject * obj, const BOOL expand)
  47. @group expanding
  48. @remarks Expands/collaps an object in tree-view.
  49. @parameters    <t '°' c=2>
  50.                 °XContainerObject * obj        °the object to expand/collaps
  51.                 °BOOL expand                        °TRUE=expand<BR>FALSE=collapse
  52.                 <t>
  53. @returns        TRUE    success
  54. */
  55. BOOL XContainerControl::ExpandTreeObject(const XContainerObject * obj, const BOOL expand) const
  56. {
  57.     if (expand)
  58.         return (BOOL) WinSendMsg(winhandle, CM_EXPANDTREE, MPFROMP(obj->core), 0);
  59.     else
  60.         return (BOOL) WinSendMsg(winhandle, CM_COLLAPSETREE, MPFROMP(obj->core), 0);
  61. }
  62.  
  63.  
  64. SHORT EXPENTRY SortRecord(const PRECORDCORE p1, const PRECORDCORE p2, const void *p3);
  65.  
  66.  
  67. /*@ XContainerControl :: SortObjects( void )
  68. @group misc
  69. @remarks Sort the objects in the container. On default the objects are sorted
  70. by the title of the object. To sort them on a user-defined way you must override
  71. the method Sort() of the XContainerObject.
  72. */
  73. void XContainerControl::SortObjects(void) const
  74. {
  75.     WinSendMsg(winhandle, CM_SORTRECORD, MPFROMP(SortRecord), 0);
  76. }
  77.  
  78.  
  79. /*@ XContainerControl :: HScroll( const LONG pix )
  80. @group display
  81. @remarks Scrolls the container content horizontal
  82. @parameters LONG pixels                  how much pixels to scroll
  83. */
  84. void XContainerControl::HScroll(const LONG pix) const
  85. {
  86.     WinSendMsg(winhandle, CM_SCROLLWINDOW, MPFROMSHORT(CMA_HORIZONTAL), (MRESULT) pix);
  87. }
  88.  
  89.  
  90. /*@ XContainerControl :: VScroll( const LONG pix )
  91. @group display
  92. @remarks Scrolls the container content vertical
  93. @parameters LONG pixels                  how much pixels to scroll
  94. */
  95. void XContainerControl::VScroll(const LONG pix) const
  96. {
  97.     WinSendMsg(winhandle, CM_SCROLLWINDOW, MPFROMSHORT(CMA_VERTICAL), (MRESULT) pix);
  98. }
  99.  
  100.  
  101. /*@ XContainerControl :: UpdateColumns( void )
  102. @group columns
  103. @remarks Update columns in detail-view. If you have inserted, deleted or modified
  104. one ore more columns you must call UpdateColumns to make your changes visible.
  105. */
  106. void XContainerControl::UpdateColumns(void) const
  107. {
  108.     WinSendMsg(winhandle, CM_INVALIDATEDETAILFIELDINFO, 0, 0);
  109. }
  110.  
  111.  
  112. /*@ XContainerControl :: FindObject( const XContainerObject * startObject, const SHORT select)
  113. @group searching
  114. @remarks Get an object from the container with relative positions
  115. @parameters <t '°' c=2>
  116.                 °XContainerObject * startObject  °search relative to this object (default is NULL)
  117.             °SHORT select                    °serach settings, valid values are:
  118.                                                             <t '°' c=2>
  119.                                                °CON_FIRST      °get the first object of the container
  120.                                                °CON_FIRSTCHILD °get the first child of startObject
  121.                                                °CON_LAST       °get the last object of the container
  122.                                                °CON_LASTCHILD  °get the last child of startObject
  123.                                                °CON_NEXT       °get the next object relative to startObject
  124.                                                °CON_PARENT     °get the parent of startObject
  125.                                                °CON_PREV       °get the previous object relative to startObject
  126.                                                             </t>
  127.                                                             default is CON_FIRST
  128.                </t>
  129. @returns    XContainerObject *              pointer to the found object (NULL if nothing is found)
  130. */
  131. XContainerObject *XContainerControl::FindObject(const XContainerObject * startObject, const SHORT select)
  132. {
  133.     RECORDCORE *res, *rel = NULL;
  134.  
  135.     if (startObject != NULL)
  136.         rel = startObject->core;
  137.  
  138.     res = (RECORDCORE *) WinSendMsg(winhandle, CM_QUERYRECORD, MPFROMP(rel), MPFROM2SHORT(select, CMA_ITEMORDER));
  139.  
  140.     if (res > 0)
  141.     {
  142.         RECORDCORE *pr = (RECORDCORE *) ((PBYTE) res + sizeof(RECORDCORE));
  143.         XContainerObject *obj;
  144.  
  145.         memcpy(&obj, pr, 4);
  146.         return obj;
  147.     }
  148.     else
  149.         return NULL;
  150. }
  151.  
  152.  
  153. /*@ XContainerControl :: GetObject( const XContainerObject * startObject, const SHORT filter)
  154. @group searching
  155. @remarks Get an object from the container by querying the objects emphasis
  156. @parameters <t '°' c=2>
  157.                 °XContainerObject * startObject  °search relative to this object (default is NULL)
  158.             °SHORT filter                    °the emphasis to search
  159.                                                             <t '°' c=2>
  160.                                                °CON_CURSORED   °the object has the cursored
  161.                                                °CON_DISABLED   °the object is disabled
  162.                                                °CON_INUSE      °the objects icon is displayed open
  163.                                                °CON_PICKED     °the objects icon is displayed dragged
  164.                                                °CON_SELECTED   °the object is selected
  165.                                                °CON_SOURCE     °the object get source-emphasis
  166.                                                             </t>
  167.                                             (default is CON_SELECTED, can be or-ed)
  168.                 </t>
  169. @returns    XContainerObject *              pointer to the found object (NULL if nothing is found)
  170. */
  171. XContainerObject *XContainerControl::GetObject(const XContainerObject * startObject, const SHORT filter)
  172. {
  173.     RECORDCORE *res, *rel;
  174.     XContainerObject *obj;
  175.  
  176.     if (startObject)
  177.         rel = startObject->core;
  178.     else
  179.         rel = (PRECORDCORE) CON_FIRST;
  180.  
  181.     res = (RECORDCORE *) WinSendMsg(winhandle, CM_QUERYRECORDEMPHASIS, MPFROMP(rel), MPFROMSHORT(filter));
  182.  
  183.     if (res > 0)
  184.     {
  185.         PRECORDCORE pr = (PRECORDCORE) ((PBYTE) res + sizeof(RECORDCORE));
  186.  
  187.         memcpy(&obj, pr, 4);
  188.         return obj;
  189.     }
  190.     else
  191.         return NULL;
  192. }
  193.  
  194.  
  195. /*@ XContainerControl :: InvalidateObject( const XContainerObject * obj, const SHORT option) const
  196. @group display
  197. @remarks Invalidates one ore all objects
  198. @parameters <t '°' c=2>
  199.                 °XContainerObject * theObject     °the object to invalidate (default is NULL)
  200.            °SHORT options                    °options, valid values are:
  201.                                                             <t '°' c=2>
  202.                                                °CON_ERASE          °erase the background
  203.                                                °CON_REPOSITION     °reposition
  204.                                                °CON_NOREPOSITION   °no reposition
  205.                                                °CON_TEXTCHANGED    °redraw the text
  206.                                                             </t>
  207.                                              (default is CON_REPOSITION, can be or-ed)
  208.             </t>
  209. */
  210. void XContainerControl::InvalidateObject(const XContainerObject * obj, const SHORT option) const
  211. {
  212.     if (obj)
  213.         WinSendMsg(winhandle, CM_INVALIDATERECORD, MPFROMP(&obj->core), MPFROM2SHORT(1, option));
  214.     else
  215.         WinSendMsg(winhandle, CM_INVALIDATERECORD, 0, 0);
  216. }
  217.  
  218.  
  219. /*@ XContainerControl :: RemoveObject( XContainerObject * obj, const BOOL destroyObject, const BOOL redraw)
  220. @group inserting/removing objects
  221. @remarks Removes an object from the container
  222. @parameters <t '°' c=2>
  223.                 °XContainerObject * theObject    °the object to remove
  224.             °BOOL destryObject               °if TRUE the destructor of the object is called
  225.                                             if FALSE it exist (usefull if an object is member
  226.                                             of multiple container-controls)
  227.                                             (default is TRUE)
  228.             °BOOL redraw                     °redraw the container (default is TRUE)
  229.                 </t>
  230. @returns    BOOL                            success
  231. */
  232. BOOL XContainerControl::RemoveObject(XContainerObject * obj, const BOOL destroyObject, const BOOL redraw) const
  233. {
  234.     SHORT settings = 0;
  235.  
  236.     if (destroyObject)
  237.         settings = CMA_FREE;
  238.     if (redraw)
  239.         settings |= CMA_INVALIDATE;
  240.  
  241.     if ((LONG) WinSendMsg(winhandle, CM_REMOVERECORD, MPFROMP(&obj->core), MPFROM2SHORT(1, settings)) == -1)
  242.         return FALSE;
  243.     if (destroyObject)
  244.         delete obj;                // new
  245.     return TRUE;
  246. }
  247.  
  248.  
  249.  
  250. /*@ XContainerControl :: RemoveObjectList( XContainerObject ** obj, const SHORT count, const BOOL destroyObject, const BOOL redraw)
  251. @group inserting/removing objects
  252. @remarks Removes an array of objects from the container
  253. @parameters <t '°' c=2>
  254.                 °XContainerObject ** theObjects    °an array of pointer to objects to remove
  255.                 °SHORT count                                °the count of object in the array
  256.             °BOOL destryObject               °if TRUE the destructor of the objects are called
  257.                                             if FALSE it exist (usefull if an object is member
  258.                                             of multiple container-controls)
  259.                                             (default is TRUE)
  260.             °BOOL redraw                     °redraw the container (default is TRUE)
  261.                 </t>
  262. @returns    BOOL                            success
  263. */
  264. BOOL XContainerControl::RemoveObjectList(XContainerObject ** obj, const SHORT count, const BOOL destroyObject, const BOOL redraw) const
  265. {
  266.     SHORT settings = 0;
  267.  
  268.     if (destroyObject)
  269.         settings = CMA_FREE;
  270.     if (redraw)
  271.         settings |= CMA_INVALIDATE;
  272.     RECORDCORE **core = (RECORDCORE **) malloc(count * sizeof(void *));
  273.     int i;
  274.  
  275.     for (i = 0; i < count; i++)
  276.         core[i] = obj[i]->core;
  277.     if ((LONG) WinSendMsg(winhandle, CM_REMOVERECORD, MPFROMP(core), MPFROM2SHORT(count, settings)) == -1)
  278.         return FALSE;
  279.  
  280.     if (destroyObject)
  281.     {
  282.         for (i = 0; i < count; i++)
  283.             delete obj[i];
  284.     }
  285.     free(core);
  286.  
  287.     return TRUE;
  288. }
  289.  
  290.  
  291. /*@ XContainerControl::AddObject(XContainerObject * object, XContainerObject * parentObject, XContainerObject * sibObject, BOOL draw)
  292. @group inserting/removing objects
  293. @remarks Add an object to the container. If you insert a large amount of objects you should set
  294. parameter <redraw> to FALSE and call InvalidateObject(NULL) if you have finished inserting.
  295. @parameters <t '°' c=2>
  296.                 °XContainerObject * theObject    °object to add
  297.             °XContainerObject * parentObject   °parent of the object (for tree-view)
  298.                                             (default is NULL)
  299.             °XContainerObject * sibObject   °sibling object to insert behind, or:
  300.                                                          <t '°' c=2>
  301.                                               °CON_FIRST  °insert at the top
  302.                                               °CON_END    °insert at the end
  303.                                                          </t>
  304.                                            In this cases you have to make a typecast: (XContainerObject *)
  305.                                            (default is CON_END)
  306.             °BOOL redraw                    °redraw the object
  307.                 </t>
  308. @returns    BOOL                            success
  309. */
  310. BOOL XContainerControl::AddObject(XContainerObject * object, XContainerObject * parentObject, XContainerObject * sibObject, BOOL draw)
  311. {
  312.     RECORDINSERT ri;
  313.  
  314.     ri.cb = sizeof(RECORDINSERT);
  315.     ri.zOrder = CMA_BOTTOM;
  316.     ri.cRecordsInsert = 1;
  317.     ri.fInvalidateRecord = draw;
  318.     ri.pRecordParent = parentObject ? parentObject->core : NULL;
  319.     if (sibObject)
  320.     {
  321.         if (sibObject != (XContainerObject *) CMA_END && sibObject != (XContainerObject *) CMA_FIRST)
  322.             ri.pRecordOrder = sibObject->core;
  323.         else
  324.             ri.pRecordOrder = (PRECORDCORE) sibObject;
  325.     }
  326.     else
  327.         ri.pRecordOrder = (PRECORDCORE) CMA_END;
  328.     return (BOOL) WinSendMsg(winhandle, CM_INSERTRECORD, (MPARAM) object->core, (MPARAM) & ri);
  329. }
  330.  
  331.  
  332. /*@ XContainerControl::AddObjectList(XContainerObject ** objectList, const USHORT count, XContainerObject * parentObject, XContainerObject * sibObject, BOOL draw)
  333. @group inserting/removing objects
  334. @remarks Add an object to the container. If you insert a large amount of objects you should set
  335. parameter <redraw> to FALSE and call InvalidateObject(NULL) if you have finished inserting.
  336. @parameters <t '°' c=2>
  337.                 °XContainerObject ** theObject    °an array of pointer to objects to add
  338.                 °SHORT count                                °count of object in the array
  339.             °XContainerObject * parentObject   °parent of the objects (for tree-view)
  340.                                             (default is NULL)
  341.             °XContainerObject * sibObject   °sibling object to insert behind, or:
  342.                                                         <t '°' c=2>
  343.                                               °CON_FIRST  °insert at the top
  344.                                               °CON_END    °insert at the end
  345.                                                         </t>
  346.                                            In this cases you have to make a typecast: (XContainerObject *)
  347.                                            (default is CON_END)
  348.             °BOOL redraw                    °draw the objects
  349.                 </t>
  350. @returns    BOOL                            success
  351. */
  352. BOOL XContainerControl::AddObjectList(XContainerObject ** objectList, const USHORT count, XContainerObject * parentObject, XContainerObject * sibObject, BOOL draw)
  353. {
  354.     if (count == 0)
  355.         return TRUE;
  356.     RECORDINSERT ri;
  357.  
  358.     ri.cb = sizeof(RECORDINSERT);
  359.     ri.zOrder = CMA_BOTTOM;
  360.     ri.cRecordsInsert = count;
  361.     ri.fInvalidateRecord = draw;
  362.     ri.pRecordParent = parentObject ? parentObject->core : NULL;
  363.     if (sibObject)
  364.     {
  365.         if (sibObject != (XContainerObject *) CMA_END && sibObject != (XContainerObject *) CMA_FIRST)
  366.             ri.pRecordOrder = sibObject->core;
  367.         else
  368.             ri.pRecordOrder = (PRECORDCORE) sibObject;
  369.     }
  370.     else
  371.         ri.pRecordOrder = (PRECORDCORE) CMA_END;
  372.     RECORDCORE **core = (RECORDCORE **) malloc(count * sizeof(void *));
  373.  
  374.     for (int i = 0; i < count; i++)
  375.         core[i] = objectList[i]->core;
  376.     return (BOOL) WinSendMsg(winhandle, CM_INSERTRECORDARRAY, (MPARAM) core, (MPARAM) & ri);
  377.     free(core);
  378. }
  379.  
  380.  
  381. /*@ XContainerControl::GetInfo(XContainerInfo * info)
  382. @group info
  383. @remarks Querys information about the container.
  384. @parameters    XContainerInfo * the information      buffer to hold the information (See the description of XContainerInfo )
  385. */
  386. void XContainerControl::GetInfo(XContainerInfo * info)
  387. {
  388.     WinSendMsg(winhandle, CM_QUERYCNRINFO, MPFROMP(&info->cnrinfo), (MRESULT) sizeof(CNRINFO));
  389.     info->changes = 0;
  390. }
  391.  
  392.  
  393. /*@ XContainerControl::SetInfo(XContainerInfo * info)
  394. @group info
  395. @remarks Set information how to display the container.
  396. @parameters    XContainerInfo * the information      See the description of XContainerInfo
  397. */
  398. void XContainerControl::SetInfo(XContainerInfo * info)
  399. {
  400.     WinSendMsg(winhandle, CM_SETCNRINFO, MPFROMP(&info->cnrinfo), MPFROMLONG(info->changes));
  401.     info->changes = 0;
  402. }
  403.  
  404.  
  405. /*@ XContainerControl::Arrange(void)
  406. @group display
  407. @remarks Rearrange the object is the container
  408. */
  409. void XContainerControl::Arrange(void) const
  410. {
  411.     WinSendMsg(winhandle, CM_ARRANGE, 0, 0);
  412. }
  413.  
  414.  
  415. void XContainerControl::Clean(PRECORDCORE first)
  416. {
  417.     XContainerObject *o;
  418.     PRECORDCORE pr;
  419.     PRECORDCORE core = first, buffer;
  420.  
  421.     while (core)
  422.     {
  423.         pr = (RECORDCORE *) ((PBYTE) core + sizeof(RECORDCORE));
  424.         PRECORDCORE co2 = (PRECORDCORE) WinSendMsg(winhandle, CM_QUERYRECORD, core, MPFROM2SHORT(CMA_FIRSTCHILD, CMA_ITEMORDER));
  425.  
  426.         if (co2)
  427.             Clean(co2);
  428.         memcpy(&o, pr, 4);
  429.         if (o)
  430.             delete o;
  431.  
  432.         buffer = (PRECORDCORE) WinSendMsg(winhandle, CM_QUERYRECORD, core, MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
  433.         WinSendMsg(winhandle, CM_REMOVERECORD, &core, MPFROM2SHORT(1, CMA_FREE));
  434.         core = buffer;
  435.     }
  436. }
  437.  
  438.  
  439. /*@ XContainerControl::RemoveAll(BOOL destroyRecords)
  440. @group inserting/removing objects
  441. @remarks Remove all objects from a container
  442. @parameters    BOOL destroyObjects       the destructors of the objects are called and
  443.                                          memory ascociated with the container is freed.
  444. */
  445. void XContainerControl::RemoveAll(BOOL destroyRecords)
  446. {
  447.     if (destroyRecords)
  448.     {
  449.         PRECORDCORE core = (PRECORDCORE) WinSendMsg(winhandle, CM_QUERYRECORD, NULL, MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER));
  450.  
  451.         if (core == (PRECORDCORE) - 1)
  452.             return;
  453.         Clean(core);
  454.     }
  455.     else
  456.         WinSendMsg(winhandle, CM_REMOVERECORD, 0, 0);
  457. }
  458.  
  459.  
  460.  
  461. /*@ XContainerControl :: XContainerControl(const XWindow * owner, const XRect * rec, const USHORT id, const ULONG style, const char *font):XControl(rec, style, owner, "", WC_CONTAINER, id, font)
  462. @group constructors/destructors
  463. @remarks
  464. @parameters <t '°' c=2>
  465.                    °XWindow * theOwner        °The owning window.
  466.                °XRect * rectangle         °Position and size.
  467.                °USHORT id                 °The id of the window.
  468.                                          Default is zero.
  469.                °ULONG style               °The style. valid values are:
  470.                                                         <t '°' c=2>
  471.                                               °CON_AUTOPOSITION    °objects are arranged automaticaly
  472.                                               °CON_EXTENDSEL       °extended selection is enabled
  473.                                               °CON_MULTIPLESEL     °mutiple selection is enabled
  474.                                               °CON_READONLY        °directe diting is disabled
  475.                                               °CON_SINGLESEL       °only one object can be selected
  476.                                                         </t>
  477.                 </t>
  478. */
  479. XContainerControl :: XContainerControl(const XWindow * owner, const XRect * rec, const USHORT id, const ULONG style, const char *font):XControl(rec, style, owner, "", WC_CONTAINER, id, font)
  480. {
  481. }
  482.  
  483.  
  484. /*@ XContainerControl::RemoveColumn(XContainerColumn * column, const SHORT option)
  485. @group columns
  486. @remarks Removes a column
  487. @parameters    <t '°' c=2>
  488.                     °XContainerColumn * theColumn   °The column to delete
  489.                °SHORT option                   °How to delete. Valid values are:
  490.                                                                 <t '°' c=2>
  491.                                                   °CON_FREE        °Destruct the column and free
  492.                                                                   container related memory
  493.                                                    °CON_INVALIDATE  °Redraw the container
  494.                                                                 </t>
  495.                     </t>
  496. @returns       BOOL                           success
  497. */
  498. BOOL XContainerControl::RemoveColumn(XContainerColumn * column, const SHORT option)
  499. {
  500.     LONG res = (LONG) WinSendMsg(winhandle, CM_REMOVEDETAILFIELDINFO, MPFROMP(column->info), MPFROM2SHORT(1, option));
  501.  
  502.     if (option & CON_FREE)
  503.         delete column;
  504.  
  505.     if (res < 0)
  506.         return FALSE;
  507.     else
  508.         return TRUE;
  509. }
  510.  
  511.  
  512. /*@ XContainerControl::GetColumn(const XContainerColumn * col, const SHORT option)
  513. @group columns
  514. @remarks Query a column from a container.
  515. @parameters    <t '°' c=2>
  516.                     °XContainerColumn * theColumnToSearch  °Relative position to begin search. In cases
  517.                                                      CMA_FIRST and CMA_LAST ignored.
  518.                °SHORT options                         °Valid values are:
  519.                                                                         <t '°' c=2>
  520.                                                         °CON_FIRST   °Get the first column.
  521.                                                         °CON_LAST    °Get the last column.
  522.                                                         °CON_NEXT    °Get the next relative to theColumnToSearch.
  523.                                                              °CON_PREV    °Get the previous relative to theColumnToSearch.
  524.                                                                         </t>
  525.                     </t>
  526. @returns       XContainerControl *                   The found column.
  527. */
  528. XContainerColumn * XContainerControl::GetColumn(const XContainerColumn * col, const SHORT option)
  529. {
  530.     FIELDINFO *i, *p;
  531.  
  532.     if (col != (XContainerColumn *) CMA_LAST && col != (XContainerColumn *) CMA_FIRST && col != (XContainerColumn *) CMA_PREV && col != (XContainerColumn *) CMA_NEXT)
  533.         p = col->info;
  534.     else
  535.         p = (FIELDINFO *) col;
  536.  
  537.     i = (FIELDINFO *) WinSendMsg(winhandle, CM_QUERYDETAILFIELDINFO, MPFROMP(p), MPFROMSHORT(option));
  538.     if (i == NULL || i == (FIELDINFO *) - 1)
  539.         return NULL;
  540.     XContainerColumn *c = NULL;
  541.  
  542.     memcpy(c, i->pUserData, sizeof(void *));
  543.     return c;
  544. }
  545.  
  546.  
  547. /*@ XContainerControl::InsertColumn(const XContainerColumn * column, const XContainerColumn * insertBehind, const BOOL redraw)
  548. @group columns
  549. @remarks Insert a column into a container. After you have added one or more columns,
  550. you must call Invalidate() so the columns are drawn.
  551. @parameters    <t '°' c=2>
  552.                     °XContainerColumn * theColumnToInsert  °This column should be inserted
  553.                °XContainerColumn * insertPosition     °The position to insert. Valid values are:
  554.                                                                         <t '°' c=2>
  555.                                                         °CON_FIRST         °Insert as the first column.
  556.                                                         °CON_LAST          °Insert as the last column.
  557.                                                         °XContaineColumn*  °The column behind which the
  558.                                                                                   column should be inserted.
  559.                                                                         </t>
  560.                     </t>
  561. @returns       BOOL                                  success
  562. */
  563. BOOL XContainerControl::InsertColumn(const XContainerColumn * column, const XContainerColumn * insertBehind, const BOOL redraw)
  564. {
  565.     FIELDINFOINSERT insert;
  566.  
  567.     insert.cb = sizeof(insert);
  568.  
  569.     insert.fInvalidateFieldInfo = redraw;
  570.     if (insertBehind)
  571.     {
  572.         if (insertBehind != (XContainerColumn *) CMA_FIRST && insertBehind != (XContainerColumn *) CMA_END)
  573.             insert.pFieldInfoOrder = insertBehind->info;
  574.         else
  575.             insert.pFieldInfoOrder = (FIELDINFO *) insertBehind;
  576.     }
  577.     else
  578.         insert.pFieldInfoOrder = (FIELDINFO *) CMA_FIRST;
  579.  
  580.     insert.cFieldInfoInsert = 1;
  581.  
  582.     if (SHORT1FROMMR(WinSendMsg(winhandle, CM_INSERTDETAILFIELDINFO, MPFROMP(column->info), MPFROMP(&insert))) == 0)
  583.         return FALSE;
  584.     else
  585.         return TRUE;
  586. }
  587.