 FastReport 2.21 fixes list

Description: This ile consists of fixes to
          FastReport 2.21.
          Fixed version will be named
          FreeReport. More recent fixes are first in this file

Special symbols:
          >ID   xxx    - fix has identification number xx
          >APPL x.xx.x - fix is applied in x.xx.x version

          >VER x.xx <date> - version x.xx is created in <date> 
                             dates in russian format dd.mm.yy

>VER 2.21.8  07.06.00
-----------------------------------------------------------------------------
ID:43
State: Applied 2.21.8
Auth: MVoicu
Mail: 
Type: -
Desc: Huge memory leak
Unit: fr_Class
Func: TfrMemoView.ExpandVariables
Was:  
    s := Memo1.GetText + s;
    Memo1.SetText(PChar(S));
Fix:
  var 
    i: Integer;
    s: String;
    P: PChar; // added
    ---
    P := Memo1.GetText;      //mv because GetText is a StrNew('string') function
    s := P + s;              //mv
    StrDispose(P);           //mv without this P remain allocated !!!!
    Memo1.SetText(PChar(S));
-----------------------------------------------------------------------------
ID:42
State: Applied 2.21.8
Auth: Magomed G. Abdurakhmanov
Mail: maq@mail.ru
Type: -
Desc: This fix removes unnamed DataSet components (created at the runtime)
      from combo box in Variable editor.

Unit: fr_ev_ed.pas
Fun: TEvForm.FillValCombo.EnumDataSets
Was:
procedure EnumDataSets(f:TComponent);
var i: Integer;
    c: TComponent;
begin
  for i := 0 to f.ComponentCount-1 do
  begin
        c := f.Components[i];
        if c is TDataSet then
          if f = Doc.Owner then
                s.Add(c.Name) else
                s.Add(f.Name + '.' + c.Name);
  end;
end;

Fix:
procedure EnumDataSets(f:TComponent);
var i: Integer;
    c: TComponent;
begin
  for i := 0 to f.ComponentCount-1 do
  begin
        c := f.Components[i];
        if (c is TDataSet) and (Length(c.Name)<>0) then
          if f = Doc.Owner then
                s.Add(c.Name) else
                s.Add(f.Name + '.' + c.Name);
  end;
end;
-----------------------------------------------------------------------------
ID:41
State:Applied 2.21.8
Auth: Magomed G. Abdurakhmanov
Mail: maq@mail.ru
Type: -
Desc: Using variables simply referencing to fields in TDataSet sometimes
      caused access violation. For example when used in detail band and
      dataset of this band is a query depending on master detail by input
      parameters. For example TQuery which has DataSource setted on master's
      source.
      ---------------------------------------------------------------------
      Here is russian translation
            fields  TDataSet'
         access violation.       
      detail band.  dataset  detail band'a    
          master dataset'. .. TQuery   
        DataSource   . Access violation 
              scrolling'e 
      master  - ..   ,   TfrValue.DField 
          TField   .
             DVield ,   
      Field     .

Unit: fr_class.pas
----------- 
Was:
  TfrValue = class
  public
    Typ: TfrValueType;
    OtherKind: Integer;   // for vtOther - typ, for vtDBField - format
    DataSet: String;      // for vtDBField
    Field: String;        // here is an expression for vtOther
    DSet: TDataSet;
    DField: TField;
  end;

Fix:
  TfrValue = class
  public
    Typ: TfrValueType;
    OtherKind: Integer;   // for vtOther - typ, for vtDBField - format
    DataSet: String;      // for vtDBField
    Field: String;        // here is an expression for vtOther
    DSet: TDataSet;
    //DField: TField; <-- fixed. maq@mail.ru
  end;
-----------
Was:
procedure TfrReport.InternalOnEnterRect(Memo:TStringList; View:TfrView);
var Value: TfrValue;
    s: String;
    i: Integer;
    DataSet: TDataSet;
    Field: TField;
begin
  if HasBlobs then
    if Memo.Count > 0 then
    begin
      s := Memo[0];
      i := Length(s);
      if (i > 2) and (s[1] = '[') then
      begin
        while (i > 0) and (s[i] <> ']') do Dec(i);
        s := Copy(s, 2, i-2);
        DataSet := nil; Field := nil;
        Value := Values.FindVariable(s);
        if Value = nil then
        begin
          DataSet := GetDefaultDataset;
          frGetDatasetAndField(s, DataSet, Field);
        end
        else if Value.Typ = vtDBField then
          Field := Value.DField;
        if (Field <> nil) and (Field.DataType in [ftBlob..ftTypedBinary]) then
          View.GetBlob(Field);
      end;
    end;
  if Assigned(FOnEnterRect) then FOnEnterRect(Memo, View);
end;

Fix:
procedure TfrReport.InternalOnEnterRect(Memo:TStringList; View:TfrView);
var Value: TfrValue;
        s: String;
        i: Integer;
        DataSet: TDataSet;
        Field: TField;
begin
  if HasBlobs then
        if Memo.Count > 0 then
        begin
          s := Memo[0];
          i := Length(s);
          if (i > 2) and (s[1] = '[') then
          begin
                while (i > 0) and (s[i] <> ']') do Dec(i);
                s := Copy(s, 2, i-2);
                DataSet := nil; Field := nil;
                Value := Values.FindVariable(s);
                if Value = nil then
                begin
                  DataSet := GetDefaultDataset;
                  frGetDatasetAndField(s, DataSet, Field);
                end
                else if Value.Typ = vtDBField then
                  Field := Value.DSet.FindField(Value.Field); <-- fixed. maq@mail.ru
                if (Field <> nil) and (Field.DataType in [ftBlob..ftTypedBinary]) then
                  View.GetBlob(Field);
          end;
        end;
  if Assigned(FOnEnterRect) then FOnEnterRect(Memo, View);
end;
----------- 
Was:
procedure TfrReport.GetVariableValue(const s:String; var v:Variant);
var Value: TfrValue;
        DataSet: TDataSet;
        Field: TField;
begin
  v := Null;
  if Assigned(FOnGetValue) then FOnGetValue(s, v);
  if v = Null then
  begin
        Value := Values.FindVariable(s);
        if Value <> nil then
          with Value do
          case Typ of
                vtNotAssigned:
                  v := '';
                vtDBField:
                //begin fix 2.21.1
                  if Assigned(DField) then
                  begin
                    if DField.FieldKind = fkCalculated Then v := DField.Text
                    Else v := DField.AsVariant;
                  end
                  else
                    v := ' ';
                //end fix 2.21.1
                vtOther:
                  if OtherKind = 1 then
                        v := Parser.Calc(Field) else
                        v := Parser.Calc(frSpecFuncs[OtherKind]);
          end
        else
        begin
          DataSet := GetDefaultDataSet;
          frGetDataSetAndField(s, DataSet, Field);
          if Field <> nil then
                v := Field.AsVariant
          else if s = 'VALUE' then
                v := CurValue
          else if s = frSpecFuncs[0] then
                v := PageNo + 1
          else if s = frSpecFuncs[2] then
                v := CurDate
          else if s = frSpecFuncs[3] then
                v := CurTime
          else if s = frSpecFuncs[4] then
                v := CurBand.Positions[psLocal]
          else if s = frSpecFuncs[5] then
                v := CurBand.Positions[psGlobal]
          else if s = frSpecFuncs[6] then
                v := CurPage.ColPos
          else if s = frSpecFuncs[7] then
                v := CurPage.CurPos
          else if s = frSpecFuncs[8] then
                v := SavedAllPages
          else
          begin
                if s <> SubValue then
                begin
                  SubValue := s;
                  v := Parser.Calc(s);
                  SubValue := '';
                end
                else raise(EParserError.Create(''));
          end;
        end;
  end;
end;

Fix:
procedure TfrReport.GetVariableValue(const s:String; var v:Variant);
var Value: TfrValue;
        DataSet: TDataSet;
        Fld: TField; <-- fixed. maq@mail.ru, renamed because Field conflicts
with TfrValue.Field
begin
  v := Null;
  if Assigned(FOnGetValue) then FOnGetValue(s, v);
  if v = Null then
  begin
        Value := Values.FindVariable(s);
        if Value <> nil then
          with Value do
          case Typ of
                vtNotAssigned:
                  v := '';
                vtDBField:
                begin // <-- fixed maq@mail.ru
                //begin fix 2.21.1
                  Fld := DSet.FindField(Field);
                  if Assigned(Fld) then
                  begin
                    if Fld.FieldKind = fkCalculated Then v := Fld.Text
                    Else v := Fld.AsVariant;
                  end
                  else
                    v := ' ';
                //end fix 2.21.1
                end;

                vtOther:
                  if OtherKind = 1 then
                        v := Parser.Calc(Field) else
                        v := Parser.Calc(frSpecFuncs[OtherKind]);
          end
        else
        begin
          DataSet := GetDefaultDataSet;
          frGetDataSetAndField(s, DataSet, Fld);
          if Fld <> nil then
                v := Fld.AsVariant
          else if s = 'VALUE' then
                v := CurValue
          else if s = frSpecFuncs[0] then
                v := PageNo + 1
          else if s = frSpecFuncs[2] then
                v := CurDate
          else if s = frSpecFuncs[3] then
                v := CurTime
          else if s = frSpecFuncs[4] then
                v := CurBand.Positions[psLocal]
          else if s = frSpecFuncs[5] then
                v := CurBand.Positions[psGlobal]
          else if s = frSpecFuncs[6] then
                v := CurPage.ColPos
          else if s = frSpecFuncs[7] then
                v := CurPage.CurPos
          else if s = frSpecFuncs[8] then
                v := SavedAllPages
          else
          begin
                if s <> SubValue then
                begin
                  SubValue := s;
                  v := Parser.Calc(s);
                  SubValue := '';
                end
                else raise(EParserError.Create(''));
          end;
        end;
  end;
end;
-----------
Was:
procedure TfrReport.PrepareDataSets;
var i: Integer;
begin
  HasBlobs := False;
  with Values do
  for i := 0 to Items.Count-1 do
    with Objects[i] do
    if Typ = vtDBField then
    begin
      
      DSet := frGetDataSet(DataSet);
      { was:
          DField := DSet.FieldByName(Field);
      if DField.DataType in [ftBlob..ftTypedBinary] then HasBlobs := True;
      }
      //fix by   <EXPERT1@dol.ru>
      if Assigned(DSet) Then
      begin
        DField := DSet.FindField(Field);
        IF Assigned(DField) Then
          if DField.DataType in [ftBlob..ftTypedBinary] then
            HasBlobs :=True;
      end
      Else DField := Nil;
      //endfix
    end;
