More work. Much clearer now... not yet complete though.
This commit is contained in:
parent
2f449887d8
commit
4c99899a1d
|
@ -53,10 +53,36 @@ static void linkInsertBefore(struct attrlist *alist, struct attr *what, struct a
|
|||
a->prev->next = a;
|
||||
}
|
||||
|
||||
static int attrHasPos(struct attr *a, size_t pos)
|
||||
{
|
||||
if (pos < a->start)
|
||||
return 0;
|
||||
return pos < a->end;
|
||||
}
|
||||
|
||||
// returns 1 if there was an intersection and 0 otherwise
|
||||
static int attrRangeIntersect(struct attr *a, size_t *start, size_t *end)
|
||||
{
|
||||
// is the range outside a entirely?
|
||||
if (*start >= a->end)
|
||||
return 0;
|
||||
if (*end < a->start)
|
||||
return 0;
|
||||
|
||||
// okay, so there is an overlap
|
||||
// compute the intersection
|
||||
if (*start < a->start)
|
||||
*start = a->start;
|
||||
if (*end > a->end)
|
||||
*end = a->end;
|
||||
return 1;
|
||||
}
|
||||
|
||||
#if 0
|
||||
void attrlistInsertAt(struct attrlist *alist, uiAttribute type, uintptr_t val, size_t start, size_t end)
|
||||
{
|
||||
struct attr *a;
|
||||
struct attr *after;
|
||||
struct attr *before;
|
||||
|
||||
a = uiNew(struct attr);
|
||||
a->type = type;
|
||||
|
@ -65,10 +91,81 @@ void attrlistInsertAt(struct attrlist *alist, uiAttribute type, uintptr_t val, s
|
|||
a->end = end;
|
||||
|
||||
// place a before the first element that starts after a does
|
||||
for (before = alist->first; before != NULL; before = before->next)
|
||||
for (before = alist->first; before != NULL; before = before->next) {
|
||||
size_t lstart, lend;
|
||||
|
||||
if (before->start > a->start)
|
||||
break;
|
||||
// TODO this does not handle cases where the attribute overwrites an existing attribute
|
||||
// if this attribute overrides another, we have to split
|
||||
lstart = start;
|
||||
lend = end;
|
||||
if (!attrRangeIntersect(before, &lstart, &lend))
|
||||
continue;
|
||||
if (before->type != type)
|
||||
continue;
|
||||
if (before->val == val)
|
||||
continue;
|
||||
// TODO now split around start/end and drop the overlap
|
||||
}
|
||||
linkInsertBefore(alist, a, before);
|
||||
// TODO see if adding this attribute leads to a fragmented contiguous run
|
||||
}
|
||||
#endif
|
||||
|
||||
void attrlistInsertAt(struct attrlist *alist, uiAttribute type, uintptr_t val, size_t start, size_t end)
|
||||
{
|
||||
struct attr *a;
|
||||
struct attr *before;
|
||||
struct attr *tail = NULL;
|
||||
|
||||
// first, figure out where in the list this should go
|
||||
// in addition, if this attribute overrides one that already exists, split that one apart so this one can take over
|
||||
before = alist->first;
|
||||
while (before != NULL) {
|
||||
size_t lstart, lend;
|
||||
|
||||
// once we get to the first point after start, we know where to insert
|
||||
if (before->start > start)
|
||||
break;
|
||||
|
||||
// if we have already split a prior instance of this attribute, don't bother doing it again
|
||||
if (tail != NULL)
|
||||
goto next;
|
||||
|
||||
// should we split this?
|
||||
if (before->type != type)
|
||||
goto next;
|
||||
lstart = start;
|
||||
lend = end;
|
||||
if (!attrRangeIntersects(before, &lstart, &lend))
|
||||
goto next;
|
||||
|
||||
// okay so this might conflict; if the val is the same as the one we want, we need to expand the existing attribute, not fragment anything
|
||||
// TODO this might cause problems with system specific attributes, if we support those; maybe also user-specific?
|
||||
if (before->val == val) {
|
||||
// TODO
|
||||
}
|
||||
// okay the values are different; we need to split apart
|
||||
// TODO
|
||||
|
||||
next:
|
||||
before = before->next;
|
||||
}
|
||||
|
||||
// if we got here, we know we have to add the attribute before before
|
||||
a = uiNew(struct attr);
|
||||
a->type = type;
|
||||
a->val = val;
|
||||
a->start = start;
|
||||
a->end = end;
|
||||
linkInsertBefore(alist, a, before);
|
||||
|
||||
// and finally, if we split, insert the remainder
|
||||
if (tail == NULL)
|
||||
return;
|
||||
// note we start at before; it won't be inserted before that by the sheer nature of how the code above works
|
||||
for (; before != NULL; before = before->next)
|
||||
if (before->start > tail->start)
|
||||
break;
|
||||
linkInsertBefore(alist, tail, before);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue