DLLEXPORT_TEST_FUNCTION void PdfGenerator_Destroy(struct PdfGenerator *self) { // clear page balloons while(self->pageBalloons->size > 0) { struct PdfGeneratedBalloon *obj; obj = (struct PdfGeneratedBalloon *)DLList_Back(self->pageBalloons); DLList_PopBack(self->pageBalloons); PdfGeneratedBalloon_Destroy(obj); } DLList_Destroy(self->pageBalloons); // clear rect matrix while(self->rectMatrix->size > 0) { struct Rectangle *obj; obj = (struct Rectangle *)DLList_Back(self->rectMatrix); DLList_PopBack(self->rectMatrix); Rectangle_Destroy(obj); } DLList_Destroy(self->rectMatrix); // destroy all data streams PdfGenerator_ClearDataStreams(self); MemoryManager_Free(self); }
void PdfGenerator_ClearDataStreams(struct PdfGenerator* self) { while(self->dataStreams->size > 0) { struct PdfGeneratorDataStream *obj; obj = (struct PdfGeneratorDataStream *)DLList_Back(self->dataStreams); DLList_PopBack(self->dataStreams); PdfGeneratorDataStream_Destroy(obj); } DLList_Destroy(self->dataStreams); // destroy list itself }
/*---------------------------------------------------------------------- * Empty an hash map. * All element are freed. * @param map Map to empty. -----------------------------------------------------------------------*/ void HashMap_Empty(HashMap map) { int i; if (map->nodes) { for (i=0; i < map->nbNodes; i++) { if (map->nodes[i] !=NULL) { DLList_Destroy ((DLList)map->nodes[i]); map->nodes[i] = NULL; } } } }
// This returns false when something is wrong // parentBalloon can be null. This means top level balloons should be used int PdfGenerator_GenerateBalloons(struct PdfGenerator *self, struct PdfTemplateBalloon *parentBalloon, struct PdfGeneratedBalloon *parentGeneratedBalloon, int level) { struct PdfTemplate *pdfTemplate = self->pdfTemplate; struct PdfTemplatePage *currentPageTemplate = self->pdfTemplate->page; struct DLListNode *iter; struct DLList *balloons; struct DLList *newBottomDockedBalloons; struct PdfTemplateBalloon *balloon; struct PdfGeneratorDataStream *stream; struct PdfGeneratedBalloon *newGeneratedBalloon; int tmpI = 0; int genRes; int dynamicBalloonProcessed = FALSE; char *tmpStr; short generatorResult = GENERATE_BALLOONS_OK; short generatorResultStatic = GENERATE_BALLOONS_OK; newBottomDockedBalloons = DLList_Create(); if (!parentBalloon) { Logger_LogNoticeMessage("PdfGenerator_GenerateBalloons: BEGIN NO PARENT BALLOON"); balloons = currentPageTemplate->balloons; } else { Logger_LogNoticeMessage("PdfGenerator_GenerateBalloons: BEGIN HAS PARENT BALLOON"); balloons = parentBalloon->balloons; } // 1. generate static balloons for(iter = DLList_Begin(balloons); iter != DLList_End(balloons); iter = iter->next) { balloon = (struct PdfTemplateBalloon*)iter->data; // skip balloons that are already generated and that are not available on every page if (!balloon->availableOnEveryPage && balloon->lastGeneratedPageNumber < self->pageNumber) { Logger_LogNoticeMessage("PdfGenerator_GenerateBalloons: Skip balloons - if (!balloon->availableOnEveryPage && balloon->lastGeneratedPageNumber < self->pageNumber)"); continue; } // Skip ballons that are top docked and have prev dynamic balloon top docked if (balloon->isStatic && balloon->dockPosition == DOCK_TOP && balloon->hasPrevDynamicTopDocked) { continue; } // if this is balloon on page that is bottom docked then just take place for it or // if this is balloon inside ballon that cannot grow if ((balloon->isStatic && balloon->dockPosition == DOCK_BOTTOM && parentBalloon == NULL) || (balloon->isStatic && balloon->dockPosition == DOCK_BOTTOM && balloon->parentBalloon != NULL && !balloon->parentBalloon->canGrow)) { // create it as standard static balloon but do not draw children items yet just allocate space for it newGeneratedBalloon = PdfGenerator_WriteBalloon(self, balloon, currentPageTemplate, parentGeneratedBalloon, TRUE, FALSE, TRUE); DLList_PushBack(newBottomDockedBalloons, newGeneratedBalloon); } // If this ballon is static and not docked bottom then generate it else if (balloon->isStatic && balloon->dockPosition != DOCK_BOTTOM) { // Check its data stream. If not initialized call InitializeDataStreamCallback. if failed stop stream = PdfGenerator_FindDataStream(self, balloon->dataStream); if (!balloon->skipDataReadMarker && !self->pageSkipDataReadMarker) { if (parentBalloon) { tmpStr = parentBalloon->dataStream; } else { tmpStr = NULL; } // It is ok to have no data stream to initialize for static ballons if (balloon->dataStream) { if (!PdfGenerator_InitializeDataStream(self, tmpStr, balloon->dataStream)) { Logger_LogErrorMessage("PdfGenerator_GenerateBalloons: Initializing data stream on static balloon. DataStream: %s FAILED", balloon->dataStream); return FALSE; } else { Logger_LogNoticeMessage("PdfGenerator_GenerateBalloons: Initializing data stream on static balloon. DataStream: %s SUCCESS", balloon->dataStream); } } } // Call ReadDataCallback if required if (balloon->dataStream) { if (self->readDataCallback) { if (!balloon->skipDataReadMarker && !self->pageSkipDataReadMarker) { if (!stream || (stream && !stream->initialized)) { self->readDataCallback(balloon->dataStream); Logger_LogNoticeMessage("PdfGenerator_GenerateBalloons: Read data callback for DataStream: %s SUCCESS", balloon->dataStream); } else { Logger_LogNoticeMessage("PdfGenerator_GenerateBalloons: Read data callback for DataStream %s not done. Stream Not initialized or null", balloon->dataStream); } } else { Logger_LogNoticeMessage("PdfGenerator_GenerateBalloons: Read Data not done for DataStream %s as skipDataReadMarker is true", balloon->dataStream); } } else { Logger_LogErrorMessage("PdfGenerator_GenerateBalloons: Read data callback is missing for DataStream: %s FAILED", balloon->dataStream); return FALSE; } } newGeneratedBalloon = PdfGenerator_WriteBalloon(self, balloon, currentPageTemplate, parentGeneratedBalloon, TRUE, TRUE, FALSE); // 8. Recursive call to 1. with parent balloon set as this genRes = PdfGenerator_GenerateBalloons(self, balloon, newGeneratedBalloon, level+1); // write balloon borders PdfGenerator_DrawBalloonBorders(self, balloon, newGeneratedBalloon); balloon->lastGeneratedPageNumber = self->pageNumber; if (genRes == GENERATE_BALLOONS_NOT_ENOUGH_SPACE) { Logger_LogNoticeMessage("PdfGenerator_GenerateBalloons: Static balloon returned NOT ENOUGH SPACE END"); generatorResultStatic = GENERATE_BALLOONS_NOT_ENOUGH_SPACE; } else if (genRes == GENERATE_BALLOONS_FAILED) { Logger_LogNoticeMessage("PdfGenerator_GenerateBalloons: Returned GENERATE_BALLOONS_FAILED END", balloon->dataStream); return genRes; } } } // foreach static balloon generatorResult = GENERATE_BALLOONS_OK; // 2. Generate Dynamic balloons for(iter = DLList_Begin(balloons); iter != DLList_End(balloons); iter = iter->next) { balloon = (struct PdfTemplateBalloon*)iter->data; if (!balloon->isStatic) { // 2. Check its data stream. If not initialized call InitializeDataStreamCallback. if failed stop if (!balloon->skipDataReadMarker && !self->pageSkipDataReadMarker) { if (parentBalloon) { tmpStr = parentBalloon->dataStream; } else { tmpStr = NULL; } if (!PdfGenerator_InitializeDataStream(self, tmpStr, balloon->dataStream)) { Logger_LogErrorMessage("PdfGenerator_GenerateBalloons: InitializeDataStream failed for dynamic balloon. DataStream: %s FAILED", balloon->dataStream); return FALSE; } else { Logger_LogNoticeMessage("PdfGenerator_GenerateBalloons: Initializing data stream on dynamic balloon. DataStream: %s SUCCESS", balloon->dataStream); } } stream = PdfGenerator_FindDataStream(self, balloon->dataStream); if (self->readDataCallback) { while(1) { if (!balloon->skipDataReadMarker && !self->pageSkipDataReadMarker) { if (!balloon->dataStream) { break; } if (!self->readDataCallback(balloon->dataStream)) { break; } } newGeneratedBalloon = PdfGenerator_WriteBalloon(self, balloon, currentPageTemplate, parentGeneratedBalloon, FALSE, TRUE, FALSE); if (!newGeneratedBalloon) { Logger_LogNoticeMessage("PdfGenerator_GenerateBalloons: Creating new generated balloon failed. DataStream: %s", balloon->dataStream); if (parentBalloon) { // mark parent not to move data and this balloon as we already read some data that was not written parentBalloon->skipDataReadMarker = TRUE; balloon->skipDataReadMarker = TRUE; } else { self->pageSkipDataReadMarker = TRUE; balloon->skipDataReadMarker = TRUE; } // we failed generating new balloon as not possible to write new one inside parent Generated Balloon. We need new parent. Logger_LogNoticeMessage("PdfGenerator_GenerateBalloons: DataStream: %s, Returned NOT ENOUGH SPACE END", balloon->dataStream); generatorResult = GENERATE_BALLOONS_NOT_ENOUGH_SPACE; goto GenerateBottomDocked; } else { // remove skip data markers when we generated new item correctly Logger_LogNoticeMessage("PdfGenerator_GenerateBalloons: DataStream: %s, New generated ballon created.", balloon->dataStream); balloon->skipDataReadMarker = FALSE; self->pageSkipDataReadMarker = FALSE; } // Recursive call to 1. with parent balloon set as this genRes = PdfGenerator_GenerateBalloons(self, balloon, newGeneratedBalloon, level+1); // write balloon borders PdfGenerator_DrawBalloonBorders(self, balloon, newGeneratedBalloon); balloon->lastGeneratedPageNumber = self->pageNumber; if (genRes == GENERATE_BALLOONS_NOT_ENOUGH_SPACE) { // we should continue to next iteration without checking condition and reading data Logger_LogNoticeMessage("PdfGenerator_GenerateBalloons: Not Enough Space, continue.", balloon->dataStream); continue; } else if (genRes == GENERATE_BALLOONS_FAILED) { Logger_LogNoticeMessage("PdfGenerator_GenerateBalloons: DataStream: %s, Returned GENERATE_FAILED END", balloon->dataStream); return genRes; } } } else { Logger_LogNoticeMessage("PdfGenerator_GenerateBalloons: DataStream: %s, No ReadData callback. Returned GENERATE_FAILED END", balloon->dataStream); return GENERATE_BALLOONS_FAILED; } if (stream) { stream->initialized = FALSE; } else { Logger_LogNoticeMessage("PdfGenerator_GenerateBalloons: DataStream: %s, No Stream. Returned GENERATE_FAILED END", balloon->dataStream); return GENERATE_BALLOONS_FAILED; } } } // 3. generate bottom docked static balloons // move to the last element and perform reverse until end iter = DLList_End(balloons); iter = iter->prev; for( ; iter != DLList_End(balloons) ; iter = iter->prev) { balloon = (struct PdfTemplateBalloon*)iter->data; // if balloon is static, bottom docked and its parent balloon is not null and can grow if (balloon->isStatic && balloon->dockPosition == DOCK_BOTTOM && parentBalloon != NULL && parentBalloon->canGrow) { // write new balloon but handle it as dynamic balloon newGeneratedBalloon = PdfGenerator_WriteBalloon(self, balloon, currentPageTemplate, parentGeneratedBalloon, FALSE, TRUE, TRUE); // if this balloon is not created that means we are missing it if (!newGeneratedBalloon) { Logger_LogNoticeMessage("PdfGenerator_GenerateBalloons: Creating new generated balloon failed. DataStream: %s", balloon->dataStream); if (parentBalloon) { // mark parent not to move data and this balloon as we already read some data that was not written parentBalloon->skipDataReadMarker = TRUE; balloon->skipDataReadMarker = TRUE; } else { self->pageSkipDataReadMarker = TRUE; balloon->skipDataReadMarker = TRUE; } if (stream) { // keep stream initialized as we want more items stream->initialized = TRUE; } // we failed generating new balloon as not possible to write new one inside parent Generated Balloon. We need new parent. Logger_LogNoticeMessage("PdfGenerator_GenerateBalloons: DataStream: %s, Returned NOT ENOUGH SPACE END", balloon->dataStream); generatorResult = GENERATE_BALLOONS_NOT_ENOUGH_SPACE; goto GenerateBottomDocked; } else { // remove skip data markers when we generated new item correctly Logger_LogNoticeMessage("PdfGenerator_GenerateBalloons: DataStream: %s, New generated ballon created.", balloon->dataStream); balloon->skipDataReadMarker = FALSE; self->pageSkipDataReadMarker = FALSE; } // if this newDynamicBalloon is not generated to be bottom one move it down genRes = PdfGenerator_GenerateBalloons(self, balloon, newGeneratedBalloon, level+1); PdfGenerator_DrawBalloonBorders(self, balloon, newGeneratedBalloon); balloon->lastGeneratedPageNumber = self->pageNumber; if (genRes == GENERATE_BALLOONS_NOT_ENOUGH_SPACE) { Logger_LogNoticeMessage("PdfGenerator_GenerateBalloons - Generate Bottom Docked static ones: DataStream: %s, Returned NOT ENOUGH SPACE END", balloon->dataStream); } else if (genRes == GENERATE_BALLOONS_FAILED) { Logger_LogNoticeMessage("PdfGenerator_GenerateBalloons - Generate Bottom Docked static ones: DataStream: %s, No Stream. Returned GENERATE_FAILED END", balloon->dataStream); return genRes; } } } // foreach static balloon docked bottom // 4. Generate top docked balloons for(iter = DLList_Begin(balloons); iter != DLList_End(balloons); iter = iter->next) { balloon = (struct PdfTemplateBalloon*)iter->data; // if balloon is static, bottom docked and its parent balloon is not null and can grow if (balloon->isStatic && balloon->dockPosition == DOCK_TOP && balloon->hasPrevDynamicTopDocked) { // write new balloon but handle it as dynamic balloon newGeneratedBalloon = PdfGenerator_WriteBalloon(self, balloon, currentPageTemplate, parentGeneratedBalloon, FALSE, TRUE, FALSE); // if this balloon is not created that means we are missing it if (!newGeneratedBalloon) { Logger_LogNoticeMessage("PdfGenerator_GenerateBalloons: Creating new generated balloon failed. DataStream: %s", balloon->dataStream); if (parentBalloon) { // mark parent not to move data and this balloon as we already read some data that was not written parentBalloon->skipDataReadMarker = TRUE; balloon->skipDataReadMarker = TRUE; } else { self->pageSkipDataReadMarker = TRUE; balloon->skipDataReadMarker = TRUE; } if (stream) { // keep stream initialized as we want more items stream->initialized = TRUE; } // we failed generating new balloon as not possible to write new one inside parent Generated Balloon. We need new parent. Logger_LogNoticeMessage("PdfGenerator_GenerateBalloons: DataStream: %s, Returned NOT ENOUGH SPACE END", balloon->dataStream); generatorResult = GENERATE_BALLOONS_NOT_ENOUGH_SPACE; goto GenerateBottomDocked; } else { // remove skip data markers when we generated new item correctly Logger_LogNoticeMessage("PdfGenerator_GenerateBalloons: DataStream: %s, New generated ballon created.", balloon->dataStream); balloon->skipDataReadMarker = FALSE; self->pageSkipDataReadMarker = FALSE; } // if this newDynamicBalloon is not generated to be bottom one move it down genRes = PdfGenerator_GenerateBalloons(self, balloon, newGeneratedBalloon, level+1); PdfGenerator_DrawBalloonBorders(self, balloon, newGeneratedBalloon); balloon->lastGeneratedPageNumber = self->pageNumber; if (genRes == GENERATE_BALLOONS_NOT_ENOUGH_SPACE) { Logger_LogNoticeMessage("PdfGenerator_GenerateBalloons - Generate Bottom Docked static ones: DataStream: %s, Returned NOT ENOUGH SPACE END", balloon->dataStream); } else if (genRes == GENERATE_BALLOONS_FAILED) { Logger_LogNoticeMessage("PdfGenerator_GenerateBalloons - Generate Bottom Docked static ones: DataStream: %s, No Stream. Returned GENERATE_FAILED END", balloon->dataStream); return genRes; } } } // foreach static balloon docked top GenerateBottomDocked: PdfGenerator_DrawRemainingBalloons(self, newBottomDockedBalloons); DLList_Destroy(newBottomDockedBalloons); // return not enough space if static requested more space if (generatorResultStatic == GENERATE_BALLOONS_NOT_ENOUGH_SPACE) { Logger_LogNoticeMessage("PdfGenerator_GenerateBalloons: Returned NOT ENOUGH SPACE because of static"); return generatorResultStatic; } else { if (generatorResult == GENERATE_BALLOONS_NOT_ENOUGH_SPACE) { Logger_LogNoticeMessage("PdfGenerator_GenerateBalloons: Returned NOT ENOUGH SPACE"); } else { Logger_LogNoticeMessage("PdfGenerator_GenerateBalloons: Returned OK"); } return generatorResult; } }
/*---------------------------------------------------------------------- SetupListValue init the attribut list ----------------------------------------------------------------------*/ void AmayaAttributeToolPanel::SetupListValue(DLList attrList) { ForwardIterator iter; DLListNode node; PtrAttrListElem elem; TtAttribute *pAttr; long index; char buffer[MAX_TXT_LEN]; int size; AttributeType type; m_pAttrList->DeleteAllItems(); m_pNewAttrChoice->Clear(); m_pVPanelSizer->Hide((size_t)0); if (m_attrList) DLList_Destroy(m_attrList); m_attrList = attrList; if (attrList) { iter = DLList_GetForwardIterator(attrList); ITERATOR_FOREACH(iter, DLListNode, node) { elem = (PtrAttrListElem)node->elem; if (elem) { if (elem->val) { index = m_pAttrList->InsertItem(m_pAttrList->GetItemCount(), TtaConvMessageToWX(AttrListElem_GetName(elem))); switch(AttrListElem_GetType(elem)) { case AtNumAttr: m_pAttrList->SetItem(index, 1, wxString::Format(wxT("%d"), TtaGetAttributeValue((Attribute)elem->val))); break; case AtTextAttr: size = MAX_TXT_LEN; TtaGiveTextAttributeValue((Attribute)elem->val, buffer, &size); m_pAttrList->SetItem(index, 1, TtaConvMessageToWX(buffer)); break; case AtEnumAttr: type.AttrSSchema = (int*) elem->pSS; type.AttrTypeNum = elem->num; pAttr = AttrListElem_GetTtAttribute(elem); if (pAttr->AttrNEnumValues == 1 && !strcasecmp (pAttr->AttrEnumValue[0], "yes")) // this is a boolean value m_pAttrList->SetItem(index, 1, TtaConvMessageToWX(pAttr->AttrName)); else m_pAttrList->SetItem(index, 1, TtaConvMessageToWX( TtaGetAttributeValueName(type, TtaGetAttributeValue((Attribute)elem->val)))); break; case AtReferenceAttr: default: break; } if (AttrListElem_IsNew(elem)) m_pAttrList->SetItemTextColour(index, COLOR_NEW); else if (AttrListElem_IsReadOnly(elem)) m_pAttrList->SetItemTextColour(index, COLOR_READONLY); else if (AttrListElem_IsMandatory(elem)) m_pAttrList->SetItemTextColour(index, COLOR_MANDATORY); m_pAttrList->SetItemData(index, (long)elem); } else { index = m_pNewAttrChoice->Append( TtaConvMessageToWX(AttrListElem_GetName(elem))); m_pNewAttrChoice->SetClientData(index, (void*)elem); } } } TtaFreeMemory(iter); }