end;

Fix:
procedure TfrReport.PrepareDataSets;
var i: Integer;
  Fld:TField;
begin
  HasBlobs := False;
  with Values do
  for i := 0 to Items.Count-1 do
        with Objects[i] do
        if Typ = vtDBField then
        begin

          DSet := frGetDataSet(DataSet);
          { was:
          DField := DSet.FieldByName(Field);
          if DField.DataType in [ftBlob..ftTypedBinary] then HasBlobs := True;
          }
          //fix by   <EXPERT1@dol.ru>
          if Assigned(DSet) Then
          begin
                Fld := DSet.FindField(Field);  <-- fixed. maq@mail.ru
                IF Assigned(Fld) Then
                  if Fld.DataType in [ftBlob..ftTypedBinary] then
                        HasBlobs :=True;
      end;
      //endfix
    end;
end;

-----------------------------------------------------------------------------
ID:40
State: Applied 2.21.8
Auth: Magomed G. Abdurakhmanov
Mail: maq@mail.ru
Type: -
Desc: Remove reference to the 'spin' unit, because it isn't used really, 
      and it doesn't exists in the CBuilder's library.

Unit: fr_rich.pas
Fun: the 'uses' list in the interface
Was:
  Forms, Dialogs, StdCtrls, Buttons, ExtCtrls, ComCtrls, ClipBrd, Spin,

Fix:
  Forms, Dialogs, StdCtrls, Buttons, ExtCtrls, ComCtrls, ClipBrd,

-----------------------------------------------------------------------------
ID:39
State: Applied 2.21.8
Auth: Magomed G. Abdurakhmanov
Mail: maq@mail.ru
Type: -
Desc: The TUpDown control for a font size in the richedit
      designer is not working.

Unit: fr_rich.dfm
Fun: All changes in the form.
How to fix:
  The name of the TUpDown's associated control is Edit1.
  Rename it to the FontSizeEdit. And set the OnChange event of FontSizeEdit to
  FontSizeChange - this event handler already exists in the source, you only
  need set the reference to the him.

-----------------------------------------------------------------------------
ID:38
State: Applied 2.21.8
Auth: Magomed G. Abdurakhmanov
Mail: maq@mail.ru
Type: -
Desc: Using unnamed DataSet components in application (created
      at the runtime) causes access violation when selecting the 
      dataset in designer.

Unit: fr_flds.pas
Fun: TFieldsForm.FillValCombo
Was:
  for i := 0 to f.ComponentCount-1 do
  begin
    c := f.Components[i];
    if c is TDataSet then
      if f = CurReport.Owner then
        s.Add(c.Name) else
        s.Add(f.Name + '.' + c.Name);
  end;

Fix:
  for i := 0 to f.ComponentCount-1 do
  begin
    c := f.Components[i];
    if (c is TDataSet) and (Length(c.Name)<>0)then
      if f = CurReport.Owner then
        s.Add(c.Name) else
        s.Add(f.Name + '.' + c.Name);
  end;

-----------------------------------------------------------------------------
ID:37
State: Applied 2.21.8
Auth: Marcel Wagenaar
Mail: <m.wagenaar@flakkee.net
Type: - - bug fix                 (+ - new feature
                                   - - fix the bug )
Desc: Open/save title names correction
Unit: FR_View
Funn: LoadBtnClick
Was:
begin
  OpenDialog.Filter := frLoadStr('SRepFile') + ' (*.frp)|*.frp';
  with OpenDialog do
    if Execute then
      LoadFromFile(FileName);
end;
Fix:
begin
  with OpenDialog do begin
    Filter := frLoadStr('SRepFile') + ' (*.frp)|*.frp';
    Title := LoadBtn.Hint;
    if Execute then
      LoadFromFile(FileName);
  end;
end;

Funn: SaveBtnClick
Was:
...
  with SaveDialog do
  begin
    Filter := s;
    FilterIndex := 1;

Fix:
  with SaveDialog do
  begin
    Filter := s;
    Title := SaveBtn.Hint;
    FilterIndex := 1;

