#include "xheaders.h"

#include XContainerControl_i
#include XContainerInfo_i
#include XContainerObject_i
#include XControl_i
#include XString_i
#include XMessageBox_i
#include XContainerColumn_i

#include "string.h"


/*DOC
CLASS XContainerControl
FUNCTION SetObjectEmphasis
GROUP object settings
REMARKS sets the emphasis of an object so displaying the objects icon is changed

Parameters: XContainerObject * theObject          object to change
            SHORT emphasis                        the needed emphasis, valid values are:
                                                      CON_CURSORED   the object has the cursored
                                                      CON_DISABLED   the object is disabled
                                                      CON_INUSE      the objects icon is displayed open
                                                      CON_PICKED     the objects icon is displayed dragged
                                                      CON_SELECTED   the object is selected
                                                      CON_SOURCE     the object get source-emphasis
                                                  (cab be orïed)
            BOOL enable                           enable/disable emphasis
Returns:    -
*/
void XContainerControl :: SetObjectEmphasis( XContainerObject * obj, SHORT emph, BOOL enableEmph)
{
   WinSendMsg( winhandle, CM_SETRECORDEMPHASIS, MPFROMP( obj->core ), MPFROM2SHORT( enableEmph, emph));
}

/*DOC
CLASS XContainerControl
FUNCTION HScroll
GROUP display
REMARKS scrolls the container content horizontal
Parameters: LONG pixels                  how much pixels to scroll
Returns:    -
*/
void XContainerControl :: HScroll( LONG pix )
{
   WinSendMsg( winhandle, CM_SCROLLWINDOW, MPFROMSHORT( CMA_HORIZONTAL), (MRESULT) pix);
}


/*DOC
CLASS XContainerControl
FUNCTION VScroll
GROUP display
REMARKS scrolls the container content vertical
Parameters: LONG pixels                  how much pixels to scroll
Returns:    -
*/
void XContainerControl :: VScroll( LONG pix )
{
   WinSendMsg( winhandle, CM_SCROLLWINDOW, MPFROMSHORT( CMA_VERTICAL), (MRESULT) pix);
}


/*DOC
CLASS XContainerControl
FUNCTION UpdateColumns
GROUP columns
REMARKS Update columns in detail-view. If you have inserted, deleted or modified
one ore more columns you must call UpdateColumns to make your changes visible.
Parameters: -
Returns:    -
*/
void XContainerControl :: UpdateColumns( void )
{
   WinSendMsg( winhandle,  CM_INVALIDATEDETAILFIELDINFO, 0,0);
}


/*DOC
CLASS XContainerControl
FUNCTION FindObject
GROUP searching
REMARKS Get an object from the container with relative positions
Parameters: XContainerObject * startObject  search relative to this object (default is NULL)
            SHORT select                    serach setings, valid values are:
                                               CON_FIRST      get the first object of the container
                                               CON_FIRSTCHILD get the first child of startObject
                                               CON_LAST       get the last object of the container
                                               CON_LASTCHILD  get the last child of startObject
                                               CON_NEXT       get the next object relative to startObject
                                               CON_PARENT     get the parent of startObject
                                               CON_PREV       get the previous object relative to startObject
                                            default is CON_FIRST
Returns:    XContainerObject *              pointer to the found object (NULL if nothing is found)
*/
XContainerObject * XContainerControl :: FindObject( XContainerObject * startObject, SHORT select)
{
   RECORDCORE * res, *rel = NULL;

   if( startObject != NULL)
      rel = startObject->core;

   res = (RECORDCORE*) WinSendMsg( winhandle, CM_QUERYRECORD, MPFROMP(rel), MPFROM2SHORT( select, CMA_ITEMORDER));

   if( res > 0)
     {
        RECORDCORE * pr = (RECORDCORE *) ((PBYTE) res + sizeof(RECORDCORE));
        XContainerObject * obj;
        memcpy(&obj, pr, 4);
        return obj;
     }
   else
     return NULL;
}


