Changed the representation of an attribute type/value pair to allow more type safety and expressability.
This commit is contained in:
parent
1c1b16a206
commit
261dd4851a
|
@ -12,8 +12,7 @@ The linked list is not a ring; alist->fist->prev == NULL and alist->last->next =
|
|||
*/
|
||||
|
||||
struct attr {
|
||||
uiAttribute type;
|
||||
uintptr_t val;
|
||||
uiAttributeSpec spec;
|
||||
size_t start;
|
||||
size_t end;
|
||||
struct attr *prev;
|
||||
|
@ -178,8 +177,7 @@ static struct attr *attrDropRange(struct attrlist *alist, struct attr *a, size_t
|
|||
|
||||
// we'll need to split the attribute into two
|
||||
b = uiNew(struct attr);
|
||||
b->type = a->type;
|
||||
b->val = a->val;
|
||||
b->spec = a->spec;
|
||||
b->start = end;
|
||||
b->end = a->end;
|
||||
*tail = b;
|
||||
|
@ -223,8 +221,7 @@ static struct attr *attrSplitAt(struct attrlist *alist, struct attr *a, size_t a
|
|||
return NULL;
|
||||
|
||||
b = uiNew(struct attr);
|
||||
b->type = a->type;
|
||||
b->val = a->val;
|
||||
b->spec = a->spec;
|
||||
b->start = at;
|
||||
b->end = a->end;
|
||||
|
||||
|
@ -287,7 +284,24 @@ static struct attr *attrDeleteRange(struct attrlist *alist, struct attr *a, size
|
|||
return a->next;
|
||||
}
|
||||
|
||||
void attrlistInsertAttribute(struct attrlist *alist, uiAttribute type, uintptr_t val, size_t start, size_t end)
|
||||
static int specsIdentical(struct attr *attr, uiAttributeSpec *spec)
|
||||
{
|
||||
if (attr->spec.Type != spec->Type)
|
||||
return 0;
|
||||
switch (attr->spec.Type) {
|
||||
case uiAttributeFamily:
|
||||
// TODO should we start copying these strings?
|
||||
return strcmp((char *) (attr->spec.Value), (char *) (spec->Value)) == 0;
|
||||
case uiAttributeSize:
|
||||
// TODO use a closest match?
|
||||
return attr->spec.Double == spec->Double;
|
||||
// TODO
|
||||
}
|
||||
// handles the rest
|
||||
return attr->spec.Value == spec->Value;
|
||||
}
|
||||
|
||||
void attrlistInsertAttribute(struct attrlist *alist, uiAttributeSpec *spec, size_t start, size_t end)
|
||||
{
|
||||
struct attr *a;
|
||||
struct attr *before;
|
||||
|
@ -309,7 +323,7 @@ void attrlistInsertAttribute(struct attrlist *alist, uiAttribute type, uintptr_t
|
|||
goto next;
|
||||
|
||||
// should we split this?
|
||||
if (before->type != type)
|
||||
if (before->spec.Type != spec->Type)
|
||||
goto next;
|
||||
lstart = start;
|
||||
lend = end;
|
||||
|
@ -317,10 +331,8 @@ void attrlistInsertAttribute(struct attrlist *alist, uiAttribute type, uintptr_t
|
|||
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?
|
||||
// TODO will this cause problems with fonts?
|
||||
// TODO will this reduce fragmentation if we first add from 0 to 2 and then from 2 to 4? or do we have to do that separately?
|
||||
if (before->val == val) {
|
||||
if (specsIdentical(before, spec)) {
|
||||
attrGrow(alist, before, start, end);
|
||||
return;
|
||||
}
|
||||
|
@ -335,8 +347,7 @@ void attrlistInsertAttribute(struct attrlist *alist, uiAttribute type, uintptr_t
|
|||
|
||||
// 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->spec = *spec;
|
||||
a->start = start;
|
||||
a->end = end;
|
||||
attrInsertBefore(alist, a, before);
|
||||
|
@ -498,7 +509,7 @@ void attrlistRemoveAttribute(struct attrlist *alist, uiAttribute type, size_t st
|
|||
// and at this point we're done, so
|
||||
break;
|
||||
}
|
||||
if (a->type != type)
|
||||
if (a->spec.Type != type)
|
||||
goto next;
|
||||
lstart = start;
|
||||
lend = end;
|
||||
|
@ -587,7 +598,7 @@ void attrlistForEach(struct attrlist *alist, uiAttributedString *s, uiAttributed
|
|||
for (a = alist->first; a != NULL; a = a->next)
|
||||
// TODO document this
|
||||
// TODO should this be return 0 to break?
|
||||
if ((*f)(s, a->type, a->val, a->start, a->end, data))
|
||||
if ((*f)(s, &(a->spec), a->start, a->end, data))
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -297,9 +297,9 @@ size_t uiAttributedStringGraphemeToByteIndex(uiAttributedString *s, size_t pos)
|
|||
return pos;
|
||||
}
|
||||
|
||||
void uiAttributedStringSetAttribute(uiAttributedString *s, uiAttribute type, uintptr_t value, size_t start, size_t end)
|
||||
void uiAttributedStringSetAttribute(uiAttributedString *s, uiAttributeSpec *spec, size_t start, size_t end)
|
||||
{
|
||||
attrlistInsertAttribute(s->attrs, type, value, start, end);
|
||||
attrlistInsertAttribute(s->attrs, spec, start, end);
|
||||
}
|
||||
|
||||
// TODO introduce an iterator?
|
||||
|
|
|
@ -78,7 +78,7 @@ extern size_t *attrstrCopyUTF16ToUTF8(uiAttributedString *s, size_t *n);
|
|||
|
||||
// attrlist.c
|
||||
struct attrlist;
|
||||
extern void attrlistInsertAttribute(struct attrlist *alist, uiAttribute type, uintptr_t val, size_t start, size_t end);
|
||||
extern void attrlistInsertAttribute(struct attrlist *alist, uiAttributeSpec *spec, size_t start, size_t end);
|
||||
extern void attrlistInsertCharactersUnattributed(struct attrlist *alist, size_t start, size_t count);
|
||||
extern void attrlistInsertCharactersExtendingAttributes(struct attrlist *alist, size_t start, size_t count);
|
||||
extern void attrlistRemoveAttribute(struct attrlist *alist, uiAttribute type, size_t start, size_t end);
|
||||
|
|
|
@ -40,41 +40,41 @@ static void adjustFontInRange(struct foreachParams *p, size_t start, size_t end,
|
|||
}
|
||||
}
|
||||
|
||||
static int processAttribute(uiAttributedString *s, uiAttribute type, uintptr_t value, size_t start, size_t end, void *data)
|
||||
static int processAttribute(uiAttributedString *s, uiAttributeSpec *spec, size_t start, size_t end, void *data)
|
||||
{
|
||||
struct foreachParams *p = (struct foreachParams *) data;
|
||||
|
||||
start = attrstrUTF8ToUTF16(s, start);
|
||||
end = attrstrUTF8ToUTF16(s, end);
|
||||
switch (type) {
|
||||
switch (spec->Type) {
|
||||
case uiAttributeFamily:
|
||||
ensureFontInRange(p, start, end);
|
||||
adjustFontInRange(p, start, end, ^(uiDrawFontDescriptor *desc) {
|
||||
desc->Family = (char *) value;
|
||||
desc->Family = (char *) (spec->Value);
|
||||
});
|
||||
break;
|
||||
case uiAttributeSize:
|
||||
ensureFontInRange(p, start, end);
|
||||
adjustFontInRange(p, start, end, ^(uiDrawFontDescriptor *desc) {
|
||||
desc->Size = *((double *) value);
|
||||
desc->Size = spec->Double;
|
||||
});
|
||||
break;
|
||||
case uiAttributeWeight:
|
||||
ensureFontInRange(p, start, end);
|
||||
adjustFontInRange(p, start, end, ^(uiDrawFontDescriptor *desc) {
|
||||
desc->Weight = (uiDrawTextWeight) value;
|
||||
desc->Weight = (uiDrawTextWeight) (spec->Value);
|
||||
});
|
||||
break;
|
||||
case uiAttributeItalic:
|
||||
ensureFontInRange(p, start, end);
|
||||
adjustFontInRange(p, start, end, ^(uiDrawFontDescriptor *desc) {
|
||||
desc->Italic = (uiDrawTextItalic) value;
|
||||
desc->Italic = (uiDrawTextItalic) (spec->Value);
|
||||
});
|
||||
break;
|
||||
case uiAttributeStretch:
|
||||
ensureFontInRange(p, start, end);
|
||||
adjustFontInRange(p, start, end, ^(uiDrawFontDescriptor *desc) {
|
||||
desc->Stretch = (uiDrawTextStretch) value;
|
||||
desc->Stretch = (uiDrawTextStretch) (spec->Value);
|
||||
});
|
||||
break;
|
||||
// TODO
|
||||
|
|
|
@ -5,6 +5,7 @@ static uiAttributedString *attrstr;
|
|||
|
||||
static void setupAttributedString(void)
|
||||
{
|
||||
uiAttributeSpec spec;
|
||||
size_t start, end;
|
||||
const char *next;
|
||||
|
||||
|
@ -14,22 +15,20 @@ static void setupAttributedString(void)
|
|||
start = uiAttributedStringLen(attrstr);
|
||||
end = start + strlen(next);
|
||||
uiAttributedStringAppendUnattributed(attrstr, next);
|
||||
uiAttributedStringSetAttribute(attrstr,
|
||||
uiAttributeFamily,
|
||||
(uintptr_t) "Courier New",
|
||||
start, end);
|
||||
spec.Type = uiAttributeFamily;
|
||||
spec.Value = (uintptr_t) "Courier New";
|
||||
uiAttributedStringSetAttribute(attrstr, &spec, start, end);
|
||||
|
||||
uiAttributedStringAppendUnattributed(attrstr, ", ");
|
||||
|
||||
next = "multiple sizes";
|
||||
static double eighteen = 18;
|
||||
start = uiAttributedStringLen(attrstr);
|
||||
end = start + strlen(next);
|
||||
uiAttributedStringAppendUnattributed(attrstr, next);
|
||||
spec.Type = uiAttributeSize;
|
||||
spec.Double = 18;
|
||||
uiAttributedStringSetAttribute(attrstr,
|
||||
uiAttributeSize,
|
||||
(uintptr_t) (&eighteen),
|
||||
start, end);
|
||||
&spec, start, end);
|
||||
|
||||
uiAttributedStringAppendUnattributed(attrstr, ", ");
|
||||
|
||||
|
@ -37,10 +36,9 @@ static void setupAttributedString(void)
|
|||
start = uiAttributedStringLen(attrstr);
|
||||
end = start + strlen(next);
|
||||
uiAttributedStringAppendUnattributed(attrstr, next);
|
||||
uiAttributedStringSetAttribute(attrstr,
|
||||
uiAttributeWeight,
|
||||
(uintptr_t) uiDrawTextWeightBold,
|
||||
start, end);
|
||||
spec.Type = uiAttributeWeight;
|
||||
spec.Value = (uintptr_t) uiDrawTextWeightBold;
|
||||
uiAttributedStringSetAttribute(attrstr, &spec, start, end);
|
||||
|
||||
uiAttributedStringAppendUnattributed(attrstr, ", ");
|
||||
|
||||
|
@ -48,10 +46,9 @@ static void setupAttributedString(void)
|
|||
start = uiAttributedStringLen(attrstr);
|
||||
end = start + strlen(next);
|
||||
uiAttributedStringAppendUnattributed(attrstr, next);
|
||||
uiAttributedStringSetAttribute(attrstr,
|
||||
uiAttributeItalic,
|
||||
(uintptr_t) uiDrawTextItalicItalic,
|
||||
start, end);
|
||||
spec.Type = uiAttributeItalic;
|
||||
spec.Value = (uintptr_t) uiDrawTextItalicItalic;
|
||||
uiAttributedStringSetAttribute(attrstr, &spec, start, end);
|
||||
|
||||
uiAttributedStringAppendUnattributed(attrstr, ", ");
|
||||
|
||||
|
@ -59,10 +56,9 @@ static void setupAttributedString(void)
|
|||
start = uiAttributedStringLen(attrstr);
|
||||
end = start + strlen(next);
|
||||
uiAttributedStringAppendUnattributed(attrstr, next);
|
||||
uiAttributedStringSetAttribute(attrstr,
|
||||
uiAttributeStretch,
|
||||
(uintptr_t) uiDrawTextStretchCondensed,
|
||||
start, end);
|
||||
spec.Type = uiAttributeStretch;
|
||||
spec.Value = (uintptr_t) uiDrawTextStretchCondensed;
|
||||
uiAttributedStringSetAttribute(attrstr, &spec, start, end);
|
||||
|
||||
uiAttributedStringAppendUnattributed(attrstr, ", ");
|
||||
|
||||
|
|
11
ui_attrstr.h
11
ui_attrstr.h
|
@ -1,4 +1,5 @@
|
|||
typedef struct uiAttributedString uiAttributedString;
|
||||
typedef struct uiAttributeSpec uiAttributeSpec;
|
||||
|
||||
_UI_ENUM(uiAttribute) {
|
||||
// TODO once we allow loading fonts in memory we can't use just one pointer anymore
|
||||
|
@ -13,7 +14,13 @@ _UI_ENUM(uiAttribute) {
|
|||
// TODO uiAttributeCustom,
|
||||
};
|
||||
|
||||
typedef int (*uiAttributedStringForEachAttributeFunc)(uiAttributedString *s, uiAttribute type, uintptr_t value, size_t start, size_t end, void *data);
|
||||
struct uiAttributeSpec {
|
||||
uiAttribute Type;
|
||||
uintptr_t Value;
|
||||
double Double;
|
||||
};
|
||||
|
||||
typedef int (*uiAttributedStringForEachAttributeFunc)(uiAttributedString *s, uiAttributeSpec *spec, size_t start, size_t end, void *data);
|
||||
|
||||
// @role uiAttributedString constructor
|
||||
// uiNewAttributedString() creates a new uiAttributedString from
|
||||
|
@ -39,7 +46,7 @@ _UI_EXTERN void uiAttributedStringDelete(uiAttributedString *s, size_t start, si
|
|||
_UI_EXTERN size_t uiAttributedStringNumGraphemes(uiAttributedString *s);
|
||||
_UI_EXTERN size_t uiAttributedStringByteIndexToGrapheme(uiAttributedString *s, size_t pos);
|
||||
_UI_EXTERN size_t uiAttributedStringGraphemeToByteIndex(uiAttributedString *s, size_t pos);
|
||||
_UI_EXTERN void uiAttributedStringSetAttribute(uiAttributedString *s, uiAttribute type, uintptr_t value, size_t start, size_t end);
|
||||
_UI_EXTERN void uiAttributedStringSetAttribute(uiAttributedString *s, uiAttributeSpec *spec, size_t start, size_t end);
|
||||
_UI_EXTERN void uiAttributedStringForEachAttribute(uiAttributedString *s, uiAttributedStringForEachAttributeFunc f, void *data);
|
||||
|
||||
typedef struct uiDrawFontDescriptor uiDrawFontDescriptor;
|
||||
|
|
Loading…
Reference in New Issue