-----------------------------------------------------------------------------
ID:36
State:Accepted
Auth: Kazimierz Stopyra
Mail: stok@wodip.opole.pl
Type: -
Desc: Parser is sensitivity for blanc char and listseparator

      In fr_parser ',' - is used to separate elemens of list.
      In Polish ',' - is used to decimal
      I propes use ListSeparator
   A) [if([x]>2,1,0)] - generate exception EConvertError
   B) [if  (...  - blanc char after function generate
exception

A)...................................
Unit: FR_Pars
 function TParser.GetIdentify
Was:
  while (i <= Length(s)) and not (s[i] in ['
','+','-','*','/','>','<','=','(',')']) do
Fix:
  while (i <= Length(s)) and not (s[i] in ['
','+','-','*','/','>','<','=','(',')',ListSeparator]) do

A) and B) ................................
procedure TParser.Get3Parameters(const s:String; var
i:Integer; var s1,s2,s3:String);
var c,d,oi,ci: Integer;
begin
  s1 := ''; s2 := ''; s3 := '';
  While (i<length(s)) and (s[i]<>'(') do inc(i);  //StoK
  c := 1;  d := 1; oi := i+1; ci := 1;
  repeat
    Inc(i);
    if i>length(s) then break; //StoK
    if s[i] = '(' then Inc(c)
    else if s[i] = ')' then Dec(c);
    if s[i] = '''' then
      if d = 1 then Inc(d) else d := 1;
    if (s[i] = {',' StoK} listSeparator) and (c = 1) and (d = 1) then
    begin
      if ci = 1 then
        s1 := Copy(s,oi,i-oi)
      else
        s2 := Copy(s,oi,i-oi);
      oi := i+1; Inc(ci);
    end;
  until (c = 0)  {or (i >= Length(s)) StoK};
  case ci of
    1: s1 := Copy(s,oi,i-oi);
    2: s2 := Copy(s,oi,i-oi);
    3: s3 := Copy(s,oi,i-oi);
  end;
  Inc(i);
end;

-----------------------------------------------------------------------------
ID:35
State: Applied 2.21.8
Auth: Kazimierz Stopyra
Mail: stok@wodip.opole.pl
Type: -
Desc: if varible is [if([xx]='',...........
   it not work
Unit: FR_Pars
function TParser.CalcOPZ
Was:
     if Format = fNone then
              nm[st] := s1

Fix:

            if Format = fNone then
              if s1='' then               //StoK .->
                nm[st] := null
              else                       //StoK <-
                nm[st] := s1
-----------------------------------------------------------------------------
ID:34
State: Rejected (make bug on print multi master data bands)
Auth: Kazimierz Stopyra
Mail: stok@wodop.opole.pl
Type: +
Desc: Print data band if dataSet is nil
Unit: FR_Class
Func: DoLoop
Was:
  begin
    b := Bands[Bnds[Level,bpData]];
    while (b <> nil) and (b.Dataset <> nil) do
    begin
      b.DataSet.First;
      if Mode = pmBuildList then
        AddRecord(b, rtFirst) else
        b.Positions[psLocal] := 1;

      b1 := Bands[btGroupHeader];
      while b1 <> nil do
      begin
        b1.Positions[psLocal] := 0;
        b1.Positions[psGlobal] := 0;
        b1 := b1.Next;
      end;

      if not b.DataSet.EOF then
      begin
        if (Level = 1) and HasGroups then
          InitGroups(Bands[btGroupHeader]);
//        AddToStack(Bands[Bnds[Level,bpHeader]]);
        AddHeadersOfBand(b,false); // fix
        while not b.DataSet.EOF do
        begin
          Application.ProcessMessages;
          if MasterReport.Terminated then break;
          AddToStack(b);
          WasPrinted := True;
          if Level < MaxLevel then
          begin
            DoLoop(Level + 1);
            if BndStackTop > 0 then
              if b.PrintIfSubsetEmpty then
                ShowStack
              else
              begin
                Dec(BndStackTop);
                WasPrinted := False;
              end;
          end
          else ShowStack;

          if (Level = 1) and HasGroups then
          begin
            b1 := Bands[btGroupFooter];
            while b1 <> nil do
            begin
              b1.DoAggregate;
              b1 := b1.Next;
            end;
          end;

          b.DataSet.Next;

          if (Level = 1) and HasGroups then
          begin
            b1 := Bands[btGroupHeader];
            while b1 <> nil do
            begin
              if (Parser.Calc(b1.GroupCondition) <> b1.LastGroupValue) or
                 b.DataSet.EOF then
              begin
//                ShowBand(Bands[Bnds[Level,bpFooter]]);
                AddFootersOfBand(b,true); // fix
                b2 := Bands[btGroupHeader].LastBand;
                while b2 <> b1 do
                begin
                  ShowBand(b2.FooterBand);
                  b2.Positions[psLocal] := 0;
                  b2 := b2.Prev;
                end;
                ShowBand(b1.FooterBand);
                if not b.DataSet.EOF then
                begin
                  if b1.NewPageAfter then NewPage;
                  InitGroups(b1);
//                  ShowBand(Bands[Bnds[Level,bpHeader]]);
                  AddHeadersOfBand(b,true); // fix
                end;
                b.Positions[psLocal] := 0;
                break;
              end;
              b1 := b1.Next;
            end;
          end;

          if Mode = pmBuildList then
            AddRecord(b, rtNext)
          else if WasPrinted then
          begin
            Inc(CurPos);
            Inc(b.Positions[psGlobal]);
            Inc(b.Positions[psLocal]);
            if not b.DataSet.EOF and b.NewPageAfter then NewPage;
          end;
          if MasterReport.Terminated then break;
        end;
        if BndStackTop = 0 then
//          ShowBand(Bands[Bnds[Level,bpFooter]])
          AddFootersOfBand(b,true) // fix
        else
          Dec(BndStackTop);
      end;
      b := b.Next;
    end;
  end;

Fix:
  // StoK - my ID
  begin
    b := Bands[Bnds[Level,bpData]];
    while (b <> nil) {StoK and (b.Dataset <> nil)} do
    begin
      if assigned (b.DataSet) then  //StoK
        b.dataSet.First;
      if Mode = pmBuildList then
        AddRecord(b, rtFirst) else
        b.Positions[psLocal] := 1;

      b1 := Bands[btGroupHeader];
      while b1 <> nil do
      begin
        b1.Positions[psLocal] := 0;
        b1.Positions[psGlobal] := 0;
        b1 := b1.Next;
      end;

      if not assigned(b.DataSet) or  //StoK
         not b.DataSet.EOF then
      begin

        if (Level = 1) and HasGroups then
          InitGroups(Bands[btGroupHeader]);
//        AddToStack(Bands[Bnds[Level,bpHeader]]);
        AddHeadersOfBand(b,false); // fix
        while
            not assigned(b.dataSet) or  //StoK
            not b.DataSet.EOF do
        begin
          Application.ProcessMessages;
          if MasterReport.Terminated then break;
          AddToStack(b);
          WasPrinted := True;
          if Level < MaxLevel then
          begin
            DoLoop(Level + 1);
            if BndStackTop > 0 then
              if b.PrintIfSubsetEmpty then
                ShowStack
              else
              begin
                Dec(BndStackTop);
                WasPrinted := False;
              end;
          end
          else ShowStack;

          if (Level = 1) and HasGroups then
          begin
            b1 := Bands[btGroupFooter];
            while b1 <> nil do
            begin
              b1.DoAggregate;
              b1 := b1.Next;
            end;
          end;

          if assigned (b.DataSet) then  //StoK
            b.DataSet.Next;

          if (Level = 1) and HasGroups then
          begin
            b1 := Bands[btGroupHeader];
            while b1 <> nil do
            begin
              if (Parser.Calc(b1.GroupCondition) <> b1.LastGroupValue)
                  or not assigned(b.dataSet)   //StoK
                  or b.DataSet.EOF then
              begin
//                ShowBand(Bands[Bnds[Level,bpFooter]]);
                AddFootersOfBand(b,true); // fix
                b2 := Bands[btGroupHeader].LastBand;
                while b2 <> b1 do
                begin
                  ShowBand(b2.FooterBand);
                  b2.Positions[psLocal] := 0;
                  b2 := b2.Prev;
                end;
                ShowBand(b1.FooterBand);
                if not assigned(b.DataSet) or  //StoK
                   not b.DataSet.EOF then
                begin
                  if b1.NewPageAfter then NewPage;
                  InitGroups(b1);
//                  ShowBand(Bands[Bnds[Level,bpHeader]]);
                  AddHeadersOfBand(b,true); // fix
                end;
                b.Positions[psLocal] := 0;
                break;
              end;
              b1 := b1.Next;
            end;
          end;

          if Mode = pmBuildList then
            AddRecord(b, rtNext)
          else if WasPrinted then
          begin
            Inc(CurPos);
            Inc(b.Positions[psGlobal]);
            Inc(b.Positions[psLocal]);
            if (not assigned(b.DataSet) or //StoK
               not b.DataSet.EOF) and b.NewPageAfter then NewPage;
          end;
          if MasterReport.Terminated then break;
          if not assigned(b.DataSet) then break; //StoK 1 pass only
        end;
        if BndStackTop = 0 then
//          ShowBand(Bands[Bnds[Level,bpFooter]])
          AddFootersOfBand(b,true) // fix
        else
          Dec(BndStackTop);
      end;
      b := b.Next;
    end;
  end;

-----------------------------------------------------------------------------
ID: 33
State: Applied 2.21.8
Auth: s999 
Mail: s999@log.philos.msu.ru
Type: -
Desc: FreeReport changes font size according to windows settings of system font
Unit: Fr_Class.pas
Func: TfrMemoView.AssignFont
Was:
  Font.Color := FontColor;

Fix:
  Font.Color := FontColor;
  Font.PixelsPerInch:=96;


>VER 2.21.7  06.02.00
-----------------------------------------------------------------------------
ID: 32
State: Applied 2.21.7
Auth: Max Belugin
Mail: belugin@mail.ru
Type: -
Desc: Component library page name isn't same as VCL Name
Unit: fr_Reg.pas
Func: Register

was:
RegisterComponents('FastReport',[TfrReport,TfrCompositeReport,
fix:
RegisterComponents('FreeReport',[TfrReport,TfrCompositeReport,
was:
RegisterComponents('FR tools',[TfrSpeedButton,TfrDock,TfrToolBar,
fix:
RegisterComponents('FreR tools',[TfrSpeedButton,TfrDock,TfrToolBar,

-----------------------------------------------------------------------------
ID: 31
State: Applied 2.21.7
Auth: Alexey Nalimov
Mail: nalimov@energy.spb.ru
Type: + 
Desc: improved aggregation parsing with formulas inside
Unit: frClass.pas
Func: procedure TfrStdFunctionLibrary.DoFunction

procedure TfrStdFunctionLibrary.DoFunction(FNo: Integer; p1, p2, p3:
Variant;
  var val: String);
var dk: (dkNone, dkSum, dkMin, dkMax, dkAvg, dkCount);
    min, max, avg, sum, count, d, v: Double;
    DataSet: TDataSet;
    Field: TField;
    s1: String;
    vv:Variant;
//Start fix - added
    OldSum, OldMax, OldMin: Double;
    dPlan: (dpAll, dpBefore, dpAfter, dpAllBefore, dpAllAfter);
    ParseDataSet: TDataSet;
    Bm, tmpBm: TBookmark;
//end fix

begin
  dk := dkNone;
  case FNo of
    0: dk := dkAvg;
    1: dk := dkCount;
    2: val := '''' + FormatDateTime(Parser.Calc(p1), Parser.Calc(p2)) + '''';
    3: val := '''' + FormatFloat(Parser.Calc(p1), Parser.Calc(p2)) + '''';
    4: val := '''' + AnsiLowerCase(Parser.Calc(p1)) + '''';
    5: dk := dkMax;
    6: dk := dkMin;
    7:
      begin
        s1 := AnsiLowerCase(Parser.Calc(p1));
        if Length(s1) > 0 then
          val := '''' + AnsiUpperCase(s1[1]) + Copy(s1, 2, Length(s1)-1) + ''''
        else
          val := '''' + '''';
      end;
    8: val := '%d''' + Parser.Calc(p1) + '''';
    9: val := '%t''' + Parser.Calc(p1) + '''';
    10: dk := dkSum;
    11: val := '''' + AnsiUpperCase(Parser.Calc(p1)) + '''';
  end;

  if dk <> dkNone then begin
    if (CurBand.Typ = btGroupFooter) and not CurBand.Visible then begin
      val := '0';
      { Is this already calculated ? }
      s1 := CurBand.GroupValues.Values[List[FNo] + p1];
      { If yes, then do not calculate again }
      if s1 <> '' then if s1[1] = '1' then Exit else s1 := Copy(s1, 2, 255);
      d := 0;
      { Calculate parameter value }
      if dk <> dkCount then begin
        vv := Parser.Calc(p1);
        if VarType(vv) = varNull then d:=0 else d:=vv;
      end;

      if s1 = '' then
        if dk = dkMin then s1 := '1e200'
        else if dk = dkMax then s1 := '-1e200'
        else s1 := '0';

      v := StrToFloat(s1);
      case dk of
        dkAvg: v := v + d;
        dkCount: v := v + 1;
        dkMax: if v < d then v := d;
        dkMin: if v > d then v := d;
        dkSum: v := v + d;
      end;

      CurBand.GroupValues.Values[List[FNo] + p1] := '1' + FloatToStr(v);
      Exit;
    end;

    if (CurBand.Typ = btGroupFooter) and CurBand.Visible then begin
      val := Copy(CurBand.GroupValues.Values[List[FNo] + p1], 2, 255);
      if dk = dkAvg then
        val := FloatToStr(StrToFloat(val) / CurBand.Count);
      Exit;
    end;

//Start fix - added
    dPlan := dpAll;  // When not specified, calculate the whole range
    ParseDataSet := nil; // Default
// End fix

    DataSet := GetDefaultDataSet;
    if dk = dkCount then DataSet := frGetDataSet(p1)
    else begin

// Start fix - added
      if p2 <> '' then begin { Plan is specified }
        if p3 <> '' then begin
          // Is have 3-d parameter, treat it as a range limitation
          if AnsiCompareText(p3, 'DP_BEFORE') = 0 then dPlan := dpBefore
          else if AnsiCompareText(p3, 'DP_AFTER') = 0 then dPlan := dpAfter
          else if AnsiCompareText(p3, 'DP_ALLBEFORE') = 0 then dPlan := dpAllBefore
          else if AnsiCompareText(p3, 'DP_ALLAFTER') = 0 then dPlan := dpAllAfter;
        end;
        // Second parameter treat as a plan table
        ParseDataSet := frGetDataSet(p2);
      end
      else frGetDataSetAndField(p1, DataSet, Field); { Plan not specified }
    end;

    if ParseDataSet = nil then ParseDataSet := DataSet;

// end fix

    min := 1e200; max := -1e200; sum := 0; count := 0; avg := 0;

// Start fix
    // Oldxxx are used with DP_BEFORE plan to remove last step calcs
    OldSum := 0; OldMax := 0; OldMin := 0;
// end fix

{ Was:

    DataSet.First;
    while not DataSet.EOF do
    begin
      v := 0;
      // fix 17.09.99
        was:
      if dk <> dkCount then
        v := Field.AsFloat;
      //
      if dk <> dkCount then
        if Field<>nil then v:= Field.AsFloat
                      else v:= Parser.Calc(p1);
      // end fix

      if v > max then max := v;
      if v < min then min := v;
      sum := sum + v;
      count := count + 1;
      DataSet.Next;
    end;

}

// Start fix
    if ParseDataSet <> nil then begin
      Bm := ParseDataSet.GetBookmark;  // Remember current position
      try
        // Goto first record, if current plan needs
        if (dPlan in [dpAll, dpBefore, dpAllBefore]) then ParseDataSet.First;
        // Skip current record, is needed
        if (dPlan in [dpAfter]) then ParseDataSet.Next;
        while not ParseDataSet.EOF do begin
          // Check if before current position
          if (dPlan in [dpBefore, dpAllBefore]) then begin
            // Possibly this step can be done better ???
            tmpBm := ParseDataSet.GetBookmark;
            try
              if ParseDataSet.CompareBookmarks(Bm, tmpBm) = 0 then begin
                if dPlan = dpBefore then begin  // Remove last step calcs
                  Max := OldMax;
                  Min := OldMin;
                  Sum := OldSum;
                  Count := Count - 1;
                end;
              end;
            finally
              ParseDataSet.FreeBookmark(tmpBm);
            end;
            // Now finished
            Break;
          end;
          v := 0;
          if dk <> dkCount then begin
            if Field <> nil then v := Field.AsFloat else v := Parser.Calc(p1);
          end;
          OldMax := Max;
          OldMin := Min;
          OldSum := Sum;
          if v > max then max := v;
          if v < min then min := v;
          Sum := Sum + v;
          Count := Count + 1;
          ParseDataSet.Next;
        end;
      finally
        ParseDataSet.GotoBookmark(Bm);
        ParseDataSet.FreeBookmark(Bm);
      end;
    end;

// End fix

    if Count > 0 then Avg := Sum / Count;
    d := 0;
    case dk of
      dkSum: d := sum;
      dkMin: d := min;
      dkMax: d := max;
      dkAvg: d := avg;
      dkCount: d := count;
    end;
    val := FloatToStr(d);
  end;
end;

-----------------------------------------------------------------------------
ID: 30
State: Applied 2.21.7
Auth: Brian K. Andersen
Mail: bka@nonstop.dk
Type: +
Desc: Printer setup in preview without printing. (eg. changing paper from
portrait to landscape and see the change on the screen at once.
Unit: FR_View
Func: New function
Was:
  Not possible

Fix:
  1. Add a new TfrSpeedButton to the Previewform next to the printer
button. 
     The easiest way is to copy the below into FR_View form (view as text):

  object TPanel: TPanel
    Left = 0
    Top = 0
    Width = 443
    Height = 33
    Align = alTop
    BevelOuter = bvNone
    TabOrder = 0
    object SetUpPrintBtn: TfrSpeedButton             <- Start here
      Left = 136
      Top = 6
      Width = 24
      Height = 24
      Hint = 'Printersetup'
      Flat = True
      Glyph.Data = {
        76010000424D7601000000000000760000002800000020000000100000000100
        0400000000000001000000000000000000001000000010000000000000000000
        800000800000008080008000000080008000808000007F7F7F00BFBFBF000000
        FF0000FF000000FFFF00FF000000FF00FF00FFFF0000FFFFFF00555550FF0559
        1950555FF75F7557F7F757000FF055591903557775F75557F77570FFFF055559
        1933575FF57F5557F7FF0F00FF05555919337F775F7F5557F7F700550F055559
        193577557F7F55F7577F07550F0555999995755575755F7FFF7F5570F0755011
        11155557F755F777777555000755033305555577755F75F77F55555555503335
        0555555FF5F75F757F5555005503335505555577FF75F7557F55505050333555
        05555757F75F75557F5505000333555505557F777FF755557F55000000355557
        07557777777F55557F5555000005555707555577777FF5557F55553000075557
        0755557F7777FFF5755555335000005555555577577777555555}
      NumGlyphs = 2
      OnClick = SetUpPrintBtnClick
    end                                               <- End here

  2: Add a TPrinterSetupDialog on to the form too. 

    object PrinterSetupDialog: TPrinterSetupDialog
      Left = 242
      Top = 99
    end

  3. Add an event to the button: SetUpPrintBtnClick

     Looking like this:

        procedure TPreviewForm.SetUpPrintBtnClick(Sender: TObject);
        var FromPg,ToPg: Integer;
            ind: Integer;
        begin
          ind := Printer.PrinterIndex;
          with PrinterSetupDialog do
          begin
            PaintAllowed := True;
            if Execute then
            begin
              if Printer.PrinterIndex <> ind then
                if Doc.CanRebuild then
                  if Doc.ChangePrinter(ind,Printer.PrinterIndex) then
                  begin
                    Doc.PrepareReport;
                    RedrawAll;
                  end
                  else exit;
              FromPg := 1; ToPg := Doc.EMFPages.Count;

              if PrintDialog.PrintRange = prPageNums then
              begin
                FromPg := PrintDialog.FromPage;
                ToPg := PrintDialog.ToPage;
              end;

              with Doc.EMFPages[0]^ do
              begin
                Prn.SetPrinterInfo(pgSize, pgWidth, pgHeight, pgOr);
                Prn.FillPrnInfo(PrnInfo);
              end;
            end;
          end;
          FormResize(nil);
          PBoxPaint(nil);
        end;

-----------------------------------------------------------------------------
ID: 29
State: Applied 2.21.7
Auth: Brian K. Andersen
Mail: bka@nonstop.dk
Type: -
Desc: A memo doesn't cut the string if it exceeds the width of the memofield (or framed rectangle)
Unit: FR_Class
Func: TfrMemoView.WrapMemo;
Was:
  procedure OutLine(const str:String);
  begin
    SMemo.Add(str);
    Inc(size, size1);
  end;
Fix:
  procedure OutLine(const str:String);
  var s : string;
  begin
    s := Str;
    While Canvas.TextWidth(s) > maxwidth do
      SetLength(s,Length(s)-1);
    SMemo.Add(s);
    Inc(size, size1);
  end;
    


-----------------------------------------------------------------
ID:28
State: Applied 2.21.7
Auth: Brian K. Andersen
Mail: bka@nonstop.dk
Type: -
Desc: If curband in GetDefaultDataSet is nil it throws an exception.
Unit: FR_Class
Func: function GetDefaultDataSet: TDataSet;

*Was*:
  function GetDefaultDataSet: TDataSet;
  var Res: TfrDataset;
  begin
    Result := nil; Res := nil;
    case CurBand.Typ of
      btMasterData, btReportSummary, btMasterFooter,
      btGroupHeader, btGroupFooter:
        Res := CurPage.Bands[btMasterData].DataSet;
      btDetailData, btDetailFooter:
        Res := CurPage.Bands[btDetailData].DataSet;
      btSubDetailData, btSubDetailFooter:
        Res := CurPage.Bands[btSubDetailData].DataSet;
      btColumnData, btColumnFooter:
        Res := CurPage.Bands[btColumnData].DataSet;
    end;
    if (Res <> nil) and (Res is TfrDBDataset) then
      with Res as TfrDBDataset do
        if DataSource <> nil then
          Result := DataSource.DataSet;
  end;

*Fix*: 
  function GetDefaultDataSet: TDataSet;
  var Res: TfrDataset;
  begin
    Result := nil; Res := nil;
    If CurBand <> Nil then
    Begin
      case CurBand.Typ of
        btMasterData, btReportSummary, btMasterFooter,
        btGroupHeader, btGroupFooter:
          Res := CurPage.Bands[btMasterData].DataSet;
        btDetailData, btDetailFooter:
          Res := CurPage.Bands[btDetailData].DataSet;
        btSubDetailData, btSubDetailFooter:
          Res := CurPage.Bands[btSubDetailData].DataSet;
        btColumnData, btColumnFooter:
          Res := CurPage.Bands[btColumnData].DataSet;
      end;
    End;

    if (Res <> nil) and (Res is TfrDBDataset) then
      with Res as TfrDBDataset do
        if DataSource <> nil then
          Result := DataSource.DataSet;
  end;
    



-----------------------------------------------------------------
ID:27
State: Applied 2.21.7
Auth: Alexander Pavlenko
Mail: apavlenko@mail.ru
Type: - (Fix ID:26 replacement)
Desc: Long strings are truncated to length 255 in Rectangle object
      while reading/writing document form.
=====================================================================
Unit: FR_Class
Func: interface
---------------------------------------------------------------------
Add:

type
  EIncompatibleVersion = class(Exception);

---------------------------------------------------------------------
Was:

const
  frCurrentVersion = 22;
---------------------------------------------------------------------
Fix:

const
  frCurrentVersion = 23;

=====================================================================
Unit: FR_Class
Func: LoadFromStream
---------------------------------------------------------------------
Was:

procedure TfrReport.LoadFromStream(Stream:TStream);
begin
  Stream.Read(frVersion, 1);
  if frVersion < 21 then
  ...
---------------------------------------------------------------------
Fix:

procedure TfrReport.LoadFromStream(Stream:TStream);
begin
  Stream.Read(frVersion, 1);
  if frVersion > frCurrentVersion then raise
EIncompatibleVersion.Create('     
  ');
  if frVersion < 21 then
  ...

=====================================================================
Unit: FR_Class
Func: LoadFromFile
---------------------------------------------------------------------
Was:

procedure TfrReport.LoadFromFile(FName:String);
var Stream: TFileStream;
begin
  Stream := TFileStream.Create(FName, fmOpenRead);
  LoadFromStream(Stream);
  Stream.Free;
end;
---------------------------------------------------------------------
Fix:

procedure TfrReport.LoadFromFile(FName:String);
var Stream: TFileStream;
begin
  Stream := TFileStream.Create(FName, fmOpenRead);
  try
    LoadFromStream(Stream);
  finally
    Stream.Free;
  end;
end;

=====================================================================
Unit: FR_Class
Func: SaveToFile
---------------------------------------------------------------------
Was:

procedure TfrReport.SaveToFile(FName:String);
var Stream: TFileStream;
begin
  Stream := TFileStream.Create(FName, fmCreate);
  try
    SaveToStream(Stream);
  finally
    Stream.Free;
  end;
end;

=====================================================================
Unit: FR_Utils
Func: frReadMemo
---------------------------------------------------------------------
Was:

procedure frReadMemo(Stream:TStream; l:TStrings);
var
  s: String[255];
  i: Integer;
  b: Byte;
begin
  l.Clear;
  i := 1;
  repeat
    Stream.Read(b,1);
    if (b = 13) or (b = 0) then
    begin
      s[0] := Chr(i-1);
      if not ((b = 0) and (i = 1)) then l.Add(s);
      i := 1;
    end
    else if b <> 0 then
    begin
      s[i] := Chr(b);
      Inc(i);
    end;
  until b = 0;
end;
---------------------------------------------------------------------
Fix:

procedure frReadMemo(Stream:TStream; l:TStrings);
var
  s: String[255];
  t: String;
  i: Integer;
  b: Byte;
begin
  if frVersion < 23 then begin
    l.Clear;
    i := 1;
    repeat
      Stream.Read(b,1);
      if (b = 13) or (b = 0) then
      begin
        s[0] := Chr(i-1);
        if not ((b = 0) and (i = 1)) then l.Add(s);
        i := 1;
      end
      else if b <> 0 then
      begin
        s[i] := Chr(b);
        Inc(i);
      end;
    until b = 0;
  end
  else begin
    Stream.ReadBuffer(i, SizeOf(i));
    SetLength(t, i);
    Stream.ReadBuffer(PChar(t)^, i);
    l.Text := t;
  end;
end;

=====================================================================
Unit: FR_Utils
Func: frWriteMemo
---------------------------------------------------------------------
Was:

procedure frWriteMemo(Stream:TStream; l:TStrings);
var s: String[255];
    i,j: Integer;
    b: Byte;
begin
  for i := 0 to l.Count-1 do
  begin
    s := l[i];
    for j := 1 to Length(s) do
      Stream.Write(s[j],1);
    b := 13;
    if i <> l.Count-1 then Stream.Write(b,1);
  end;
  b := 0;
  Stream.Write(b,1);
end;
---------------------------------------------------------------------
Fix:

procedure frWriteMemo(Stream:TStream; l:TStrings);
var
  s: String;
  i: Integer;
begin
  s := l.Text;
  i := Length(s);
  Stream.WriteBuffer(i, SizeOf(i));
  Stream.WriteBuffer(PChar(s)^, i);
end;
  

-----------------------------------------------------------------
ID:26
State: accepted
Auth: Alexander Pavlenko
Mail: apavlenko@mail.ru
Type: -
Desc: Long strings are truncated to length 255 in Rectangle object
      while reading/writing document form.
Unit: FR_Utils
Func: frReadMemo, frWriteMemo
Was:
procedure frReadMemo(Stream:TStream; l:TStrings);
var s: String[255];
    i: Integer;
    b: Byte;
begin
  l.Clear;
  i := 1;
  repeat
    Stream.Read(b,1);
    if (b = 13) or (b = 0) then
    begin
      s[0] := Chr(i-1);
      if not ((b = 0) and (i = 1)) then l.Add(s);
      i := 1;
    end
    else if b <> 0 then
    begin
      s[i] := Chr(b);
      Inc(i);
    end;
  until b = 0;
end;


Fix:
procedure frReadMemo(Stream:TStream; l:TStrings);
var
  s: String;
  i: Integer;
begin
  Stream.ReadBuffer(i, SizeOf(i));
  SetLength(s, i);
  Stream.ReadBuffer(PChar(s)^, i);
  l.Text := s;
end;

Func: frWriteMemo
Was:

procedure frWriteMemo(Stream:TStream; l:TStrings);
var s: String[255];
    i,j: Integer;
    b: Byte;
begin
  for i := 0 to l.Count-1 do
  begin
    s := l[i];
    for j := 1 to Length(s) do
      Stream.Write(s[j],1);
    b := 13;
    if i <> l.Count-1 then Stream.Write(b,1);
  end;
  b := 0;
  Stream.Write(b,1);
end;

Fix:

procedure frWriteMemo(Stream:TStream; l:TStrings);
var
  s: String;
  i: Integer;
begin
  s := l.Text;
  i := Length(s);
  Stream.WriteBuffer(i, SizeOf(i));
  Stream.WriteBuffer(PChar(s)^, i);
end;
-----------------------------------------------------------------
ID:25
State: Applied 2.21.7
Auth: Alexey Popov
Mail: aghost@bigfoot.com
Type: +
Desc: Multiple headers and footers for data-bands, (As in FR 2.3)


Unit: Fr_class
Func: DoLoop
Fix:
  procedure DoLoop(Level:Integer);
  var WasPrinted: Boolean;
      b,b1,b2: TfrBand;

    procedure InitGroups(b:TfrBand);
    begin
      b.InitGroupValues;
      while b <> nil do
      begin
        Inc(b.Positions[psLocal]);
        Inc(b.Positions[psGlobal]);
        ShowBand(b);
        b := b.Next;
      end;
    end;

    // Alex Ghost's procs begin
    procedure AddHeadersOfBand(b: TfrBand; ShowNow: boolean);
    var
      Ymin,Ymax: integer;
      b1: TfrBand;
    begin
      if Assigned(b.Prev) then Ymin:=b.Prev.y else Ymin:=0;
      Ymax:=b.y;
      b1:=Bands[Bnds[Level,bpHeader]];
      while Assigned(b1) do begin
        if (b1.y > Ymin) and (b1.y < Ymax) then
          if ShowNow then
            ShowBand(b1)
          else
            AddToStack(b1);
        b1:=b1.Next;
      end;
    end;

    procedure AddFootersOfBand(b: TfrBand; ShowNow: boolean);
    var
      Ymin,Ymax: integer;
      b1: TfrBand;
    begin
      if Assigned(b.Next) then Ymax:=b.Next.y else Ymax:=MaxInt;
      Ymin:=b.y;
      b1:=Bands[Bnds[Level,bpFooter]];
      while Assigned(b1) do begin
        if (b1.y > Ymin) and (b1.y < Ymax) then
          if ShowNow then
            ShowBand(b1)
          else
            AddToStack(b1);
        b1:=b1.Next;
      end;
    end;
    // Alex Ghost's procs end

  begin
    b := Bands[Bnds[Level,bpData]];
    while (b <> nil) and (b.Dataset <> nil) do
    begin
      b.DataSet.First;
      if Mode = pmBuildList then
        AddRecord(b, rtFirst) else
        b.Positions[psLocal] := 1;

      b1 := Bands[btGroupHeader];
      while b1 <> nil do
      begin
        b1.Positions[psLocal] := 0;
        b1.Positions[psGlobal] := 0;
        b1 := b1.Next;
      end;

      if not b.DataSet.EOF then
      begin
        if (Level = 1) and HasGroups then
          InitGroups(Bands[btGroupHeader]);
//        AddToStack(Bands[Bnds[Level,bpHeader]]);
        AddHeadersOfBand(b,false); // fix
        while not b.DataSet.EOF do
        begin
          Application.ProcessMessages;
          if MasterReport.Terminated then break;
          AddToStack(b);
          WasPrinted := True;
          if Level < MaxLevel then
          begin
            DoLoop(Level + 1);
            if BndStackTop > 0 then
              if b.PrintIfSubsetEmpty then
                ShowStack
              else
              begin
                Dec(BndStackTop);
                WasPrinted := False;
              end;
          end
          else ShowStack;

          if (Level = 1) and HasGroups then
          begin
            b1 := Bands[btGroupFooter];
            while b1 <> nil do
            begin
              b1.DoAggregate;
              b1 := b1.Next;
            end;
          end;

          b.DataSet.Next;

          if (Level = 1) and HasGroups then
          begin
            b1 := Bands[btGroupHeader];
            while b1 <> nil do
            begin
              if (Parser.Calc(b1.GroupCondition) <> b1.LastGroupValue) or
                 b.DataSet.EOF then
              begin
//                ShowBand(Bands[Bnds[Level,bpFooter]]);
                AddFootersOfBand(b,true); // fix
                b2 := Bands[btGroupHeader].LastBand;
                while b2 <> b1 do
                begin
                  ShowBand(b2.FooterBand);
                  b2.Positions[psLocal] := 0;
                  b2 := b2.Prev;
                end;
                ShowBand(b1.FooterBand);
                if not b.DataSet.EOF then
                begin
                  if b1.NewPageAfter then NewPage;
                  InitGroups(b1);
//                  ShowBand(Bands[Bnds[Level,bpHeader]]);
                  AddHeadersOfBand(b,true); // fix
                end;
                b.Positions[psLocal] := 0;
                break;
              end;
              b1 := b1.Next;
            end;
          end;

          if Mode = pmBuildList then
            AddRecord(b, rtNext)
          else if WasPrinted then
          begin
            Inc(CurPos);
            Inc(b.Positions[psGlobal]);
            Inc(b.Positions[psLocal]);
            if not b.DataSet.EOF and b.NewPageAfter then NewPage;
          end;
          if MasterReport.Terminated then break;
        end;
        if BndStackTop = 0 then
//          ShowBand(Bands[Bnds[Level,bpFooter]])
          AddFootersOfBand(b,true) // fix
        else
          Dec(BndStackTop);
      end;
      b := b.Next;
    end;
  end;
==================================================


Unit: Fr_btyp
Func: TBandTypesForm.FormCreate
==================================================
Was:
    b.Enabled := (bt in [btMasterData,btDetailData,btSubDetailData,
      btGroupHeader,btGroupFooter]) or not frCheckBand(bt);

Fix:
    b.Enabled := (bt in [btMasterHeader,btMasterData,btMasterFooter,
      btDetailHeader,btDetailData,btDetailFooter,
      btSubDetailHeader,btSubDetailData,btSubDetailFooter,
      btGroupHeader,btGroupFooter]) or not frCheckBand(bt);
==================================================



>VER 2.21.6
-----------------------------------------------------------------
ID: 24
State: applied 2.21.6
Auth: Alex Bartels
Mail: alex@msk-garant.ru
Type: + 
Desc: Export to RTF
Unit: FR_Class.pas
Was:
  TfrView = class(TObject)
  ...
protected
  Canvas: TCanvas;
  ....

Fix:
 TfrView = class(TObject)
 ...
 public
   Canvas: TCanvas;
   ...

Was:
implementation

uses FR_Fmted, FR_View, FR_Prntr, FR_Progr, FR_EText;
Fix:
implementation

uses FR_Fmted, FR_View, FR_Prntr, FR_Progr, FR_EText,
     Fr_ertf; \\ see FRRTF.zip

Unit: FreeRep5.dpk, Fastrep3.dpk, FASTREP.DPK
Was:
  fr_view in 'fr_view.pas';
Fix:
  fr_view in 'fr_view.pas',
  Fr_ertf in 'Fr_ertf.pas',
  Fr_ertfClass in 'Fr_ertfClass.pas';

-----------------------------------------------------------------
ID:23
State:applied 2.21.6
Auth: Alexey Popov
Mail: aghost@bigfoot.com
Type: +
Desc: Report clear
Unit: Fr_class
Fix:
==================================================
interface

type
  TfrReport = class(TComponent)
    . . . . . .
  public
    . . . . . .
    {Clear report data}
    procedure Clear;
    . . . . . .
  end;

implementation

. . . . . .

procedure TfrReport.Clear;
begin
  Pages.Clear;
  Pages.Add;
  Variables.Clear;
end;

-----------------------------------------------------------------
ID:22
State: applied 2.21.6
Auth: Alexey Popov
Mail: aghost@bigfoot.com
Type: -
Desc: Impossible to open form "Variable list", if exception occured
  while opening dataset on any form
Unit: Fr_ev_ed
Func: TEvForm.GetFields

Was:
  with DataSet do
  begin
    FieldDefs.Update;
    if FieldCount > 0 then
      for i := 0 to FieldCount-1 do
        ValList.Items.Add(Fields[i].FieldName)
    else
      for i := 0 to FieldDefs.Count-1 do
        ValList.Items.Add(FieldDefs.Items[i].Name);
  end;

Fix:
  with DataSet do
    try
      FieldDefs.Update;
      if FieldCount > 0 then
        for i := 0 to FieldCount-1 do
          ValList.Items.Add(Fields[i].FieldName)
      else
        for i := 0 to FieldDefs.Count-1 do
          ValList.Items.Add(FieldDefs.Items[i].Name);
    except
    end;

>VER 2.21.5 16.11.99
ID: 21
State: Canceled 2.21.7
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
 Date: , 15  1999  10:57:35
 From: Alex Bartels <alex@msk-garant.ru>
 To: FreeReport <FreeRep@listbot.com>
 : 
--------------------------------------------------------------------------------

(translated by maxbelugin)

unit FR_Class

Trouble:
 Number 1256 (Format is 1 234,50 - two decimals and dot as delimiter).
 Output is 1 256 (.00 - No )
 
function TfrReport.FormatValue(V:Variant; Format:Integer;

<<was:>>

    case f1 of
      0: Result := v;
      1:
        begin
          DecimalSeparator := Chr(Format and $FF);
          case f2 of
            0: Result := FormatFloat('###.##', v);
                                     ^^^^^^^^
            1: Result := FloatToStrF(v, ffFixed, 10, (Format div $0100) and $FF);
            2: Result := FormatFloat('#,###.##', v);
                                     ^^^^^^^^^^
            3: Result := FloatToStrF(v, ffNumber, 10, (Format div $0100) and $FF);
            4: Result := FormatFloat(FormatStr, v);
          end;
        end;

<<change to:>>

    case f1 of
      0: Result := v;
      1:
        begin
          DecimalSeparator := Chr(Format and $FF);
          case f2 of
            0: Result := FormatFloat('0.00', v);
            1: Result := FloatToStrF(v, ffFixed, 10, (Format div $0100) and $FF);
            2: Result := FormatFloat('0,.00', v);
            3: Result := FloatToStrF(v, ffNumber, 10, (Format div $0100) and $FF);
            4: Result := FormatFloat(FormatStr, v);
          end;
        end;


--

Bartels Alex    

Joint-Stock Insurance Company Energogarant                      
mailto:alex@msk-garant.ru


______________________________________________________________________
To unsubscribe, write to FreeRep-unsubscribe@listbot.com
Start Your Own FREE Email List at http://www.listbot.com/


>APPL 2.21.5
>ID 20
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
    Date: , 11  1999  13:19:35
   From: Alex Bartels <alex@msk-garant.ru>
 To: FreeReport <FreeRep@listbot.com>
--------------------------------------------------------------------------------
(translated by maxbelugin)

FreeReport - http://come.to/belugin

In version 2.2.1.4

1)
   It seems you have forget to apply
   Fix 

    18 oct 1999 (  By: "expert1" <EXPERT1@dol.ru> )

    << unit FR_BTyp>>
    << method TBandTypesForm.FormCreate>>
    << was>>

    Button1.Left := Round((ClientWidth-Button1.Width)/2); {Ok button position}

    << change to>>
    Button1.Left := 20; {Ok button position}
    
2)  Delete OldCreateOrder ptoperty from form FR_BTyp.dfm (Delphi 3.0
    incompatibility)

3)  Set checkbox in Fastrep3.dpk - Design Time.

Bartels Alex    

>APPL 2.21.5
>ID 19
(translated by maxbelugin)
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
    Date: , 12  1999  11:02:44
   From: Gaiser <gaiser@cybergal.com>
 To: FreeReport <FreeRep@listbot.com>
 Subj: Re: small fixes
--------------------------------------------------------------------------------

FreeReport - http://come.to/belugin


VK> FreeReport - http://come.to/belugin

VK> fr_utils.fix2

VK> << fr_utils.pas >>
VK> << procedure frWriteMemo >>

Some speed improvements
 1. Avoid evaluation of l.Count-1 in every loop
    . 
  procedure frWriteMemo(Stream:TStream; l:TStrings);
  var
    i,iCount: Integer;
    b: Byte;
  begin
   b := 13; iCount:=l.Count-1;
   for i := 0 to iCount do
   begin
  ....
  

   Gaiser
                                gaiser@cyberdude.com


______________________________________________________________________
To unsubscribe, write to FreeRep-unsubscribe@listbot.com
Start Your Own FREE Email List at http://www.listbot.com/

>APPL 2.21.5
>ID 18
(translated by maxbelugin)
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
    Date: , 12  1999  09:27:54
   : "Vitaly Krivosheyev" <vk@nasnet.kiev.ua>
 : "Free Report" <FreeRep@listbot.com>
 : small fixes
--------------------------------------------------------------------------------

FreeReport - http://come.to/belugin

fr_utils.fix2

<< fr_utils.pas >>
<< procedure frWriteMemo >>


1. Why does it writes string symbol by sumbol ?
2. Why does it initialize variable inside loop if it can be done before
loop (b )?

This is my version, it's tested. It works.

procedure frWriteMemo(Stream:TStream; l:TStrings);
var 
   i: Integer;
   b: Byte;
begin
  b := 13;
  for i := 0 to l.Count-1 do
  begin
    Stream.Write(l[i][1], Length(l[i])); 
    if i <> l.Count-1 then Stream.Write(b,1);
  end;
  b := 0;
  Stream.Write(b,1);
end;
  

// WBR, Shatl




______________________________________________________________________
To unsubscribe, write to FreeRep-unsubscribe@listbot.com
Start Your Own FREE Email List at http://www.listbot.com/

>APPL 2.21.5
>ID 17
(translated by maxbelugin)
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
    Date: , 12  1999  00:40:39
   From: "Vitaly Krivosheyev" <vk@nasnet.kiev.ua>
 To: "Free Report" <FreeRep@listbot.com>
 Subj: small fixes
--------------------------------------------------------------------------------

FreeReport - http://come.to/belugin

fr_util.fix.1

<< fr_utils.pas >>
<< frEnableControls >>
after line
   if c[i] is TLabel then
was:
   with c[i] as TLabel do
change to:
   with TLabel(c[i]) do

was:
   with c[i] as TEdit
change to:
   with TEdit(c[i])


This can improve speed

// WBR, Shatl



______________________________________________________________________
To unsubscribe, write to FreeRep-unsubscribe@listbot.com
Start Your Own FREE Email List at http://www.listbot.com/

>APPL 2.21.5
>ID 16
(translated by maxbelugin)
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
    Date: , 09  1999  16:15:11
   From: "Oleksiy Ostapov" <ostap@sumy.com>
 To: "FreeReport" <FreeRep@listbot.com>
 Subj: BugFix for 2.21-4
--------------------------------------------------------------------------------

FreeReport - http://come.to/belugin

Auth: Alexey Ostapov
Mail: ostap@sumy.com
Type: -
Desc: exception raised after mouse click lower then last item
in object inspector.
Unit: FR_Insp
Func: TInspForm.SetItemIndex(Value:Integer);
Was:
  if not TProp(FItems.Objects[Value]).Enabled then Exit;
Fix:
  if (Value = FItems.Count) or not TProp(FItems.Objects[Value]).Enabled then
    exit;


>VER 2.21.4 7.11.99
>ID 15
>APPL 2.21.4
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
    Date: , 05  1999  16:50:05
   : "expert1" <expert1@dol.ru>
 : "FreeRep Bag Fix" <FreeRep@listbot.com>
 : Path for FR
--------------------------------------------------------------------------------

FreeReport - http://come.to/belugin

 !

    FR     . 
          .
         . 
    ,    .
            
     .

<<  FR_Class >>
1.      .   
   TfrMemoView.ShowMemo >>OutMemo>>OutLine   ...

  function OutLine(const str:String): Boolean;
  var curx: Integer;
  begin
//    if cury + th <= DR.Bottom then
//    begin
      if Adjust = 0 then
...  
      Result := False;
//    end;
//    else Result := True;
    cury := cury + th;
  end;

2.         .
 procedure TfrMemoView.ShowMemo ( );

<<>>
  else if (Adjust and $4) <> 0 then OutMemo90 else OutMemo;
<<>>
  else if (Adjust and $4) <> 0 then OutMemo90 else OutMemo;
  IF DocMode = dmDesigning
   Then begin
  IF FillColor = clRed
   Then Canvas.Pen.Color := clYellow
   Else Canvas.Pen.Color := clRed;
  Canvas.Pen.Width := 3;
  IF (Adjust and $4) <> 0
   Then begin { 90}
    IF -Canvas.Font.Height > (DRect.Right - DRect.Left)
     Then begin
      Canvas.MoveTo(DRect.Left,DRect.Top+Round((DRect.Bottom-DRect.Top)/2));
      Canvas.LineTo(DRect.Right,DRect.Top+Round((DRect.Bottom-DRect.Top)/2));
     end
    end Else begin {}
     IF -Canvas.Font.Height > (DRect.Bottom - DRect.Top)
      Then begin
       Canvas.MoveTo(DRect.Left+Round((DRect.Right-DRect.Left)/2),DRect.Top);
       Canvas.LineTo(DRect.Left+Round((DRect.Right-DRect.Left)/2),DRect.Bottom);
      end;
    end;
  end;  
<<Eof>>

3.      
   procedure TfrMemoView.Draw(Canvas:TCanvas);
          ClipRgn : HRGN;
<<>>
  CalcGaps;
  with Canvas do
  begin
    if DrawMode <> drCalcHeight then ShowBackground;
    if Memo1.Count <> 0 then
    begin
      if DrawMode in [drAll, drCalcHeight] then WrapMemo;
      if (DrawMode <> drCalcHeight) and not DisableDrawing then
        ShowMemo;
    end;
    if DrawMode <> drCalcHeight then ShowFrame;
<<>>
  CalcGaps;
  { }
  with DRect
   do ClipRgn := CreateRectRgn(Left, Top, Right, Bottom);
  SelectClipRgn(Canvas.Handle, ClipRgn);
  with Canvas do
  begin
    if DrawMode <> drCalcHeight then ShowBackground;
//    if Memo1.Count <> 0 then
//    begin
      if DrawMode in [drAll, drCalcHeight] then WrapMemo;
      if (DrawMode <> drCalcHeight) and not DisableDrawing then
        ShowMemo;
//    end;
    if DrawMode <> drCalcHeight then ShowFrame;
<<Eof>>

<<>>
  Flags := OldFlags;
end;
<<>>
  Flags := OldFlags;
  {  }
  SelectClipRgn(Canvas.Handle, 0);
  DeleteObject(ClipRgn);
end;
<<Eof>>

,       .

 


>APPL 2.21.4
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
    Date: , 04  1999  12:17:25
   : VVS <VVS@nbank.donetsk.ua>
 : FreeRep@Listbot.com
 : frRichObject
--------------------------------------------------------------------------------

   frRichObject
      p   p "["
     pp: "p  [Hp]"    "p  [56-"
     p p  p:
      fr_Rich  procedure GetRichData re.SelStart:=sum+i-1 
                                       re.SelStart:=sum+i
>ID 14
>VER 2.21.3 25.10.99
>APPL 2.21.3 
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
 Date: , 18  1999  12:34:09
   : "expert1" <EXPERT1@dol.ru>
 : "FreeRep Bag Fix" <FreeRep@listbot.com>
 : Fast Report Fix
--------------------------------------------------------------------------------

FreeReport - http://come.to/belugin

   Alex Bartels  15  1999 14:13.

    08  1999,   
  Ok   .    
. 

<<  FR_BTyp>>
<<  TBandTypesForm.FormCreate>>
<<   >>

 Button1.Left := Round((ClientWidth-Button1.Width)/2); {  Ok}


<< >>

 Button1.Left := 20; {  Ok}

 [  Cancel].Left := ClientWidth - [  Cancel].Width - 20; {  Cancel}


<<Eof>>

Best regards,
 


>ID 13
>APPL 2.21.3
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
 Date: , 15  1999  14:13:41
   : Alex Bartels <alex@msk-garant.ru>
 : FreeReport <FreeRep@listbot.com>
 : FreeReport
--------------------------------------------------------------------------------

FreeReport - http://come.to/belugin

 .


  .
    Band`. (    
,   Band,     ).

 fr_desgn.pas
procedure TPreview.MDown(Sender:TObject; Button:TMouseButton; Shift:TShiftState; X,Y:Integer);

:
 procedure CreateSection;
 begin
  BandTypesForm := TBandTypesForm.Create(nil);
  BandTypesForm.ShowModal
  Objects.Add(TfrBandView.Create);
  t := Objects.Last;
  t.FrameTyp := BandTypesForm.SelectedTyp;
  BandTypesForm.Free;
  SendBandsToDown;
 end;

:

function CreateSection:boolean;
begin
  Result:=False;
  BandTypesForm := TBandTypesForm.Create(nil);
  if BandTypesForm.ShowModal=mrOk then
   begin
    Result:=True;
    Objects.Add(TfrBandView.Create);
    t := Objects.Last;
    t.FrameTyp := BandTypesForm.SelectedTyp;
    BandTypesForm.Free;
    SendBandsToDown;
   end;
end;

 :
  .....
    for i := 0 to ControlCount-1 do
      if Controls[i] is TfrSpeedButton then
      with Controls[i] as TfrSpeedButton do
        if Down then
        begin
          if Tag = gtBand then
            if GetUnusedBand <> btNone then
               CreateSection;
  .....

 :

  .....
    for i := 0 to ControlCount-1 do
      if Controls[i] is TfrSpeedButton then
      with Controls[i] as TfrSpeedButton do
        if Down then
        begin
          if Tag = gtBand then
            if GetUnusedBand <> btNone then
             begin
               if not CreateSection then
                 begin
                  Moved := False;
                  CT := ctNone;
                  DesignerForm.OB1.Down := True;
                  abort;
                 end;
             end
  .....

fr_btyp.dfm   ""

Best regards,
 Alex                          mailto:alex@msk-garant.ru


______________________________________________________________________

>ID 12
>APPL 2.21.3
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
    Date: , 14  1999  13:23:18
   : "expert1" <EXPERT1@dol.ru>
 : "FreeRep Bag Fix" <FreeRep@listbot.com>
 : 
--------------------------------------------------------------------------------

FreeReport - http://come.to/belugin

 ,        
      (
)      .  
  . ...

<<  FR_Class>>
<<  TfrPictureView.Draw>>
{
<<  >>

<< >>
   Var
    ClipRgn : HRGN;
<< EOF >>

<< >> 
  CalcGaps;
<< >> 
  CalcGaps;
  with DRect
   do ClipRgn := CreateRectRgn(Left, Top, Right, Bottom);
  SelectClipRgn(Canvas.Handle, ClipRgn);
<< EOF >>

<< >> 
    ShowFrame;
<< >> 
    SelectClipRgn(Canvas.Handle, 0);
    DeleteObject(ClipRgn);
    ShowFrame;
<< EOF >>
}

 

>ID 11
>VER 2.21.2 17.10.99
>APPL 2.21.2
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
    Date: , 14  1999  13:56:10
   : "Oleg E. Shubarov" <oleg_shubarov@mail.ru>
 : FreeReport <FreeRep@listbot.com>
 : Re:
--------------------------------------------------------------------------------

Hello all,

   bug:    
[SUM([[fData.Q_View."ACNSUMMA"]-[fData.Q_View."SUMMA"]])]
  access vialiation:

fr_class.pas
procedure TfrStdFunctionLibrary.DoFunction(FNo:Integer; p1,p2,p3:Variant;

...  4392 (  2.21.1)
    DataSet := GetDefaultDataSet;
    if dk = dkCount then
      DataSet := frGetDataSet(p1) else
      frGetDataSetAndField(p1, DataSet, Field);
    min := 1e200; max := -1e200; sum := 0; count := 0; avg := 0;
    DataSet.First;
    while not DataSet.EOF do
    begin
      v := 0;
// -------------
      if dk <> dkCount then
        v := Field.AsFloat;      // Field  is null,
                                 //      !
// -------------
      if v > max then max := v;
      if v < min then min := v;
      sum := sum + v;
      count := count + 1;
      DataSet.Next;
    end;

    
// -------------
      if dk <> dkCount then
         if Field<>nil then v:= Field.AsFloat
                       else v:= Parser.Calc(p1);
// -------------


Best regards,
 Oleg Shubarov                  mailto:oleg_shubarov@mail.ru

>ID 10
>APPL 2.21.2
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
    Date: , 12  1999  12:36:18
   : "expert1" <EXPERT1@dol.ru>
 : "FreeRep Bag Fix" <FreeRep@listbot.com>
 : Fast Report bag fix
--------------------------------------------------------------------------------

FreeReport - http://come.to/belugin

<< >>
frToolBar  .      IDE Delphi 3.0 (   4  )  frDock  GPF.     .
      Invalidate.    
  2.21    2.3.
 
 

<<>>
!
 
, .   DoResize   
if csDestroying in ComponentState then Exit

Good luck,
Alexander Tzyganenko

<<Eof>>

MB:
unit: FR_Dock
procedure: TFRToolBar.DoResize
fix: 
{    begin }
if csDestroying in ComponentState then Exit  


______________________________________________________________________
To unsubscribe, write to FreeRep-unsubscribe@listbot.com
Start Your Own FREE Email List at http://www.listbot.com/

>ID 9
>APPL 2.21.2
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
    Date: , 11  1999  20:24:09
   : "expert1" <EXPERT1@dol.ru>
 : "FreeRep Bag Fix" <FreeRep@listbot.com>
 : Fast Report bag fix
--------------------------------------------------------------------------------

FreeReport - http://come.to/belugin

   Konstantin Scheglov
>...    ExpandVariables  
> Memo.  ,    
>  . ...
>
<< : FR_Class>>
<<>>
TfrMemoView.ExpandVariables
<<  Fix>>
    if DocMode <> dmDesigning then GetData(s);
    Memo1.SetText(PChar(s));
<<   >>
    if DocMode <> dmDesigning then GetData(s);
    Memo1.Add(s);
<< >>
    if DocMode <> dmDesigning then GetData(s);
    s := Memo1.GetText + s;
    Memo1.SetText(PChar(S));
<<Eof>>

 

>ID 8
>APPL 2.21.2
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
    Date: , 08  1999  20:31:38
   : "expert1" <EXPERT1@dol.ru>
 : "Max Belugin" <belugin@mail.ru>
 : Info Fast Report
--------------------------------------------------------------------------------

       
(     Language ).
<< : FR_BTyp>>
   TBandTypesForm.FormCreate 
>>
procedure TBandTypesForm.FormCreate(Sender: TObject);
var b: TRadioButton;
    bt: TfrBandType;
    First: Boolean;
    ItemMaxLen : Integer;
Function FindMaxLen : Integer;
Var I : TfrBandType;
begin
  Result := 0;
  For I := btReportTitle to btColumnFooter
   do IF Canvas.TextWidth(frBandNames[Integer(I)]) > Result
    Then Result := Canvas.TextWidth(frBandNames[Integer(I)]);
  Result := Result + 20; {  RadioButton}
end;
begin
  First := True;
  ItemMaxLen := FindMaxLen;
  GB1.ClientWidth := ItemMaxLen * 2 + 12*2 + 30;   { 
GroupBox}
  ClientWidth := GB1.Width + GB1.Left * 2;         {  
}
  Button1.Left := Round((ClientWidth-Button1.Width)/2); {  Ok}
  for bt := btReportTitle to btColumnFooter do
  begin
    b := TRadioButton.Create(GB1);
    b.Parent := GB1;
    if Integer(bt) > 10 then
    begin
      b.Left := ItemMaxLen + 12 + 30;
      b.Top := (Integer(bt)-11)*20+20;
    end
    else
    begin
      b.Left := 12;
      b.Top := Integer(bt)*20+20;
    end;
    b.Width := Canvas.TextWidth(frBandNames[Integer(bt)])+20;
    b.Tag := Integer(bt);
    b.Caption := frBandNames[Integer(bt)];
    b.OnClick := bClick;
    b.Enabled := (bt in [btMasterData,btDetailData,btSubDetailData,
      btGroupHeader,btGroupFooter]) or not frCheckBand(bt);
    if b.Enabled and First then
    begin
      b.Checked := True;
      SelectedTyp := Integer(bt);
      First := False;
    end;
  end;
end;
<<Eof>>
 

>ID 7
>APPL 2.21.2
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
    Date: , 08  1999  14:32:40
   : "expert1" <EXPERT1@dol.ru>
 : "Max Belugin" <belugin@mail.ru>
 : Info Fast Report
--------------------------------------------------------------------------------

    Band.

,     100   ,
       (.. 
  Language ). Fix ...

1.     TfrBandView
<< : FR_Class>>
<<>>

<<>>
private
     function GetRectangleWidth : Integer;
 .
 .
{   }
function TfrBandView.GetRectangleWidth : Integer;
 begin
  with TCanvas.Create do
   begin
    Handle := GetDC(0);
    Font.Name := 'Arial';
    Font.Style := [];
    Font.Size := 8;
    Result := TextWidth(frBandNames[FrameTyp])+8; {4+4   }
    ReleaseDC(0, Handle);
    Free;
   end;
 end;
<<Eof>>

<< : FR_Class>>
<<>>
function TfrBandView.GetClipRgn(rt:TfrRgnType): HRGN;
.
.
  if TfrBandType(FrameTyp) in [btColumnHeader..btColumnFooter] then
    R := CreateRectRgn(x-18, y, x, y+100)
  else
    R := CreateRectRgn(x, y-18, x+100, y);
<<>>
function TfrBandView.GetClipRgn(rt:TfrRgnType): HRGN;
.
.
  if TfrBandType(FrameTyp) in [btColumnHeader..btColumnFooter] then
    R := CreateRectRgn(x-18, y, x, y+GetRectangleWidth)
  else
    R := CreateRectRgn(x, y-18, x+GetRectangleWidth, y);
<<Eof>>

<< : FR_Class>>
<<>>
procedure TfrBandView.Draw(Canvas:TCanvas);
.
.
    Brush.Color := clBtnFace;
    if TfrBandType(FrameTyp) in [btColumnHeader..btColumnFooter] then
    begin
      FillRect(Rect(x-18, y, x, y+100));
      Pen.Color := clBtnShadow;
      MoveTo(x-18, y+98); LineTo(x, y+98);
      Pen.Color := clBlack;
      MoveTo(x-18, y+99); LineTo(x, y+99);
      Pen.Color := clBtnHighlight;
      MoveTo(x-18, y+99); LineTo(x-18, y);
      h := Create90Font(Font);
      oldh := SelectObject(Handle, h);
      TextOut(x-15, y+TextWidth(frBandNames[FrameTyp])+4,
frBandNames[FrameTyp]);
      SelectObject(Handle, oldh);
      DeleteObject(h);
    end
    else
    begin
      FillRect(Rect(x, y-18, x+100, y));
      Pen.Color := clBtnShadow;
      MoveTo(x+98, y-18); LineTo(x+98, y);
      Pen.Color := clBlack;
      MoveTo(x+99, y-18); LineTo(x+99, y);
      TextOut(x+4, y-17, frBandNames[FrameTyp]);
    end;
<<>>
procedure TfrBandView.Draw(Canvas:TCanvas);
var RWidth : Integer;
.
.
    Brush.Color := clBtnFace;
    RWidth := GetRectangleWidth;
    if TfrBandType(FrameTyp) in [btColumnHeader..btColumnFooter] then
    begin
      FillRect(Rect(x-18, y, x, y+RWidth));
      Pen.Color := clBtnShadow;
      MoveTo(x-18, y+RWidth-2); LineTo(x, y+RWidth-2);
      Pen.Color := clBlack;
      MoveTo(x-18, y+RWidth-1); LineTo(x, y+RWidth-1);
      Pen.Color := clBtnHighlight;
      MoveTo(x-18, y+RWidth-1); LineTo(x-18, y);
      h := Create90Font(Font);
      oldh := SelectObject(Handle, h);
      TextOut(x-15, y+TextWidth(frBandNames[FrameTyp])+4,
frBandNames[FrameTyp]);
      SelectObject(Handle, oldh);
      DeleteObject(h);
    end
    else
    begin
      FillRect(Rect(x, y-18, x+RWidth, y));
      Pen.Color := clBtnShadow;
      MoveTo(x+RWidth-2, y-18); LineTo(x+RWidth-2, y);
      Pen.Color := clBlack;
      MoveTo(x+RWidth-1, y-18); LineTo(x+RWidth-1, y);
      TextOut(x+4, y-17, frBandNames[FrameTyp]);
    end;
<<Eof>>

 

>VER  2.21.1 07.10.99
>ID 5
>APPL 2.21.1
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
    Date: , 07  1999  14:11:36
   : "expert1" <EXPERT1@dol.ru>
 : "Max Belugin" <belugin@mail.ru>
 : Info Fast Report
--------------------------------------------------------------------------------

  3-    Fast Report 2.2
1.        
 -   . 
,      OnGetText
      Field.Text.
2.       ,
   GPF     .
<< FR_Class>>
<<  >>
        vtDBField:
           v := DField.AsVariant;
<<  >>
        vtDBField:
         IF Assigned(DField)
          Then begin
          IF DField.FieldKind = fkCalculated
           Then v := DField.Text
           Else v := DField.AsVariant;
          end Else v := ' ';
<<Eof>>
3.        , 
 ,  Exception   . .
<< FR_Class>>
<<  >>
procedure TfrReport.PrepareDataSets;
 .
 .
      DSet := frGetDataSet(DataSet);
      DField := DSet.FieldByName(Field);
      if DField.DataType in [ftBlob..ftTypedBinary] then HasBlobs := True;
<<>>
procedure TfrReport.PrepareDataSets;
 .
 .
      DSet := frGetDataSet(DataSet);
      if Assigned(DSet)
       Then begin
        DField := DSet.FindField(Field);
        IF Assigned(DField)
         Then if DField.DataType in [ftBlob..ftTypedBinary] then HasBlobs :=
True;
       end Else DField := Nil;
<< Eof >>


 
>ID 4
>APPL 2.21.1
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
    Date: , 06  1999  15:41:45
   : "expert1" <EXPERT1@dol.ru>
 : "Max Belugin" <belugin@mail.ru>
 : Info Fast Report
--------------------------------------------------------------------------------

     FR.lng
  Windows .    
    ,   Windows    
System.
<<  : FR_Utils>>
<<  >>
procedure CreateIniFile;
begin
  Ini := TIniFile.Create('FR.lng');
end;
<<>>
procedure CreateIniFile;
Const
    SysBufSize = 144;
    INILangFile = 'FR.lng';
Var InILangPath : String;
    SysDir      : PChar;
Function AddFlash(Const Path : ShortString) : ShortString;
 begin
  Result:=Path;
  IF Result[Length(Result)] <> '\'
   Then Result:=Result+'\';
 end;
begin
 {   }
 GetMem(SysDir,SysBufSize);
 InILangPath := AddFlash(ExtractFilePath(Application.ExeName))+INILangFile;
 IF not FileExists(InILangPath)
  Then begin
   {   Windows}
   GetWindowsDirectory(SysDir, SysBufSize);
   InILangPath := AddFlash(StrPas(SysDir))+INILangFile;
   IF not FileExists(InILangPath)
    Then begin
     {   System}
     GetSystemDirectory(SysDir, SysBufSize);
     InILangPath := AddFlash(StrPas(SysDir))+INILangFile;
    end; {Else INI  }
  end;
 Ini := TIniFile.Create(InILangPath);
 FreeMem(SysDir,SysBufSize);
end;
<<Eof>>
 
>ID 3
>APPL 2.21.1
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
    Date: , 06  1999  10:26:04
   : "expert1" <EXPERT1@dol.ru>
 : "Max Belugin" <belugin@mail.ru>
 : Info Fast Report
--------------------------------------------------------------------------------

  Fast Report 2.2  :

1.     Memo    
  .    TfrMemoView.ExpandVariables
  Memo1 .
<<  >>
    if DocMode <> dmDesigning then GetData(s);
    Memo1.Add(s);
<<>>
    if DocMode <> dmDesigning then GetData(s);
    Memo1.SetText(PChar(s));

 

--------------------------------------------------------------------------
>ID 2
>APPL 2.21.1 ( library path)
From:
                                                                     12:00
Subject: Re: DX.REP FastReport 2.3

I'm glad to see you, Vladimir!

 [10  99 10:27], [Vladimir Shalimov] -> [All]:

 > ,   2.21  D5 ?

        2.21?   fr_vers.inc {$ifdef ver130}{$define delphi4}{$endif} 
.       library path $(delphi)/src/toolsapi ( 
  DsgnIntf)

... "OS/2 will be the platform of the 90's." -- (q) Bill Gates, 1989

------------------------------------------------------------------------------
ID: 1
State: APPLied 2.21.1
Auth: Michael aka Matador
Mail: matador@cityline.ru
Type: -
Desc: 

.
   p  p,   numeric- p 
"",     (  p,     Null-). 
,    SUM   ,  "Invalid variant
type conversion".     fr_class, procedure
TfrStdFunctionLibrary.DoFunction:

  ,  

      if dk <> dkCount then
        d := Parser.Calc(p1);

   

      if dk <> dkCount then
      begin
        vv := Parser.Calc(p1);
        if VarType(vv) = varNull then d:=0 else d:=vv;
      end;

   vv:variant.

      .
           Michael aka Matador                  [2:5020/1252.0 & .152]
                                                [matador@cityline.ru]
                                                [UIN: 9550050]
---------------------------------------------------------------------------
ID: 0
state: applied 2.21.1
Auth: Max Belugin
Mail: belugin@mail.ru
Type: -
Desc: Exception occured while converting to text

Unit: FR_EText
Func: TfrTextExportFilter.OnEndPage;"
Was:
  while (Lines[i] = '') do
Fix:
  while (Lines[i] = '') and (i>0)do