/*DOC
CLASS XContainerControl
FUNCTION QueryObject
GROUP searching
REMARKS Get an object from the container by querying the objects emphasis
Parameters: XContainerObject * startObject  search relative to this object (default is NULL)
            SHORT filter                    the emphasis to search
                                               CON_CURSORED   the object has the cursored
                                               CON_DISABLED   the object is disabled
                                               CON_INUSE      the objects icon is displayed open
                                               CON_PICKED     the objects icon is displayed dragged
                                               CON_SELECTED   the object is selected
                                               CON_SOURCE     the object get source-emphasis
                                            (default is CON_SELECTED, can be orïed)
Returns:    XContainerObject *              pointer to the found object (NULL if nothing is found)
*/
XContainerObject * XContainerControl :: QueryObject( XContainerObject * startObject, SHORT filter)
{
   RECORDCORE * res, *rel;
   XContainerObject * obj;

   if( startObject )
      rel = startObject->core;
   else
      rel = (PRECORDCORE) CON_FIRST;

   res = (RECORDCORE*) WinSendMsg( winhandle, CM_QUERYRECORDEMPHASIS, MPFROMP(rel), MPFROMSHORT( filter));

   if( res > 0)
     {
        PRECORDCORE pr = (PRECORDCORE) ((PBYTE) res + sizeof(RECORDCORE));
        memcpy(&obj, pr, 4);
        return obj;
     }
   else
     return NULL;
}


/*DOC
CLASS XContainerControl
FUNCTION InvalidateObject
GROUP display
REMARKS invalidates one ore all objects
Prameters: XContainerObject * theObject     the object to invalidate (default is NULL)
           SHORT options                    options, valid values are:
                                               CON_ERASE          erase the background
                                               CON_REPOSITION     reposition
                                               CON_NOREPOSITION   no reposition
                                               CON_TEXTCHANGED    redraw the text
                                             (default is CON_REPOSITION, can be orïed)
Returns:   -
*/
void XContainerControl :: InvalidateObject( XContainerObject * obj, SHORT option)
{
   if( obj )
      WinSendMsg( winhandle, CM_INVALIDATERECORD, MPFROMP(&obj->core), MPFROM2SHORT(1, option));
   else
      WinSendMsg( winhandle,  CM_INVALIDATERECORD, 0, 0);
}


/*DOC
CLASS XContainerControl
FUNCTION RemoveObject
GROUP inserting/removing objects
REMARKS removes an object from the container
Parameters: XContainerObject * theObject    the object to remove
            BOOL destryObject               if TRUE the destructor of theObject is called
                                            if FALSE it exist (usefull if an object is member
                                            of multiple container-controls)
                                            (default is TRUE)
            BOOL redraw                     redraw the container (defeult is TRUE)
Returns:    BOOL                            success
*/
BOOL XContainerControl :: RemoveObject( XContainerObject * obj, BOOL destroyObject, BOOL redraw)
{
   SHORT settings = 0;

   if(destroyObject)
      settings = CMA_FREE;
   if( redraw )
      settings|= CMA_INVALIDATE;

   if ( (LONG) WinSendMsg( winhandle,  CM_REMOVERECORD, MPFROMP( &obj->core), MPFROM2SHORT(1, settings)) == -1)
      return FALSE;
   return TRUE;
}


/*
BOOL XContainerControl :: AddObjectList( XContainerObject ** objectList, SHORT count, XContainerObject * parentObject)
{
   SHORT i;
   RECORDINSERT ri;
   memset(&ri, 0,  sizeof(RECORDINSERT));
   ri.cb = sizeof(RECORDINSERT);
   ri.pRecordOrder = (PRECORDCORE) CMA_END;
   ri.zOrder  = CMA_BOTTOM;
   ri.cRecordsInsert = count;
   ri.fInvalidateRecord = TRUE;

   if( count > 1)
      {
         for(i = count-2; i > 0; i--)
           objectList[i]->core->preccNextRecord = objectList[i+1]->core;
      }
   WinSendMsg( winhandle,  CM_INSERTRECORD, MPFROMP(objectList[0]->core), MPFROMP(&ri));
}
*/


