sl@0: /*
sl@0:  **********************************************************************
sl@0:  *   Copyright (C) 1998-2004, International Business Machines
sl@0:  *   Corporation and others.  All Rights Reserved.
sl@0:  **********************************************************************
sl@0:  */
sl@0: 
sl@0: #include "LETypes.h"
sl@0: #include "LEInsertionList.h"
sl@0: 
sl@0: U_NAMESPACE_BEGIN
sl@0: 
sl@0: #define ANY_NUMBER 1
sl@0: 
sl@0: struct InsertionRecord
sl@0: {
sl@0:     InsertionRecord *next;
sl@0:     le_int32 position;
sl@0:     le_int32 count;
sl@0:     LEGlyphID glyphs[ANY_NUMBER];
sl@0: };
sl@0: 
sl@0: UOBJECT_DEFINE_RTTI_IMPLEMENTATION(LEInsertionList)
sl@0: 
sl@0: LEInsertionList::LEInsertionList(le_bool rightToLeft)
sl@0: : head(NULL), tail(NULL), growAmount(0), append(rightToLeft)
sl@0: {
sl@0:     tail = (InsertionRecord *) &head;
sl@0: }
sl@0: 
sl@0: LEInsertionList::~LEInsertionList()
sl@0: {
sl@0:     reset();
sl@0: }
sl@0: 
sl@0: void LEInsertionList::reset()
sl@0: {
sl@0:     while (head != NULL) {
sl@0:         InsertionRecord *record = head;
sl@0: 
sl@0:         head = head->next;
sl@0:         LE_DELETE_ARRAY(record);
sl@0:     }
sl@0: 
sl@0:     tail = (InsertionRecord *) &head;
sl@0:     growAmount = 0;
sl@0: }
sl@0: 
sl@0: le_int32 LEInsertionList::getGrowAmount()
sl@0: {
sl@0:     return growAmount;
sl@0: }
sl@0: 
sl@0: LEGlyphID *LEInsertionList::insert(le_int32 position, le_int32 count,
sl@0:     LEErrorCode &success)
sl@0: {
sl@0:     if (LE_FAILURE(success)) {
sl@0:         return 0;
sl@0:     }
sl@0: 
sl@0:     InsertionRecord *insertion = (InsertionRecord *) LE_NEW_ARRAY(char, sizeof(InsertionRecord) + (count - ANY_NUMBER) * sizeof (LEGlyphID));
sl@0: 
sl@0:     if (!insertion) {
sl@0:     	success = LE_MEMORY_ALLOCATION_ERROR;
sl@0:         return 0;
sl@0:     }
sl@0: 
sl@0:     insertion->position = position;
sl@0:     insertion->count = count;
sl@0: 
sl@0:     growAmount += count - 1;
sl@0: 
sl@0:     if (append) {
sl@0:         // insert on end of list...
sl@0:         insertion->next = NULL;
sl@0:         tail->next = insertion;
sl@0:         tail = insertion;
sl@0:     } else {
sl@0:         // insert on front of list...
sl@0:         insertion->next = head;
sl@0:         head = insertion;
sl@0:     }
sl@0: 
sl@0:     return insertion->glyphs;
sl@0: }
sl@0: 
sl@0: le_bool LEInsertionList::applyInsertions(LEInsertionCallback *callback)
sl@0: {
sl@0:     for (InsertionRecord *rec = head; rec != NULL; rec = rec->next) {
sl@0:         if (callback->applyInsertion(rec->position, rec->count, rec->glyphs)) {
sl@0:             return TRUE;
sl@0:         }
sl@0:     }
sl@0: 
sl@0:     return FALSE;
sl@0: }
sl@0: 
sl@0: U_NAMESPACE_END