1/*
2 **********************************************************************
3 *   Copyright (C) 1998-2008, International Business Machines
4 *   Corporation and others.  All Rights Reserved.
5 **********************************************************************
6 */
7
8#include "LETypes.h"
9#include "LEInsertionList.h"
10
11U_NAMESPACE_BEGIN
12
13#define ANY_NUMBER 1
14
15struct InsertionRecord
16{
17    InsertionRecord *next;
18    le_int32 position;
19    le_int32 count;
20    LEGlyphID glyphs[ANY_NUMBER];
21};
22
23UOBJECT_DEFINE_RTTI_IMPLEMENTATION(LEInsertionList)
24
25LEInsertionList::LEInsertionList(le_bool rightToLeft)
26: head(NULL), tail(NULL), growAmount(0), append(rightToLeft)
27{
28    tail = (InsertionRecord *) &head;
29}
30
31LEInsertionList::~LEInsertionList()
32{
33    reset();
34}
35
36void LEInsertionList::reset()
37{
38    while (head != NULL) {
39        InsertionRecord *record = head;
40
41        head = head->next;
42        LE_DELETE_ARRAY(record);
43    }
44
45    tail = (InsertionRecord *) &head;
46    growAmount = 0;
47}
48
49le_int32 LEInsertionList::getGrowAmount()
50{
51    return growAmount;
52}
53
54LEGlyphID *LEInsertionList::insert(le_int32 position, le_int32 count, LEErrorCode &success)
55{
56    if (LE_FAILURE(success)) {
57        return 0;
58    }
59
60    InsertionRecord *insertion = (InsertionRecord *) LE_NEW_ARRAY(char, sizeof(InsertionRecord) + (count - ANY_NUMBER) * sizeof (LEGlyphID));
61    if (insertion == NULL) {
62        success = LE_MEMORY_ALLOCATION_ERROR;
63        return 0;
64    }
65
66    insertion->position = position;
67    insertion->count = count;
68
69    growAmount += count - 1;
70
71    if (append) {
72        // insert on end of list...
73        insertion->next = NULL;
74        tail->next = insertion;
75        tail = insertion;
76    } else {
77        // insert on front of list...
78        insertion->next = head;
79        head = insertion;
80    }
81
82    return insertion->glyphs;
83}
84
85le_bool LEInsertionList::applyInsertions(LEInsertionCallback *callback)
86{
87    for (InsertionRecord *rec = head; rec != NULL; rec = rec->next) {
88        if (callback->applyInsertion(rec->position, rec->count, rec->glyphs)) {
89            return TRUE;
90        }
91    }
92
93    return FALSE;
94}
95
96U_NAMESPACE_END
97