/*DOC
CLASS XContainerControl
FUNCTION AddObject
GROUP inserting/removing objects
REMARKS add an object to the container
Parameters: XContainerObject * theObject    object to add
            XContainerObject * parentObject parent of the object (for tree-view)
                                            (default is NULL)
Returns:    BOOL                            success
*/
BOOL XContainerControl :: AddObject( XContainerObject * object, XContainerObject * parentObject)
{
   RECORDINSERT ri;
   memset(&ri, 0,  sizeof(RECORDINSERT));
   ri.cb = sizeof(RECORDINSERT);
   ri.pRecordOrder = (PRECORDCORE) CMA_END;
   ri.zOrder  = CMA_BOTTOM;
   ri.cRecordsInsert = 1;
   ri.fInvalidateRecord = TRUE;

   if(parentObject)
      ri.pRecordParent = parentObject->core;

   return (BOOL) WinSendMsg( winhandle,  CM_INSERTRECORD, MPFROMP(object->core), MPFROMP(&ri));
}


/*DOC
CLASS XContainerControl
FUNCTION QueryInfo
GROUP info
REMARKS querys information about the container.

Parameters:    XContainerInfo * the information      buffer to hold the information
Returns:       -
*/
void XContainerControl :: QueryInfo( XContainerInfo * info )
{
   WinSendMsg( winhandle,  CM_QUERYCNRINFO , MPFROMP( &info->cnrinfo), (MRESULT) sizeof(CNRINFO));
   info->changes = 0;
}


/*DOC
CLASS XContainerControl
FUNCTION SetInfo
GROUP info
REMARKS Set information how to display the container.

Parameters:    XContainerInfo * the information      See the description of XContainerInfo
Returns:       -
*/
void XContainerControl :: SetInfo( XContainerInfo * info )
{
   WinSendMsg( winhandle,  CM_SETCNRINFO, MPFROMP( &info->cnrinfo ), MPFROMLONG( info->changes ));
   info->changes = 0;
}

/*
BOOL XContainerControl :: Sort( PFN functionPointer)
{
   return WinSendMsg( winhandle, CM_SORTRECORD, MPFROMP(functionPointer), 0);
}
*/


/*DOC
CLASS XContainerControl
FUNCTION Arrange
GROUP display
REMARKS Rearrange the object is the container

Parameters: -
Returns:    -
*/
void XContainerControl :: Arrange( void )
{
   WinSendMsg( winhandle, CM_ARRANGE, 0, 0);
}


/*DOC
CLASS XContainerControl
FUNCTION RemoveAll
GROUP inserting/removing objects
REMARKS Remove all objects from a container

Parameters:    BOOL destroyObjects       the destructors of the objects are called and
                                         memory ascociated with the container is freed.
Returns:       -
*/
void XContainerControl :: RemoveAll( BOOL destroyRecords )
{
   if(destroyRecords)
      {
        PRECORDCORE core = (PRECORDCORE) WinSendMsg( winhandle,  CM_QUERYRECORD, NULL, MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER) );
        XContainerObject * o;
        PRECORDCORE pr;
        if( core == (PRECORDCORE) - 1)
           return;
        while( core )
           {
              pr = (RECORDCORE *) ((PBYTE) core + sizeof(RECORDCORE));
              memcpy(&o, pr, 4);
              if( o )
                 delete o;
              WinSendMsg( winhandle,  CM_REMOVERECORD, &core, MPFROM2SHORT(1, CMA_FREE));
              core = (PRECORDCORE) WinSendMsg( winhandle,  CM_QUERYRECORD, NULL, MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER) );
           }
      }
   else
     WinSendMsg( winhandle,  CM_REMOVERECORD, 0, 0);
}


/*DOC
CLASS XContainerControl
FUNCTION ~XContainerControl
GROUP constructors/destructors
*/
XContainerControl :: XContainerControl(HWND hwnd): XControl( hwnd )
{ ;}

/*DOC
CLASS XContainerControl
FUNCTION XContainerControl
GROUP constructors/destructors
REMARKS

Parameters:    XWindow * theOwner        The owning window.
               XRect * rectangle         Position and size.
               USHORT id                 The id of the window.
                                         Default is zero.
               ULONG style               The style. valid values are:

                                              CON_AUTOPOSITION    objects are arranged automaticaly
                                              CON_EXTENDSEL       extended selection is enabled
                                              CON_MULTIPLESEL     mutiple selection is enabled
                                              CON_READONLY        directe diting is disabled
                                              CON_SINGLESEL       only one object can be selected
Returns:       -
*/
XContainerControl :: XContainerControl( XWindow * owner, XRect * rec, USHORT id, ULONG style): XControl(rec, style, owner, "", WC_CONTAINER, id)
{ ;}


