unit attributes; {$M+} { For some kinds of text attributes, multiple attributes can apply to one character. Some kinds of attributes cancel override each other. = Kinds of Attributes = Font size Font set Foreground color underline doubleunderline? strike-through italic bold(ness) set tab stop box drawing start table start table row start table column end table column end table row end table (Insert image) = Representation = attribute_definition := pair(attribute_type_and_kind, attribute_parameters) attribute_reference := ??? backreference (as in " attribute definitions back", possibly encoded in as few bits as possible?) or something more sophisticated? } interface { TODO attributes: singleton } uses symbols; type TAttribute = class private fRelativeTo : TAttribute; protected constructor Create; function OverridesP(aAttribute : TAttribute) : Boolean; virtual; published property RelativeTo : TAttribute read fRelativeTo write fRelativeTo; // if any. end; TValueAttribute = class(TAttribute) private fValue : Integer; published constructor Create(aRelativeTo : TAttribute; aValue : Integer); property Value : Integer read fValue write fValue; end; TForegroundColorAttribute = class(TAttribute) private fColor : TSymbol; published constructor Create(aValue : TSymbol); property Color : TSymbol read fColor write fColor; end; TUnderlinenessAttribute = class(TValueAttribute) end; TBoldnessAttribute = class(TValueAttribute) end; {TableRowAttribute { TODO how to represent relative attribute changes _and_ absolute attribute changes cleanly? The "RelativeTo" thingie kinda looks wrong. } implementation var gDefaultAttributes : array of TAttribute; { TAttribute } constructor TAttribute.Create; begin end; function TAttribute.OverridesP(aAttribute : TAttribute) : Boolean; var vAttribute : TAttribute; begin Result := (aAttribute <> Self) and (TypeOf(aAttribute) = TypeOf(Self)); if Result then begin vAttribute := fRelativeTo; while Assigned(vAttribute) do begin // TODO endless loop check. if vAttribute = aAttribute then begin Result := False; // Result := ... and (not (aAttribute in fRelativeTo chain)); Break; end; vAttribute := vAttribute.RelativeTo; end; end; end; { TValueAttribute } constructor TValueAttribute.Create(aRelativeTo : TAttribute; aValue : Integer); begin inherited Create; fRelativeTo := aRelativeTo; fValue := aValue; end; { TForegroundColorAttribute } constructor TForegroundColorAttribute.Create(aValue : TSymbol); begin inherited Create; fColor := aValue; end; initialization SetLength(gDefaultAttributes, 3); gDefaultAttributes[0] := TForegroundColorAttribute.Create(TSymbol.Create('black')); gDefaultAttributes[1] := TUnderlinenessAttribute.Create(nil, 0); gDefaultAttributes[2] := TBoldnessAttribute.Create(nil, 0); end.