anchor.diff:        begin
           i := StrToInt(Copy(aFieldName, i + LENGTH_FLD_UPRIGHT, 999));
           Result := GetUpright(i - 1);
  +      end
  +      else
  +      begin
  +        i := Pos (FLD_ATTRIBUTE, aFieldName);
  +        if i > 0 then
  +        begin
  +          i := StrToInt(Copy(aFieldName, i + LENGTH_FLD_ATTRIBUTE, 999));
  +          Result := FEvent.GetAttribute(i - 1).AsVariant;
  +        end
  +        else
  +        begin
  +          i := Pos(FLD_HIGHLIGHT, aFieldName);
  +          if i > 0 then
  +          begin
  +            i := StrToInt(Copy(aFieldName, i + LENGTH_FLD_HIGHLIGHT, 999));
  +            Result := TmUprightHighlightTypeToVariant(FHighlights[i - 1]);
  +          end
  +          else
  +          begin
  +            i := Pos(FLD_REMAINING, aFieldName);
  +            if i > 0 then
  +            begin
  +              i := StrToInt(Copy(aFieldName, i + LENGTH_FLD_REMAINING, 999));
  +              Result := FRemainings[i - 1].AsVariant;
  +            end
  +            else
  +            begin
  +              i := Pos(FLD_LIMIT, aFieldName);
  +              if i > 0 then
  +              begin
  +                i := StrToInt(Copy(aFieldName, i + LENGTH_FLD_LIMIT, 999));
  +                Result := FLimits[i - 1].AsVariant;
  +              end;
  +            end;
  +          end;
  +        end;
         end;
       end;
     end;
   end;
   
  -procedure TmUprightDatum.SetPropertyByFieldName(const aFieldName: String; const aValue: Variant);
  -begin
  -  // none
  -end;
   
   function TmUprightDatum.AsObject: TObject;
   begin
     Result := Self;
   end;
   
  -class procedure TmUprightDatum.FillVirtualFieldDefs(aFieldDefs: TmVirtualFieldDefs; aPrefix: String; const aValuesCount : integer = 1);
  +class procedure TmUprightDatum.FillVirtualFieldDefs(aFieldDefs: TmVirtualFieldDefs; aPrefix: String; const aValuesCount : integer = 1; const aAttributesCount : integer = 4);
   var
     i : integer;
   begin
  
positive.code: begin
    aFieldsForLookup.Add(TmUprightDatum.FLD_POSITION);
    aFieldsForLookup.Add(TmUprightDatum.FLD_DATE);
    aFieldsForLookup.Add(TmUprightDatum.FLD_UPRIGHT);
  end;
  
  end.
  
negative.code:   i, k : integer;
    tmpEvent : TmUprightEvent;
    tmpDatum : TmUprightDatum;
    currentLimitIndex : array[0..MAX_NUM_OF_VALUES-1] of integer;
    lastValues : array [0..MAX_NUM_OF_VALUES -1] of double;
    tmpLimits : TFPList;
  
  begin
    FDataList.Clear;
    FGarbage.Clear;
  
    tmpLimits := TFPList.Create;
    try
  
      for i := 0 to FEventsList.Count - 1 do
      begin
        tmpEvent:= TmUprightEvent(FEventsList.Items[i]);
        if tmpEvent.EventType = etuValue then
        begin
          tmpDatum := TmUprightDatum.Create;
          tmpDatum.FEvent := tmpEvent;
          FDataList.Add(tmpDatum);
          FGarbage.Add(tmpDatum);
        end
        else
        begin
          tmpLimits.Add(tmpEvent);
        end;
      end;
  
      if aDoSort then
      begin
        MergeSort(FDataList, OnCompareData);
        MergeSort(tmpLimits, OnCompareEvents);
      end;
  
  
  
      for i := 0 to MAX_NUM_OF_VALUES -1 do
      begin
        lastValues[i] := 0;
        currentLimitIndex[i]:= -1;
      end;
  
      for i := 0 to FDataList.Count -1 do
      begin
        tmpDatum:= TmUprightDatum(FDataList.Items[i]);
  
        for k := 0 to MAX_NUM_OF_VALUES -1 do
        begin
          if (tmpLimits.Count > currentLimitIndex[k] + 1) then
          begin
            tmpEvent := TmUprightEvent(tmpLimits.Items[currentLimitIndex[k] + 1]);
            while Assigned(tmpEvent) and (tmpEvent.GetValue(k).NotNull) and DoubleIsLessThan(tmpEvent.EventDate, tmpDatum.FEvent.EventDate) do
            begin
              inc(currentLimitIndex[k]);
              if (tmpLimits.Count > currentLimitIndex[k] + 1) then
                tmpEvent := TmUprightEvent(tmpLimits.Items[currentLimitIndex[k] + 1])
              else
                tmpEvent := nil;
            end;
          end;
        end;
        tmpDatum.FKey.FPosition := i + 1;
        for k := 0 to MAX_NUM_OF_VALUES - 1 do
        begin
          tmpDatum.SetUpright(k, lastValues[k] + tmpDatum.FEvent.GetValue(k).AsFloat);
          lastValues[k] := tmpDatum.GetUpright(k);
        end;
  
        for k := 0 to MAX_NUM_OF_VALUES - 1 do
        begin
          if currentLimitIndex[k] >= 0 then
          begin
            tmpEvent := TmUprightEvent(tmpLimits.Items[currentLimitIndex[k]]);
            tmpDatum.FLimits[k].Assign(tmpEvent.GetValue(k));
            tmpDatum.FRemainings[k].Value := tmpDatum.FLimits[k].AsFloat + tmpDatum.GetUpright(k);
          end;
        end;
      end;
      Self.CalculateHighlights;
  
    finally
      tmpLimits.Free;
    end;
  end;
  
  function TmUpright.Count: integer;
  