/*DOC
CLASS XContainerControl
FUNCTION RemoveColumn
GROUP columns
REMARKS Removes a column

Parameters:    XContainerColumn * theColumn   The column to delete
               SHORT option                   How to delete. Valid values are:

                                                  CON_FREE        Destruct the column and free
                                                                  container related memory
                                                  CON_INVALIDATE  Redraw the container

Returns:       BOOL                           success
*/
BOOL XContainerControl :: RemoveColumn( XContainerColumn * column, SHORT option)
{
   LONG res = (LONG) WinSendMsg( winhandle, CM_REMOVEDETAILFIELDINFO, MPFROMP( column->info),  MPFROM2SHORT(1, option));

   if(option & CON_FREE)
      delete column;

   if( res < 0)
      return FALSE;
   else
      return TRUE;
}


/*DOC
CLASS XContainerControl
FUNCTION QueryColumn
GROUP columns
REMARKS Query a column from a container.

Parameters:    XContainerColumn * theColumnToSearch  Relative position to begin search. In cases
                                                     CMA_FIRST and CMA_LAST ignored.
               SHORT options                         Valid values are:

                                                        CON_FIRST   Get the first column.
                                                        CON_LAST    Get the last column.
                                                        CON_NEXT    Get the next relative to theColumnToSearch.
                                                        CON_PREV    Get the previous relative to theColumnToSearch.

Returns:       XContainerControl *                   The found column.
*/
XContainerColumn * XContainerControl :: QueryColumn( XContainerColumn * col, SHORT option)
{
   FIELDINFO * i,* p;

   if( col != (XContainerColumn*) CMA_LAST && col != (XContainerColumn*) CMA_FIRST && col != (XContainerColumn*) CMA_PREV && col != (XContainerColumn*) CMA_NEXT)
      p = col->info;
   else
      p = (FIELDINFO*) col;

   i = (FIELDINFO*) WinSendMsg( winhandle,  CM_QUERYDETAILFIELDINFO, MPFROMP(p), MPFROMSHORT(option));
   if( i == NULL || i == (FIELDINFO*) -1)
      return NULL;
   XContainerColumn * c;
   memcpy( c, i->pUserData, sizeof(void*));
   return c;
}


/*DOC
CLASS XContainerControl
FUNCTION InsertColumn
GROUP columns
REMARKS Insert a column into a container. After you have added one or more columns,
you must call Invalidate() so the columns are drawn.

Parameters:    XContainerColumn * theColumnToInsert  This column should be inserted
               XContainerColumn * insertPosition     The position to insert. Valid values are:

                                                        CON_FIRST         Insert as the first column.
                                                        CON_LAST          Insert as the last column.
                                                        XContaineColumn*  The column behind which the
                                                                          column should be inserted

Returns:       BOOL                                  success
*/
BOOL XContainerControl :: InsertColumn( XContainerColumn * column, XContainerColumn * insertBehind, BOOL redraw)
{
   FIELDINFOINSERT insert;

   insert.cb = sizeof(insert);

   insert.fInvalidateFieldInfo = redraw;
   if( insertBehind )
      {
         if( insertBehind != (XContainerColumn *) CMA_FIRST && insertBehind != (XContainerColumn *) CMA_END)
            insert.pFieldInfoOrder = insertBehind->info;
         else
            insert.pFieldInfoOrder = (FIELDINFO*) insertBehind;
      }
   else
      insert.pFieldInfoOrder = (FIELDINFO*) CMA_FIRST;

   insert.cFieldInfoInsert = 1;

   if( SHORT1FROMMR(WinSendMsg( winhandle,  CM_INSERTDETAILFIELDINFO, MPFROMP( column->info), MPFROMP( &insert ))) == 0)
      return FALSE;
   else
      return TRUE;
}


