Finished filling in exp_attrdll.c. I think this will stay.

This commit is contained in:
Pietro Gagliardi 2016-12-22 14:22:01 -05:00
parent 0078615662
commit ab8aa9266e
1 changed files with 111 additions and 7 deletions

View File

@ -156,19 +156,23 @@ static struct attr *attrDropRange(struct attrlist *alist, struct attr *a, size_t
return a->next;
// just outright delete the attribute?
if (a->start == start && a->end == end)
// the inequalities handle attributes entirely inside the range
// if both are equal, the attribute's range is equal to the range
if (a->start >= start && a->end <= end)
return attrDelete(alist, a);
// only chop off the start or end?
if (a->start == start) { // chop off the end
a->end = end;
return a->next;
}
if (a->end == end) { // chop off the start
a->start = start;
if (a->start == start) { // chop off the start
// we are dropping the left half, so set a->start and unlink
a->start = end;
*tail = a;
return attrUnlink(attr, a);
}
if (a->end == end) { // chop off the end
// we are dropping the right half, so just set a->end
a->end = start;
return a->next;
}
// we'll need to split the attribute into two
b = uiNew(struct attr);
@ -226,6 +230,61 @@ static struct attr *attrSplitAt(struct attrlist *alist, struct attr *a, size_t a
return b;
}
// attrDeleteRange() removes attributes while deleting characters.
//
// If the attribute does not include the deleted range, then nothing is done (though the start and end are adjusted as necessary).
//
// If the attribute needs to be deleted, it is deleted.
//
// Otherwise, the attribute only needs the start or end deleted, and it is adjusted.
//
// In all cases, the return value is the next attribute to look at in a forward sequential loop.
// TODO rewrite this comment
static struct attr *attrDeleteRange(struct attrlist *alist, struct attr *a, size_t start, size_t end)
{
size_t ostart, oend;
size_t count;
ostart = start;
oend = end;
count = oend - ostart;
if (!attrRangeIntersect(a, &start, &end)) {
// out of range
// adjust if necessary
if (a->start >= ostart)
a->start -= count;
if (a->end >= oend)
a->end -= count;
return a->next;
}
// just outright delete the attribute?
// the inequalities handle attributes entirely inside the range
// if both are equal, the attribute's range is equal to the range
if (a->start >= start && a->end <= end)
return attrDelete(alist, a);
// only chop off the start or end?
if (a->start == start) { // chop off the start
// if we weren't adjusting positions this would just be setting a->start to end
// but since this is deleting from the start, we need to adjust both by count
a->start = end - count;
a->end -= count;
return a->next;
}
if (a->end == end) { // chop off the end
// a->start is already good
a->end = start;
return a->next;
}
// in this case, the deleted range is inside the attribute
// we can clear it by just removing count from a->end
a->end -= count;
return a->next;
}
void attrlistInsertAt(struct attrlist *alist, uiAttribute type, uintptr_t val, size_t start, size_t end)
{
struct attr *a;
@ -464,10 +523,55 @@ void attrlistRemoveAttribute(struct attrlist *alist, uiAttribute type, size_t st
}
}
// TODO merge this with the above
void attrlistRemoveAttributes(struct attrlist *alist, size_t start, size_t end)
{
struct attr *a;
struct attr *tails = NULL; // see attrlistInsertCharactersUnattributed() above
struct attr *tailsAt = NULL;
a = alist->start;
while (a != NULL) {
size_t lstart, lend;
// this defines where to re-attach the tails
// (all the tails will have their start at end, so we can just insert them all before tailsAt)
if (a->start >= end) {
tailsAt = a;
// and at this point we're done, so
break;
}
lstart = start;
lend = end;
if (!attrRangeIntersect(a, &lstart, &lend))
goto next;
a = attrDropRange(alist, a, start, end, &tail);
if (tail != NULL) {
tail->next = tails;
tails = tail;
}
continue;
next:
a = a->next;
}
while (tails != NULL) {
struct attr *next;
// make all the links NULL before insertion, just to be safe
next = tails->next;
tails->next = NULL;
attrInsertBefore(alist, tails, a);
tails = next;
}
}
void attrlistRemoveCharacters(struct attrlist *alist, size_t start, size_t end)
{
struct attr *a;
a = alist->first;
while (a != NULL)
a = attrDeleteRange(alist, a, start, end);
}