system/lib/lcd/gui/Widget/GUI_ARRAY.c

335 lines
9.1 KiB
C

/*
*********************************************************************************************************
* uC/GUI
* Universal graphic software for embedded applications
*
* (c) Copyright 2002, Micrium Inc., Weston, FL
* (c) Copyright 2002, SEGGER Microcontroller Systeme GmbH
*
* µC/GUI is protected by international copyright laws. Knowledge of the
* source code may not be used to write a similar product. This file may
* only be used in accordance with a license and should not be redistributed
* in any way. We appreciate your understanding and fairness.
*
----------------------------------------------------------------------
File : GUI_ARRAY.c
Purpose : Array handling routines
---------------------------END-OF-HEADER------------------------------
*/
#include "GUI_ARRAY.h"
#include <string.h>
#if GUI_WINSUPPORT
/*********************************************************************
*
* public code
*
**********************************************************************
*/
/*********************************************************************
*
* GUI_ARRAY_GetNumItems
*/
unsigned int GUI_ARRAY_GetNumItems(const GUI_ARRAY* pThis) {
GUI_ARRAY_CHECK(pThis); /* Sanity checks at higher debug levels only */
return pThis->NumItems;
}
/*********************************************************************
*
* GUI_ARRAY_AddItem
*
* Purpose:
* Add an item to a GUI_ARRAY.
* If the SIze is > 0, a memory block is allocated for storage.
* If on top of this a pointer is specified, the memory block holding
* the copy of the item is initialized.
*
* Return value:
* If O.K. : 0
* On error: 1
*
*/
int GUI_ARRAY_AddItem(GUI_ARRAY* pThis, const void *pNew, int Len) {
WM_HMEM hNewItem = 0;
WM_HMEM hNewBuffer;
WM_HMEM *pNewBuffer;
int r = 0;
GUI_ARRAY_CHECK(pThis); /* Sanity checks at higher debug levels only */
WM_LOCK();
/* Alloc memory for new item */
if (Len) {
if ((hNewItem = GUI_ALLOC_AllocInit(pNew, Len)) == 0) {
GUI_DEBUG_ERROROUT("GUI_ARRAY_AddItem failed to alloc buffer");
r = 1; /* Error */
}
}
/* Put handle of new item into the array */
if (r == 0) {
int NumItems;
NumItems = pThis->NumItems;
/* Add the handle to new item to the buffer */
hNewBuffer = GUI_ALLOC_Realloc(pThis->haHandle, (NumItems + 1) * sizeof(WM_HMEM));
if (hNewBuffer == 0) {
GUI_DEBUG_ERROROUT("GUI_ARRAY_AddItem failed to alloc buffer");
GUI_ALLOC_Free(hNewItem);
r = 1; /* Error */
} else {
pNewBuffer = (WM_HMEM*) GUI_ALLOC_h2p(hNewBuffer);
*(pNewBuffer + NumItems) = hNewItem;
pThis->haHandle = hNewBuffer;
pThis->NumItems++;
}
}
WM_UNLOCK();
return r;
}
/*********************************************************************
*
* GUI_ARRAY_Delete
*
* Purpose:
* Free all allocated memory blocks
*
* Add. info:
* Locking is not required, since this routine is considered internal
* and should only be called after locking.
*/
void GUI_ARRAY_Delete(GUI_ARRAY* pThis) {
int i;
WM_HMEM ha;
WM_HMEM* pa;
GUI_ARRAY_CHECK(pThis); /* Sanity checks at higher debug levels only */
ha = pThis->haHandle;
if (ha) {
pa = (WM_HMEM*) GUI_ALLOC_h2p(ha);
/* Free the attached items, one at a time */
for (i = 0; i < pThis->NumItems; i++) {
GUI_ALLOC_FreePtr(pa+i);
}
/* Free the handle buffer */
GUI_ALLOC_FreePtr(&pThis->haHandle);
pThis->NumItems = 0; /* For safety, in case the array is used after it has been deleted */
}
#if GUI_DEBUG_LEVEL >= GUI_DEBUG_LEVEL_CHECK_ALL
pThis->InitState = GUI_ARRAY_STATE_DELETED;
#endif
}
/*********************************************************************
*
* GUI_ARRAY_SethItem
*
* Purpose:
* Sets an item.
*
* Returns:
* 1: if operation has failed
* 0: OK
*
* Notes:
* (1) Replacing Items
* If the item is already assigned
* (Which means the handle is already != 0), it is freeed. However,
* the handle is treated as a handle to a data item, not an object.
* This means the data item is freed, but if the pointer points to
* an object, the destructor of the object is not called.
*/
int GUI_ARRAY_SethItem(GUI_ARRAY* pThis, unsigned int Index, WM_HMEM hItem) {
WM_HMEM ha;
WM_HMEM* pa;
int r = 1;
GUI_ARRAY_CHECK(pThis); /* Sanity checks at higher debug levels only */
if (Index < (unsigned)pThis->NumItems) {
ha = pThis->haHandle;
if (ha) {
pa = (WM_HMEM*) GUI_ALLOC_h2p(ha);
pa += Index;
GUI_ALLOC_FreePtr(pa);
*pa = hItem;
r = 0;
}
}
return r;
}
/*********************************************************************
*
* GUI_ARRAY_SetItem
*
* Purpose:
* Sets an item, returning the handle.
* If a data pointer is given, the allocated memory is initialized from it thru memcpy.
*
* Returns:
* Handle of the allocated memory block
*
* Notes:
* (1) Replacing Items
* If the item is already assigned
* (Which means the handle is already != 0), it is freeed. However,
* the handle is treated as a handle to a data item, not an object.
* This means the data item is freed, but if the pointer points to
* an object, the destructor of the object is not called.
*/
WM_HMEM GUI_ARRAY_SetItem(GUI_ARRAY* pThis, unsigned int Index, const void* pData, int Len) {
WM_HMEM hItem = 0;
GUI_ARRAY_CHECK(pThis); /* Sanity checks at higher debug levels only */
if (Index < (unsigned)pThis->NumItems) {
WM_HMEM ha;
ha = pThis->haHandle;
if (ha) {
WM_HMEM* pa;
pa = (WM_HMEM*) GUI_ALLOC_h2p(ha);
pa += Index;
hItem = *pa;
/*
* If a buffer is already available, a new buffer is only needed when the
* new item has a different size.
*/
if (hItem) {
if (GUI_ALLOC_GetSize(hItem) != Len) {
hItem = 0;
}
}
/*
* Allocate a new buffer and free the old one (if needed).
*/
if (!hItem) {
hItem = GUI_ALLOC_AllocZero(Len);
if (hItem) {
GUI_ALLOC_FreePtr(pa);
*pa = hItem;
}
}
/*
* Set the item (if needed)
*/
if (pData && hItem) {
char* pItem = (char*) GUI_ALLOC_h2p(hItem);
memcpy(pItem, pData, Len);
}
}
}
return hItem;
}
/*********************************************************************
*
* GUI_ARRAY_GethItem
*
* Purpose:
* Gets the handle of specified item
*
* Notes:
* (1) Index out of bounds
* It is permitted to specify an index larger than the
* array size. In this case, a 0-handle is returned.
*/
WM_HMEM GUI_ARRAY_GethItem(const GUI_ARRAY* pThis, unsigned int Index) {
WM_HMEM h = 0;
GUI_ARRAY_CHECK(pThis); /* Sanity checks at higher debug levels only */
if (Index < (unsigned)pThis->NumItems) {
WM_HMEM ha;
WM_HMEM* pa;
ha = pThis->haHandle;
if (ha) {
pa = (WM_HMEM*) GUI_ALLOC_h2p(ha);
h = *(pa + Index);
}
}
return h;
}
/*********************************************************************
*
* GUI_ARRAY_GetpItem
*
* Purpose:
* Gets the pointer of specified item
*
* Notes:
* (1) Index out of bounds
* It is permitted to specify an index larger than the
* array size. In this case, a 0-handle is returned.
* (2) Locking
* It is the caller's responsibility to lock before calling this
* function.
*/
void* GUI_ARRAY_GetpItem(const GUI_ARRAY* pThis, unsigned int Index) {
void* p = NULL;
WM_HMEM h;
GUI_ARRAY_CHECK(pThis); /* Sanity checks at higher debug levels only */
h = GUI_ARRAY_GethItem(pThis, Index);
if (h) {
p = WM_H2P(h);
}
return p;
}
/*********************************************************************
*
* Debug support
*
**********************************************************************
*
* Purpose:
* The routines below are required only at higher debug levels
*/
#if GUI_DEBUG_LEVEL >= GUI_DEBUG_LEVEL_CHECK_ALL
/*********************************************************************
*
* GUI_ARRAY_Create
*
* Purpose:
*/
void GUI_ARRAY_Create(GUI_ARRAY * pThis) {
GUI_DEBUG_ERROROUT_IF(pThis->InitState != GUI_ARRAY_STATE_NOT_CREATED, "GUI_ARRAY_Create: GUI_ARRAY not initialized to 0");
pThis->InitState = GUI_ARRAY_STATE_CREATED;
}
/*********************************************************************
*
* GUI_ARRAY_Check
*
* Purpose:
*/
void GUI_ARRAY_Check(const GUI_ARRAY * pThis) {
if (pThis->InitState == GUI_ARRAY_STATE_DELETED) {
GUI_DEBUG_ERROROUT("GUI_ARRAY_Check: GUI_ARRAY has been deleted");
} else if (pThis->InitState == GUI_ARRAY_STATE_NOT_CREATED) {
GUI_DEBUG_ERROROUT("GUI_ARRAY_Check: GUI_ARRAY has not been created");
} else if (pThis->InitState != GUI_ARRAY_STATE_CREATED) {
GUI_DEBUG_ERROROUT("GUI_ARRAY_Check: GUI_ARRAY in unknown state");
}
}
#endif /* GUI_DEBUG_LEVEL >= GUI_DEBUG_LEVEL_CHECK_ALL */
#else /* avoid empty object files */
void GUI_ARRAY_C(void);
void GUI_ARRAY_C(void){}
#endif /* GUI_WINSUPPORT */