Browse Source

Copied over from my fpc_patch_playground repository. See latest commit messages for changes versus Jepafi's version.

Reinier Olislagers 10 years ago
commit
8d61dcf063
27 changed files with 5439 additions and 0 deletions
  1. BIN
      EMPLOYEE.FDB
  2. 53 0
      EMPLOYEE.qb
  3. BIN
      Help/QBuilder.chm
  4. 76 0
      QBAbout.lfm
  5. 59 0
      QBAbout.pas
  6. BIN
      QBBUTTON.RES
  7. 93 0
      QBDBFrm.lfm
  8. 74 0
      QBDBFrm.pas
  9. 94 0
      QBDBFrm2.lfm
  10. 62 0
      QBDBFrm2.pas
  11. 70 0
      QBDirFrm.lfm
  12. 75 0
      QBDirFrm.pas
  13. 136 0
      QBEIBX.pas
  14. 155 0
      QBESqlDb.pas
  15. 187 0
      QBEZEOS.pas
  16. 192 0
      QBLnkFrm.lfm
  17. 57 0
      QBLnkFrm.pas
  18. 1061 0
      QBuilder.lfm
  19. 2489 0
      QBuilder.pas
  20. 65 0
      license.txt
  21. BIN
      project1.ico
  22. 153 0
      project1.lpi
  23. 32 0
      project1.lpr
  24. BIN
      project1.res
  25. 58 0
      readme.txt
  26. 37 0
      unit1.lfm
  27. 161 0
      unit1.pas

BIN
EMPLOYEE.FDB


+ 53 - 0
EMPLOYEE.qb

@@ -0,0 +1,53 @@
+# QBuilder
+# Don't change this file !
+[Options]
++
+1,174,1,169;
+[Database]
+EMPLOYEE.FDB,0;
+[Tables]
+PROJ_DEPT_BUDGET,283,899,0,1,0,0,1,0;
+JOB,320,704,0,1,1,1,0,0,0,0,0;
+DEPARTMENT,117,723,0,0,1,1,0,0,0,0;
+COUNTRY,394,6,0,0,1;
+PHONE_LIST,192,6,0,0,1,1,0,0,0;
+EMPLOYEE,25,534,0,0,1,1,1,0,0,0,0,0,0,0;
+SALES,204,371,0,0,0,1,1,1,0,0,0,0,0,0,0,0;
+SALARY_HISTORY,9,115,0,0,1,1,0,0,0;
+CUSTOMER,248,187,0,0,1,1,1,0,0,0,0,0,0,0,0;
+EMPLOYEE_PROJECT,10,754,0,0,0;
+PROJECT,11,971,0,0,0,0,0,0;
+[Links]
+SALES,2,CUSTOMER,8,0,0;
+EMPLOYEE,2,PHONE_LIST,1,0,0;
+EMPLOYEE,2,SALARY_HISTORY,2,0,0;
+CUSTOMER,6,COUNTRY,1,0,0;
+JOB,1,EMPLOYEE,6,0,0;
+DEPARTMENT,3,EMPLOYEE,1,0,0;
+EMPLOYEE_PROJECT,1,EMPLOYEE,2,0,0;
+EMPLOYEE_PROJECT,2,PROJECT,3,0,0;
+PROJ_DEPT_BUDGET,1,DEPARTMENT,3,0,0;
+PROJ_DEPT_BUDGET,4,PROJECT,3,0,0;
+[Columns]
+1,CHANGE_DATE,SALARY_HISTORY,Show,,,;
+2,UPDATER_ID,SALARY_HISTORY,Show,,,;
+3,FIRST_NAME,PHONE_LIST,Show,,,;
+4,LAST_NAME,PHONE_LIST,Show,,,;
+5,CURRENCY,COUNTRY,Show,Asc,,;
+6,CUSTOMER,CUSTOMER,Show,,,;
+7,CONTACT_FIRST,CUSTOMER,Show,,,;
+8,CONTACT_LAST,CUSTOMER,Show,,,;
+9,FIRST_NAME,EMPLOYEE,Show,,,;
+10,LAST_NAME,EMPLOYEE,Show,,,;
+11,PHONE_EXT,EMPLOYEE,Show,,,;
+12,SALES_REP,SALES,Show,,,;
+13,ORDER_STATUS,SALES,Show,,,;
+14,ORDER_DATE,SALES,Show,,,;
+15,JOB_CODE,JOB,Show,,,;
+16,JOB_GRADE,JOB,Show,,,;
+17,JOB_COUNTRY,JOB,Show,,,;
+18,DEPARTMENT,DEPARTMENT,Show,,,;
+19,HEAD_DEPT,DEPARTMENT,Show,,,;
+20,FISCAL_YEAR,PROJ_DEPT_BUDGET,Show,,,;
+21,PROJECTED_BUDGET,PROJ_DEPT_BUDGET,Show,,,;
+[End]

BIN
Help/QBuilder.chm


+ 76 - 0
QBAbout.lfm

@@ -0,0 +1,76 @@
+object OQBAboutForm: TOQBAboutForm
+  Left = 428
+  Height = 141
+  Top = 205
+  Width = 251
+  BorderIcons = [biSystemMenu]
+  BorderStyle = bsDialog
+  Caption = 'About'
+  ClientHeight = 141
+  ClientWidth = 251
+  Color = clBtnFace
+  Font.Color = clWindowText
+  Font.Height = -11
+  Font.Name = 'Tahoma'
+  Position = poScreenCenter
+  LCLVersion = '1.0.6.0'
+  object Bevel1: TBevel
+    Left = 0
+    Height = 141
+    Top = 0
+    Width = 251
+    Align = alClient
+    Style = bsRaised
+  end
+  object Label1: TLabel
+    Left = 35
+    Height = 40
+    Top = 8
+    Width = 180
+    Caption = 'Open QBuilder'
+    Font.Color = clNavy
+    Font.Height = -31
+    Font.Name = 'Impact'
+    ParentColor = False
+    ParentFont = False
+  end
+  object Label3: TLabel
+    Left = 36
+    Height = 14
+    Top = 51
+    Width = 181
+    Caption = 'Copyright © Sergey Orlik, 1996-2003'
+    ParentColor = False
+  end
+  object Label5: TLabel
+    Left = 38
+    Height = 12
+    Top = 93
+    Width = 175
+    Caption = 'http://www.fast-report.com/en/qbuilder.php'
+    Font.Color = clWindowText
+    Font.Height = -9
+    Font.Name = 'Small Fonts'
+    ParentColor = False
+    ParentFont = False
+  end
+  object Label2: TLabel
+    Left = 36
+    Height = 14
+    Top = 67
+    Width = 179
+    Caption = 'Copyright © Fast Reports, Inc. 2003'
+    ParentColor = False
+  end
+  object Ok: TButton
+    Left = 80
+    Height = 20
+    Top = 111
+    Width = 85
+    Cancel = True
+    Caption = 'Ok'
+    Default = True
+    ModalResult = 1
+    TabOrder = 0
+  end
+end

+ 59 - 0
QBAbout.pas

@@ -0,0 +1,59 @@
+{*******************************************************}
+{                                                       }
+{       Delphi Visual Component Library                 }
+{       QBuilder dialog component                       }
+{                                                       }
+{       Copyright (c) 1996-2003 Sergey Orlik            }
+{                                                       }
+{     Written by:                                       }
+{       Sergey Orlik                                    }
+{       product manager                                 }
+{       Russia, C.I.S. and Baltic States (former USSR)  }
+{       Borland Moscow office                           }
+{       Internet:  [email protected],             }
+{                  [email protected]                   }
+{                  http://www.fast-report.com           }
+{                                                       }
+{ Converted to Lazarus/Free Pascal by Jean Patrick      }
+{ Data: 14/02/2013                                      }
+{ E-mail: [email protected]                     }
+{                                                       }
+{*******************************************************}
+
+unit QBAbout;
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+
+
+interface
+
+uses
+  Forms,
+  StdCtrls, ExtCtrls, LMessages, LCLType;
+
+type
+  TOQBAboutForm = class(TForm)
+    Bevel1: TBevel;
+    Ok: TButton;
+    Label1: TLabel;
+    Label3: TLabel;
+    Label5: TLabel;
+    Label2: TLabel;
+    procedure WMNCHitTest(var Message :TLMNCHITTEST); message LM_NCHITTEST;
+  end;
+
+implementation
+
+  {$R *.lfm}
+
+procedure TOQBAboutForm.WMNCHitTest(var Message: TLMNCHITTEST);
+begin
+  inherited;
+  if Message.Result = htClient then
+    Message.Result := htCaption;
+end;
+
+end.

BIN
QBBUTTON.RES


+ 93 - 0
QBDBFrm.lfm

@@ -0,0 +1,93 @@
+object OQBDBForm: TOQBDBForm
+  Left = 537
+  Height = 147
+  Top = 250
+  Width = 249
+  BorderIcons = [biSystemMenu]
+  BorderStyle = bsDialog
+  Caption = 'Select Database'
+  ClientHeight = 147
+  ClientWidth = 249
+  Color = clBtnFace
+  Font.Color = clWindowText
+  Font.Height = -11
+  Font.Name = 'Tahoma'
+  Position = poScreenCenter
+  LCLVersion = '1.0.6.0'
+  object Bevel1: TBevel
+    Left = 1
+    Height = 118
+    Top = 1
+    Width = 248
+    Shape = bsFrame
+  end
+  object Label1: TLabel
+    Left = 13
+    Height = 14
+    Top = 7
+    Width = 62
+    Caption = 'Select Alias :'
+    ParentColor = False
+  end
+  object Label2: TLabel
+    Left = 13
+    Height = 14
+    Top = 46
+    Width = 67
+    Caption = 'Or Directory :'
+    ParentColor = False
+  end
+  object BtnOk: TButton
+    Left = 119
+    Height = 20
+    Top = 124
+    Width = 61
+    Caption = '&Ok'
+    Default = True
+    ModalResult = 1
+    TabOrder = 0
+  end
+  object BtnCancel: TButton
+    Left = 186
+    Height = 20
+    Top = 124
+    Width = 59
+    Cancel = True
+    Caption = '&Cancel'
+    ModalResult = 2
+    TabOrder = 1
+  end
+  object ComboDB: TComboBox
+    Left = 13
+    Height = 21
+    Top = 20
+    Width = 222
+    ItemHeight = 13
+    Style = csDropDownList
+    TabOrder = 2
+  end
+  object CheckDB: TCheckBox
+    Left = 13
+    Height = 19
+    Top = 91
+    Width = 223
+    Caption = 'Include System Tables (for SQL-database)'
+    TabOrder = 3
+  end
+  object EdtDir: TEdit
+    Left = 13
+    Height = 21
+    Top = 59
+    Width = 202
+    TabOrder = 4
+  end
+  object btnDir: TButton
+    Left = 215
+    Height = 20
+    Top = 59
+    Width = 20
+    Caption = '...'
+    OnClick = btnDirClick
+    TabOrder = 5
+  end
+end

+ 74 - 0
QBDBFrm.pas

@@ -0,0 +1,74 @@
+{*******************************************************}
+{                                                       }
+{       Delphi Visual Component Library                 }
+{       QBuilder dialog component                       }
+{                                                       }
+{       Copyright (c) 1996-2003 Sergey Orlik            }
+{                                                       }
+{     Written by:                                       }
+{       Sergey Orlik                                    }
+{       product manager                                 }
+{       Russia, C.I.S. and Baltic States (former USSR)  }
+{       Borland Moscow office                           }
+{       Internet:  [email protected],             }
+{                  [email protected]                   }
+{                  http://www.fast-report.com           }
+{                                                       }
+{ Converted to Lazarus/Free Pascal by Jean Patrick      }
+{ Data: 14/02/2013                                      }
+{ E-mail: [email protected]                     }
+{                                                       }
+{*******************************************************}
+
+unit QBDBFrm;
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+
+
+interface
+
+uses
+  Controls, Forms,
+  StdCtrls, ExtCtrls;
+
+type
+  TOQBDBForm = class(TForm)
+    BtnOk: TButton;
+    BtnCancel: TButton;
+    Bevel1: TBevel;
+    ComboDB: TComboBox;
+    CheckDB: TCheckBox;
+    EdtDir: TEdit;
+    btnDir: TButton;
+    Label1: TLabel;
+    Label2: TLabel;
+    procedure btnDirClick(Sender: TObject);
+  end;
+
+
+implementation
+
+  {$R *.lfm}
+
+uses
+  QBDirFrm;
+
+
+procedure TOQBDBForm.btnDirClick(Sender: TObject);
+var
+  QBDirForm: TOQBDirForm;
+  s: string;
+begin
+  s := '';
+  QBDirForm := TOQBDirForm.Create(Application);
+  GetDir(0, s);
+  QBDirForm.Directory := s;
+  if QBDirForm.ShowModal = mrOk then
+    EdtDir.Text := QBDirForm.Directory;
+  QBDirForm.Free;
+end;
+
+end.

+ 94 - 0
QBDBFrm2.lfm

@@ -0,0 +1,94 @@
+object OQBDBForm2: TOQBDBForm2
+  Left = 656
+  Height = 126
+  Top = 270
+  Width = 248
+  BorderIcons = [biSystemMenu]
+  BorderStyle = bsSingle
+  Caption = 'Select Database'
+  ClientHeight = 126
+  ClientWidth = 248
+  Color = clBtnFace
+  Font.Color = clWindowText
+  Font.Height = -11
+  Font.Name = 'Tahoma'
+  Position = poScreenCenter
+  LCLVersion = '1.3'
+  object Bevel1: TBevel
+    Left = 0
+    Height = 97
+    Top = 0
+    Width = 248
+    Shape = bsFrame
+  end
+  object Label1: TLabel
+    Left = 13
+    Height = 13
+    Top = 6
+    Width = 85
+    Caption = 'Select Database :'
+    ParentColor = False
+  end
+  object BtnOk: TButton
+    Left = 119
+    Height = 20
+    Top = 104
+    Width = 61
+    Caption = '&Ok'
+    Default = True
+    ModalResult = 1
+    TabOrder = 0
+  end
+  object BtnCancel: TButton
+    Left = 186
+    Height = 20
+    Top = 104
+    Width = 59
+    Cancel = True
+    Caption = '&Cancel'
+    ModalResult = 2
+    TabOrder = 1
+  end
+  object CheckDB: TCheckBox
+    Left = 13
+    Height = 17
+    Top = 71
+    Width = 127
+    Caption = 'Include System Tables'
+    TabOrder = 2
+  end
+  object EdtDB: TEdit
+    Left = 13
+    Height = 21
+    Top = 19
+    Width = 202
+    TabOrder = 3
+  end
+  object btnDir: TButton
+    Left = 215
+    Height = 20
+    Top = 19
+    Width = 20
+    Caption = '...'
+    OnClick = btnDbClick
+    TabOrder = 4
+  end
+  object CheckView: TCheckBox
+    Left = 13
+    Height = 17
+    Top = 51
+    Width = 85
+    Caption = 'Include Views'
+    Checked = True
+    State = cbChecked
+    TabOrder = 5
+  end
+  object DlgSelect: TOpenDialog
+    Title = 'Select Database'
+    DefaultExt = '.*.gdb'
+    Filter = 'InterBase database (*.gdb)|*.gdb|All Files (*.*)|*.*'
+    Options = [ofHideReadOnly, ofPathMustExist, ofFileMustExist, ofEnableSizing]
+    left = 184
+    top = 48
+  end
+end

+ 62 - 0
QBDBFrm2.pas

@@ -0,0 +1,62 @@
+{*******************************************************}
+{                                                       }
+{       Delphi Visual Component Library                 }
+{       QBuilder dialog component                       }
+{                                                       }
+{       Copyright (c) 1996-2003 Sergey Orlik            }
+{                                                       }
+{     Written by:                                       }
+{       Sergey Orlik                                    }
+{       product manager                                 }
+{       Russia, C.I.S. and Baltic States (former USSR)  }
+{       Borland Moscow office                           }
+{       Internet:  [email protected],             }
+{                  [email protected]                   }
+{                  http://www.fast-report.com           }
+{                                                       }
+{*******************************************************}
+
+unit QBDBFrm2;
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+
+
+interface
+
+uses
+  Forms, Dialogs,
+  StdCtrls, ExtCtrls;
+
+type
+  TOQBDBForm2 = class(TForm)
+    BtnOk: TButton;
+    BtnCancel: TButton;
+    Bevel1: TBevel;
+    CheckDB: TCheckBox;
+    EdtDB: TEdit;
+    btnDir: TButton;
+    Label1: TLabel;
+    DlgSelect: TOpenDialog;
+    CheckView: TCheckBox;
+    procedure btnDbClick(Sender: TObject);
+  end;
+
+
+implementation
+
+  {$R *.lfm}
+
+procedure TOQBDBForm2.btnDbClick(Sender: TObject);
+var
+  s: string;
+begin
+  GetDir(0, s);
+  DlgSelect.InitialDir := s;
+  if DlgSelect.Execute then
+    EdtDB.Text := DlgSelect.FileName;
+end;
+
+end.

+ 70 - 0
QBDirFrm.lfm

@@ -0,0 +1,70 @@
+object OQBDirForm: TOQBDirForm
+  Left = 687
+  Height = 208
+  Top = 282
+  Width = 300
+  BorderIcons = [biSystemMenu]
+  BorderStyle = bsDialog
+  Caption = 'Select Directory'
+  ClientHeight = 208
+  ClientWidth = 300
+  Color = clBtnFace
+  Font.Color = clWindowText
+  Font.Height = -11
+  Font.Name = 'Tahoma'
+  Position = poScreenCenter
+  LCLVersion = '1.0.6.0'
+  object Bevel: TBevel
+    Left = 1
+    Height = 180
+    Top = 1
+    Width = 298
+    Shape = bsFrame
+  end
+  object BtnOk: TButton
+    Left = 167
+    Height = 20
+    Top = 184
+    Width = 61
+    Caption = '&Ok'
+    Default = True
+    ModalResult = 1
+    TabOrder = 0
+  end
+  object BtnCancel: TButton
+    Left = 234
+    Height = 20
+    Top = 184
+    Width = 59
+    Cancel = True
+    Caption = '&Cancel'
+    ModalResult = 2
+    TabOrder = 1
+  end
+  object FileLbx: TFileListBox
+    Left = 8
+    Height = 133
+    Top = 40
+    Width = 285
+    Directory = 'C:\oqb401_LAZARUS'
+    ExtendedSelect = False
+    Font.Color = clInactiveCaption
+    Font.Height = -11
+    Font.Name = 'MS Sans Serif'
+    ItemHeight = 0
+    Mask = '*.db;*.dbf;*.txt'
+    ParentFont = False
+    TabOrder = 2
+  end
+  object DirLbx: TDirectoryEdit
+    Left = 8
+    Height = 21
+    Top = 8
+    Width = 261
+    ShowHidden = False
+    ButtonWidth = 23
+    NumGlyphs = 0
+    MaxLength = 0
+    TabOrder = 3
+  end
+end

+ 75 - 0
QBDirFrm.pas

@@ -0,0 +1,75 @@
+{*******************************************************}
+{                                                       }
+{       Delphi Visual Component Library                 }
+{       QBuilder dialog component                       }
+{                                                       }
+{       Copyright (c) 1996-2003 Sergey Orlik            }
+{                                                       }
+{     Written by:                                       }
+{       Sergey Orlik                                    }
+{       product manager                                 }
+{       Russia, C.I.S. and Baltic States (former USSR)  }
+{       Borland Moscow office                           }
+{       Internet:  [email protected],             }
+{                  [email protected]                   }
+{                  http://www.fast-report.com           }
+{                                                       }
+{ Converted to Lazarus/Free Pascal by Jean Patrick      }
+{ Data: 14/02/2013                                      }
+{ E-mail: [email protected]                     }
+{                                                       }
+{*******************************************************}
+
+unit QBDirFrm;
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+
+
+interface
+
+uses
+  Forms,
+  StdCtrls, ExtCtrls, FileCtrl, EditBtn;
+
+type
+
+  { TOQBDirForm }
+
+  TOQBDirForm = class(TForm)
+    BtnOk: TButton;
+    BtnCancel: TButton;
+    Bevel: TBevel;
+    DirLbx: TDirectoryEdit;
+    FileLbx: TFileListBox;
+    procedure DirLbxChange(Sender: TObject);
+  private
+    procedure SetDir(aDir: string);
+    function GetDir: string;
+  public
+    property Directory: string read GetDir write SetDir;
+  end;
+
+
+implementation
+
+  {$R *.lfm}
+
+procedure TOQBDirForm.SetDir(aDir: string);
+begin
+  DirLbx.Directory := aDir;
+end;
+
+function TOQBDirForm.GetDir: string;
+begin
+  Result := DirLbx.Directory;
+end;
+
+procedure TOQBDirForm.DirLbxChange(Sender: TObject);
+begin
+  FileLbx.Directory := DirLbx.Directory;
+end;
+
+end.

+ 136 - 0
QBEIBX.pas

@@ -0,0 +1,136 @@
+{*******************************************************}
+{                                                       }
+{       Delphi Visual Component Library                 }
+{       Open QBuilder Engine for IBX Sources            }
+{                                                       }
+{       Copyright (c) 2003 Fast Reports, Inc.           }
+{                                                       }
+{ Adapted to Lazarus by Reinier Olislagers October 2014 }
+{*******************************************************}
+
+//untested: ibx users, please test!
+
+unit QBEIBX;
+
+interface
+
+uses
+  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
+  StdCtrls, ExtCtrls, DB, IBDatabase, IBQuery, QBuilder;
+
+type
+  TOQBEngineIBX = class(TOQBEngine)
+  private
+    FResultQuery: TIBQuery;
+    FIBXConnection : TIBDatabase;
+    FTransaction : TIBTransaction;
+  public
+    constructor Create(AOwner: TComponent); override;
+    destructor Destroy; override;
+    procedure ClearQuerySQL; override;
+    procedure CloseResultQuery; override;
+    procedure OpenResultQuery; override;
+    procedure ReadFieldList(const ATableName: string); override;
+    procedure ReadTableList; override;
+    procedure SaveResultQueryData; override;
+    procedure SetConnection(Value: TIBDatabase);
+    procedure SetQuerySQL(const Value: string); override;
+    function ResultQuery: TDataSet; override;
+    function SelectDatabase: Boolean; override;
+    procedure Notification(AComponent: TComponent; Operation: TOperation); override;
+  published
+    // Breaking change: used to be DatabaseName
+    property Connection: TIBDatabase read FIBXConnection write SetConnection;
+  end;
+
+implementation
+
+{ TOQBEngineIBX }
+
+constructor TOQBEngineIBX.Create(AOwner: TComponent);
+begin
+  inherited;
+  FResultQuery := TIBQuery.Create(Self);
+  FTransaction := TIBTransaction.Create(Self);
+  FResultQuery.Transaction := FTransaction;
+end;
+
+destructor TOQBEngineIBX.Destroy;
+begin
+  FResultQuery.Free;
+  FTransaction.Free;
+  inherited;
+end;
+
+procedure TOQBEngineIBX.SetConnection(Value: TIBDatabase);
+begin
+  FIBXConnection := Value;
+  FResultQuery.Database := Value;
+end;
+
+function TOQBEngineIBX.SelectDatabase: Boolean;
+begin
+  Result := True;
+end;
+
+procedure TOQBEngineIBX.ReadTableList;
+begin
+  TableList.Clear;
+  FResultQuery.Database.GetTableNames(TableList, ShowSystemTables);
+end;
+
+procedure TOQBEngineIBX.ReadFieldList(const ATableName: string);
+begin
+  FieldList.Clear;
+  FResultQuery.Database.GetFieldNames(ATableName, FieldList);
+  FieldList.Insert(0, '*');
+end;
+
+procedure TOQBEngineIBX.ClearQuerySQL;
+begin
+  FResultQuery.SQL.Clear;
+end;
+
+procedure TOQBEngineIBX.SetQuerySQL(const Value: string);
+begin
+  FResultQuery.SQL.Text := Value;
+end;
+
+function TOQBEngineIBX.ResultQuery: TDataSet;
+begin
+  Result := FResultQuery;
+end;
+
+procedure TOQBEngineIBX.OpenResultQuery;
+begin
+  FTransaction.DefaultDatabase := FIBXConnection;
+  FTransaction.Active := True;
+  FResultQuery.Open;
+end;
+
+procedure TOQBEngineIBX.CloseResultQuery;
+begin
+  FResultQuery.Close;
+end;
+
+{$WARNINGS OFF}
+procedure TOQBEngineIBX.SaveResultQueryData;
+begin
+//
+end;
+{$WARNINGS ON}
+
+procedure TOQBEngineIBX.Notification(AComponent: TComponent;
+  Operation: TOperation);
+begin
+  inherited;
+  if (AComponent = FIBXConnection) and (Operation = opRemove) then
+  begin
+    FIBXCOnnection := nil;
+    FResultQuery.Database := nil;
+  end;
+end;
+
+
+end.
+

+ 155 - 0
QBESqlDb.pas

@@ -0,0 +1,155 @@
+{*******************************************************}
+{                                                       }
+{       Open QBuilder Engine for SQLDB Sources          }
+{                Lazarus / Free Pascal                  }
+{                                                       }
+{ Created by Reinier Olislagers                         }
+{ Data: October 2014                                    }
+{                                                       }
+{*******************************************************}
+
+unit QBESqlDb;
+
+interface
+
+uses
+  SysUtils, Classes, DB, sqldb, QBuilder;
+
+type
+
+  { TOQBEngineSqlDB }
+
+  TOQBEngineSqlDB = class(TOQBEngine)
+    procedure FResultQueryAfterOpen(DataSet: TDataSet);
+    procedure GridMemoFieldGetText(Sender: TField; var aText: string;
+      {%H-}DisplayText: Boolean);
+  private
+    FResultQuery: TSQLQuery;
+    FSqlDBConnection : TSQLConnection;
+  public
+    constructor Create(AOwner: TComponent); override;
+    destructor Destroy; override;
+    procedure ClearQuerySQL; override;
+    procedure CloseResultQuery; override;
+    procedure OpenResultQuery; override;
+    procedure ReadFieldList(const ATableName: string); override;
+    procedure ReadTableList; override;
+    procedure SaveResultQueryData; override;
+    procedure SetConnection(Value: TSQLConnection);
+    procedure SetQuerySQL(const Value: string); override;
+    function ResultQuery: TDataSet; override;
+    function SelectDatabase: Boolean; override;
+    procedure Notification(AComponent: TComponent; Operation: TOperation); override;
+  published
+    property Connection: TSQLConnection read FSqlDBConnection write SetConnection;
+  end;
+
+implementation
+
+{ TOQBEngineSqlDB }
+
+procedure TOQBEngineSqlDB.FResultQueryAfterOpen(DataSet: TDataSet);
+var
+  i: Integer;
+begin
+  for i := 0 to DataSet.Fields.Count - 1 do
+  begin
+    if DataSet.Fields[i].DataType = ftMemo then
+    begin
+      DataSet.Fields[i].OnGetText := @GridMemoFieldGetText;
+    end;
+  end;
+end;
+
+procedure TOQBEngineSqlDB.GridMemoFieldGetText(Sender: TField;
+  var aText: string; DisplayText: Boolean);
+begin
+  // Show memo fields
+  aText := TField(Sender).AsString;
+end;
+
+constructor TOQBEngineSqlDB.Create(AOwner: TComponent);
+begin
+  inherited;
+  FResultQuery := TSQLQuery.Create(Self);
+  FResultQuery.AfterOpen := @FResultQueryAfterOpen;
+end;
+
+destructor TOQBEngineSqlDB.Destroy;
+begin
+  FResultQuery.Free;
+  inherited;
+end;
+
+procedure TOQBEngineSqlDB.SetConnection(Value: TSQLConnection);
+begin
+  FSqlDBConnection := Value;
+  FResultQuery.Database := Value;
+end;
+
+function TOQBEngineSqlDB.SelectDatabase: Boolean;
+begin
+  Result := True;
+end;
+
+procedure TOQBEngineSqlDB.ReadTableList;
+begin
+  TableList.Clear;
+  TSQLConnection(FResultQuery.Database).GetTableNames(TableList, ShowSystemTables);
+end;
+
+procedure TOQBEngineSqlDB.ReadFieldList(const ATableName: string);
+begin
+  FieldList.Clear;
+  TSQLConnection(FResultQuery.Database).GetFieldNames(ATableName, FieldList);
+  FieldList.Insert(0, '*');
+end;
+
+procedure TOQBEngineSqlDB.ClearQuerySQL;
+begin
+  FResultQuery.SQL.Clear;
+end;
+
+procedure TOQBEngineSqlDB.SetQuerySQL(const Value: string);
+begin
+  FResultQuery.SQL.Text := Value;
+end;
+
+function TOQBEngineSqlDB.ResultQuery: TDataSet;
+begin
+  Result := FResultQuery;
+end;
+
+procedure TOQBEngineSqlDB.OpenResultQuery;
+begin
+  try
+    FResultQuery.Open;
+  finally
+  end;
+end;
+
+procedure TOQBEngineSqlDB.CloseResultQuery;
+begin
+  FResultQuery.Close;
+end;
+
+{$WARNINGS OFF}
+procedure TOQBEngineSqlDB.SaveResultQueryData;
+begin
+  //
+end;
+{$WARNINGS ON}
+
+procedure TOQBEngineSqlDB.Notification(AComponent: TComponent;
+  Operation: TOperation);
+begin
+  inherited;
+  if (AComponent = FSqlDBConnection) and (Operation = opRemove) then
+  begin
+    FSqlDBCOnnection := nil;
+    FResultQuery.Database := nil;
+  end;
+end;
+
+end.
+

+ 187 - 0
QBEZEOS.pas

@@ -0,0 +1,187 @@
+{*******************************************************}
+{                                                       }
+{       Open QBuilder Engine for ZEOS Sources           }
+{                Lazarus / Free Pascal                  }
+{                                                       }
+{ Created by Jean Patrick                               }
+{ Data: 14/02/2013                                      }
+{ E-mail: [email protected]                     }
+{                                                       }
+{*******************************************************}
+
+unit QBEZEOS;
+
+interface
+
+uses
+  types, SysUtils, Classes, DB, ZDataset, ZConnection, QBuilder;
+
+type
+
+  { TOQBEngineZEOS }
+
+  TOQBEngineZEOS = class(TOQBEngine)
+    procedure FResultQueryAfterOpen(DataSet: TDataSet);
+    procedure GridFloatFieldGetText(Sender: TField; var aText: string;
+      DisplayText: Boolean);
+    procedure GridMemoFieldGetText(Sender: TField; var aText: string;
+      DisplayText: Boolean);
+  private
+    FResultQuery: TZQuery;
+    FZEOSConnection : TZConnection;
+  public
+    SchemaPostgreSQL : String;
+    constructor Create(AOwner: TComponent); override;
+    destructor Destroy; override;
+    procedure ClearQuerySQL; override;
+    procedure CloseResultQuery; override;
+    procedure OpenResultQuery; override;
+    procedure ReadFieldList(const ATableName: string); override;
+    procedure ReadTableList; override;
+    procedure SaveResultQueryData; override;
+    procedure SetConnection(Value: TZConnection);
+    procedure SetQuerySQL(const Value: string); override;
+    function ResultQuery: TDataSet; override;
+    function SelectDatabase: Boolean; override;
+    procedure Notification(AComponent: TComponent; Operation: TOperation); override;
+  published
+    // ZEOS connection to be used
+    // Breaks backward compatibility: used to be DatabaseName
+    property Connection: TZConnection read FZEOSConnection write SetConnection;
+  end;
+
+implementation
+
+{ TOQBEngineZEOS }
+
+procedure TOQBEngineZEOS.FResultQueryAfterOpen(DataSet: TDataSet);
+var
+  i: Integer;
+begin
+  for i := 0 to DataSet.Fields.Count - 1 do
+  begin
+    if DataSet.Fields[i].DataType = ftMemo then
+    begin
+      DataSet.Fields[i].OnGetText := @GridMemoFieldGetText;
+    end;
+    // Work around Zeos 7.0.3 bug with DOUBLE PRECISION fields in Firebird
+    if (DataSet.Fields[i].DataType = ftFloat) and
+      (Pos('firebird',FZEOSConnection.Protocol) > 0) and
+      (FZEOSConnection.Version = '7.0.3-stable') then
+    begin
+      DataSet.Fields[i].OnGetText := @GridFloatFieldGetText;
+    end;
+    // ------------------------------------------------------------------
+  end;
+end;
+
+procedure TOQBEngineZEOS.GridFloatFieldGetText(Sender: TField;
+  var aText: string; DisplayText: Boolean);
+begin
+  // Work around Zeos 7.0.3 bug with DOUBLE PRECISION fields in Firebird
+  aText := FloatToStr(TField(Sender).AsFloat);
+end;
+
+procedure TOQBEngineZEOS.GridMemoFieldGetText(Sender: TField;
+  var aText: string; DisplayText: Boolean);
+begin
+  // Show memo fields
+  aText := TField(Sender).AsString;
+end;
+
+constructor TOQBEngineZEOS.Create(AOwner: TComponent);
+begin
+  inherited;
+  FResultQuery := TZQuery.Create(Self);
+  FResultQuery.AfterOpen := @FResultQueryAfterOpen;
+end;
+
+destructor TOQBEngineZEOS.Destroy;
+begin
+  FResultQuery.Free;
+  inherited;
+end;
+
+procedure TOQBEngineZEOS.SetConnection(Value: TZConnection);
+begin
+  FZEOSConnection := Value;
+  FResultQuery.Connection := Value;
+end;
+
+function TOQBEngineZEOS.SelectDatabase: Boolean;
+begin
+  Result := True;
+end;
+
+procedure TOQBEngineZEOS.ReadTableList;
+var
+  vTypesTables: TStringDynArray;
+begin
+  SetLength(vTypesTables,2);
+  vTypesTables[0] := 'TABLE';
+  vTypesTables[1] := 'VIEW';
+  if ShowSystemTables then begin
+    SetLength(vTypesTables,3);
+    vTypesTables[0] := 'TABLE';
+    vTypesTables[1] := 'VIEW';
+    vTypesTables[2] := 'SYSTEM TABLE';
+  end;
+  TableList.Clear;
+  FResultQuery.Connection.GetTableNames(SchemaPostgreSQL,'',vTypesTables,TableList);
+end;
+
+procedure TOQBEngineZEOS.ReadFieldList(const ATableName: string);
+begin
+  FieldList.Clear;
+  FResultQuery.Connection.GetColumnNames(ATableName, '', FieldList);
+  FieldList.Insert(0, '*');
+end;
+
+procedure TOQBEngineZEOS.ClearQuerySQL;
+begin
+  FResultQuery.SQL.Clear;
+end;
+
+procedure TOQBEngineZEOS.SetQuerySQL(const Value: string);
+begin
+  FResultQuery.SQL.Text := Value;
+end;
+
+function TOQBEngineZEOS.ResultQuery: TDataSet;
+begin
+  Result := FResultQuery;
+end;
+
+procedure TOQBEngineZEOS.OpenResultQuery;
+begin
+  try
+    FResultQuery.Open;
+  finally
+  end;
+end;
+
+procedure TOQBEngineZEOS.CloseResultQuery;
+begin
+  FResultQuery.Close;
+end;
+
+{$WARNINGS OFF}
+procedure TOQBEngineZEOS.SaveResultQueryData;
+begin
+  //
+end;
+{$WARNINGS ON}
+
+procedure TOQBEngineZEOS.Notification(AComponent: TComponent;
+  Operation: TOperation);
+begin
+  inherited;
+  if (AComponent = FZEOSConnection) and (Operation = opRemove) then
+  begin
+    FZEOSCOnnection := nil;
+    FResultQuery.Connection := nil;
+  end;
+end;
+
+end.
+

+ 192 - 0
QBLnkFrm.lfm

@@ -0,0 +1,192 @@
+object OQBLinkForm: TOQBLinkForm
+  Left = 477
+  Height = 239
+  Top = 258
+  Width = 280
+  ActiveControl = RadioOpt
+  BorderIcons = [biSystemMenu]
+  BorderStyle = bsDialog
+  Caption = 'Link Options'
+  ClientHeight = 239
+  ClientWidth = 280
+  Color = clBtnFace
+  Font.Color = clWindowText
+  Font.Height = -11
+  Font.Name = 'Tahoma'
+  Position = poScreenCenter
+  LCLVersion = '1.0.6.0'
+  object Label1: TLabel
+    Left = 2
+    Height = 14
+    Top = 7
+    Width = 37
+    Caption = 'Table 1'
+    Font.Color = clWindowText
+    Font.Height = -11
+    Font.Name = 'MS Sans Serif'
+    ParentColor = False
+    ParentFont = False
+  end
+  object Label2: TLabel
+    Left = 2
+    Height = 14
+    Top = 46
+    Width = 37
+    Caption = 'Table 2'
+    Font.Color = clWindowText
+    Font.Height = -11
+    Font.Name = 'MS Sans Serif'
+    ParentColor = False
+    ParentFont = False
+  end
+  object Label3: TLabel
+    Left = 3
+    Height = 14
+    Top = 24
+    Width = 45
+    Caption = 'Column 1'
+    Font.Color = clWindowText
+    Font.Height = -11
+    Font.Name = 'MS Sans Serif'
+    ParentColor = False
+    ParentFont = False
+  end
+  object Label4: TLabel
+    Left = 2
+    Height = 14
+    Top = 62
+    Width = 45
+    Caption = 'Column 2'
+    Font.Color = clWindowText
+    Font.Height = -11
+    Font.Name = 'MS Sans Serif'
+    ParentColor = False
+    ParentFont = False
+  end
+  object RadioOpt: TRadioGroup
+    Left = 3
+    Height = 150
+    Top = 85
+    Width = 98
+    AutoFill = True
+    Caption = 'Join Operator'
+    ChildSizing.LeftRightSpacing = 6
+    ChildSizing.TopBottomSpacing = 6
+    ChildSizing.EnlargeHorizontal = crsHomogenousChildResize
+    ChildSizing.EnlargeVertical = crsHomogenousChildResize
+    ChildSizing.ShrinkHorizontal = crsScaleChilds
+    ChildSizing.ShrinkVertical = crsScaleChilds
+    ChildSizing.Layout = cclLeftToRightThenTopToBottom
+    ChildSizing.ControlsPerLine = 1
+    ClientHeight = 132
+    ClientWidth = 94
+    ItemIndex = 0
+    Items.Strings = (
+      '='
+      '<'
+      '>'
+      '<='
+      '>='
+      '<>'
+    )
+    TabOrder = 0
+  end
+  object RadioType: TRadioGroup
+    Left = 107
+    Height = 150
+    Top = 85
+    Width = 104
+    AutoFill = True
+    Caption = 'Join Type'
+    ChildSizing.LeftRightSpacing = 6
+    ChildSizing.TopBottomSpacing = 6
+    ChildSizing.EnlargeHorizontal = crsHomogenousChildResize
+    ChildSizing.EnlargeVertical = crsHomogenousChildResize
+    ChildSizing.ShrinkHorizontal = crsScaleChilds
+    ChildSizing.ShrinkVertical = crsScaleChilds
+    ChildSizing.Layout = cclLeftToRightThenTopToBottom
+    ChildSizing.ControlsPerLine = 1
+    ClientHeight = 132
+    ClientWidth = 100
+    ItemIndex = 0
+    Items.Strings = (
+      'Inner'
+      'Left Outer'
+      'Right Outer'
+      'Full Outer'
+    )
+    TabOrder = 1
+  end
+  object BtnOk: TButton
+    Left = 215
+    Height = 20
+    Top = 185
+    Width = 61
+    Caption = '&Ok'
+    Default = True
+    ModalResult = 1
+    TabOrder = 2
+  end
+  object BtnCancel: TButton
+    Left = 215
+    Height = 20
+    Top = 211
+    Width = 61
+    Cancel = True
+    Caption = '&Cancel'
+    ModalResult = 2
+    TabOrder = 3
+  end
+  object txtTable1: TStaticText
+    Left = 55
+    Height = 16
+    Top = 7
+    Width = 219
+    BorderStyle = sbsSunken
+    Font.Color = clWindowText
+    Font.Height = -11
+    Font.Name = 'MS Sans Serif'
+    Font.Style = [fsBold]
+    ParentFont = False
+    TabOrder = 4
+  end
+  object txtTable2: TStaticText
+    Left = 55
+    Height = 16
+    Top = 46
+    Width = 220
+    BorderStyle = sbsSunken
+    Font.Color = clWindowText
+    Font.Height = -11
+    Font.Name = 'MS Sans Serif'
+    Font.Style = [fsBold]
+    ParentFont = False
+    TabOrder = 5
+  end
+  object txtCol1: TStaticText
+    Left = 55
+    Height = 16
+    Top = 23
+    Width = 219
+    BorderStyle = sbsSunken
+    Font.Color = clWindowText
+    Font.Height = -11
+    Font.Name = 'MS Sans Serif'
+    Font.Style = [fsBold]
+    ParentFont = False
+    TabOrder = 6
+  end
+  object txtCol2: TStaticText
+    Left = 55
+    Height = 16
+    Top = 62
+    Width = 220
+    BorderStyle = sbsSunken
+    Font.Color = clWindowText
+    Font.Height = -11
+    Font.Name = 'MS Sans Serif'
+    Font.Style = [fsBold]
+    ParentFont = False
+    TabOrder = 7
+  end
+end

+ 57 - 0
QBLnkFrm.pas

@@ -0,0 +1,57 @@
+{*******************************************************}
+{                                                       }
+{       Delphi Visual Component Library                 }
+{       QBuilder dialog component                       }
+{                                                       }
+{       Copyright (c) 1996-2003 Sergey Orlik            }
+{                                                       }
+{     Written by:                                       }
+{       Sergey Orlik                                    }
+{       product manager                                 }
+{       Russia, C.I.S. and Baltic States (former USSR)  }
+{       Borland Moscow office                           }
+{       Internet:  [email protected],             }
+{                  [email protected]                   }
+{                  http://www.fast-report.com           }
+{                                                       }
+{ Converted to Lazarus/Free Pascal by Jean Patrick      }
+{ Data: 14/02/2013                                      }
+{ E-mail: [email protected]                     }
+{                                                       }
+{*******************************************************}
+
+unit QBLnkFrm;
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+
+
+interface
+
+uses
+  Forms,
+  StdCtrls, ExtCtrls;
+
+type
+  TOQBLinkForm = class(TForm)
+    RadioOpt: TRadioGroup;
+    RadioType: TRadioGroup;
+    BtnOk: TButton;
+    BtnCancel: TButton;
+    txtTable1: TStaticText;
+    txtTable2: TStaticText;
+    Label1: TLabel;
+    Label2: TLabel;
+    Label3: TLabel;
+    txtCol1: TStaticText;
+    Label4: TLabel;
+    txtCol2: TStaticText;
+  end;
+
+implementation
+
+  {$R *.lfm}
+
+end.

+ 1061 - 0
QBuilder.lfm

@@ -0,0 +1,1061 @@
+object OQBForm: TOQBForm
+  Left = 318
+  Height = 501
+  Top = 114
+  Width = 567
+  ActiveControl = QBTables
+  Caption = 'Open QBuilder'
+  ClientHeight = 501
+  ClientWidth = 567
+  Color = clBtnFace
+  Font.Color = clWindowText
+  Font.Height = -11
+  Font.Name = 'Tahoma'
+  Position = poScreenCenter
+  LCLVersion = '1.3'
+  object QBPanel: TPanel
+    Left = 0
+    Height = 472
+    Top = 29
+    Width = 567
+    Align = alClient
+    BevelOuter = bvNone
+    ClientHeight = 472
+    ClientWidth = 567
+    TabOrder = 0
+    object VSplitter: TSplitter
+      Left = 444
+      Height = 315
+      Top = 0
+      Width = 2
+      Align = alRight
+      Color = clBtnFace
+      ParentColor = False
+      ResizeAnchor = akRight
+    end
+    object HSplitter: TSplitter
+      Cursor = crVSplit
+      Left = 0
+      Height = 2
+      Top = 315
+      Width = 567
+      Align = alBottom
+      Color = clBtnFace
+      ParentColor = False
+      ResizeAnchor = akBottom
+    end
+    object Pages: TPageControl
+      Left = 0
+      Height = 155
+      Top = 317
+      Width = 567
+      ActivePage = TabColumns
+      Align = alBottom
+      TabIndex = 0
+      TabOrder = 0
+      object TabColumns: TTabSheet
+        Caption = 'Columns'
+      end
+      object TabSQL: TTabSheet
+        Caption = 'SQL'
+        ClientHeight = 127
+        ClientWidth = 563
+        object MemoSQL: TMemo
+          Left = 0
+          Height = 127
+          Top = 0
+          Width = 547
+          Align = alClient
+          Font.Color = clWindowText
+          Font.Height = -11
+          Font.Name = 'Courier New'
+          ParentFont = False
+          ScrollBars = ssBoth
+          TabOrder = 0
+        end
+      end
+      object TabResults: TTabSheet
+        Caption = 'Results'
+        ClientHeight = 127
+        ClientWidth = 563
+        object ResDBGrid: TDBGrid
+          Left = 0
+          Height = 127
+          Top = 0
+          Width = 547
+          Align = alClient
+          Color = clWindow
+          Columns = <>
+          DataSource = ResDataSource
+          Options = [dgTitles, dgIndicator, dgColumnResize, dgColLines, dgRowLines, dgTabs, dgConfirmDelete, dgCancelOnExit]
+          TabOrder = 0
+          TitleFont.Color = clWindowText
+          TitleFont.Height = -11
+          TitleFont.Name = 'Tahoma'
+        end
+      end
+    end
+    object QBTables: TListBox
+      Left = 446
+      Height = 315
+      Top = 0
+      Width = 121
+      Align = alRight
+      DragMode = dmAutomatic
+      ExtendedSelect = False
+      ItemHeight = 0
+      ScrollWidth = 119
+      TabOrder = 1
+      TabStop = False
+    end
+  end
+  object QBBar: TToolBar
+    Left = 0
+    Height = 29
+    Top = 0
+    Width = 567
+    AutoSize = True
+    ButtonHeight = 27
+    ButtonWidth = 28
+    Images = ToolImages
+    ParentShowHint = False
+    ShowHint = True
+    TabOrder = 1
+    object btnDB: TToolButton
+      Left = 1
+      Hint = 'Select Database'
+      Top = 2
+      Caption = 'Select Database'
+      ImageIndex = 5
+      OnClick = btnDBClick
+    end
+    object btnNew: TToolButton
+      Left = 29
+      Hint = 'New Model'
+      Top = 2
+      Caption = 'New Model'
+      ImageIndex = 0
+      OnClick = btnNewClick
+    end
+    object btnOpen: TToolButton
+      Left = 57
+      Hint = 'Open Model'
+      Top = 2
+      Caption = 'Open Model'
+      ImageIndex = 1
+      OnClick = btnOpenClick
+    end
+    object btnSave: TToolButton
+      Left = 85
+      Hint = 'Save Model'
+      Top = 2
+      Caption = 'Save Model'
+      ImageIndex = 2
+      OnClick = btnSaveClick
+    end
+    object ToolButton1: TToolButton
+      Left = 113
+      Top = 2
+      Width = 5
+      Caption = 'ToolButton1'
+      ImageIndex = 0
+      Style = tbsDivider
+    end
+    object btnPages: TToolButton
+      Left = 118
+      Hint = 'Show Pages'
+      Top = 2
+      Caption = 'Show Pages'
+      Down = True
+      ImageIndex = 4
+      OnClick = btnPagesClick
+      Style = tbsCheck
+    end
+    object btnTables: TToolButton
+      Left = 146
+      Hint = 'Show Tables'
+      Top = 2
+      Caption = 'Show Tables'
+      Down = True
+      ImageIndex = 3
+      OnClick = btnTablesClick
+      Style = tbsCheck
+    end
+    object ToolButton2: TToolButton
+      Left = 174
+      Top = 2
+      Width = 5
+      Caption = 'ToolButton2'
+      ImageIndex = 0
+      Style = tbsDivider
+    end
+    object btnSQL: TToolButton
+      Left = 179
+      Hint = 'Generate SQL'
+      Top = 2
+      Caption = 'Generate SQL'
+      ImageIndex = 6
+      OnClick = btnSQLClick
+    end
+    object btnResults: TToolButton
+      Left = 207
+      Hint = 'Run Current SQL'
+      Top = 2
+      Caption = 'Run Current SQL'
+      ImageIndex = 7
+      OnClick = btnResultsClick
+    end
+    object btnSaveResults: TToolButton
+      Left = 235
+      Hint = 'Save Results'
+      Top = 2
+      Caption = 'Save Results'
+      ImageIndex = 9
+      OnClick = btnSaveResultsClick
+    end
+    object ToolButton3: TToolButton
+      Left = 263
+      Top = 2
+      Width = 5
+      Caption = 'ToolButton3'
+      ImageIndex = 8
+      Style = tbsDivider
+    end
+    object btnAbout: TToolButton
+      Left = 268
+      Hint = 'About'
+      Top = 2
+      Caption = 'About'
+      ImageIndex = 8
+      OnClick = btnAboutClick
+    end
+    object ToolButton6: TToolButton
+      Left = 296
+      Top = 2
+      Width = 5
+      Caption = 'ToolButton6'
+      ImageIndex = 11
+      Style = tbsDivider
+    end
+    object btnOK: TToolButton
+      Left = 301
+      Hint = 'OK'
+      Top = 2
+      Caption = 'btnOK'
+      ImageIndex = 11
+      OnClick = btnOKClick
+    end
+    object btnCancel: TToolButton
+      Left = 329
+      Hint = 'Cancel'
+      Top = 2
+      Caption = 'btnCancel'
+      ImageIndex = 10
+      OnClick = btnCancelClick
+    end
+  end
+  object mnuTbl: TPopupMenu
+    AutoPopup = False
+    left = 392
+    top = 272
+    object Remove1: TMenuItem
+      Caption = 'Remove'
+      OnClick = mnuRemoveClick
+    end
+  end
+  object mnuFunc: TPopupMenu
+    AutoPopup = False
+    left = 488
+    top = 272
+    object Nofunction1: TMenuItem
+      Tag = 1
+      Caption = 'No function'
+      Checked = True
+      GroupIndex = 1
+      RadioItem = True
+      OnClick = mnuFunctionClick
+    end
+    object N1: TMenuItem
+      Caption = '-'
+      Enabled = False
+      GroupIndex = 1
+      RadioItem = True
+    end
+    object Average1: TMenuItem
+      Tag = 2
+      Caption = 'Average'
+      GroupIndex = 1
+      RadioItem = True
+      OnClick = mnuFunctionClick
+    end
+    object Count1: TMenuItem
+      Tag = 3
+      Caption = 'Count'
+      GroupIndex = 1
+      RadioItem = True
+      OnClick = mnuFunctionClick
+    end
+    object Minimum1: TMenuItem
+      Tag = 4
+      Caption = 'Maximum'
+      GroupIndex = 1
+      RadioItem = True
+      OnClick = mnuFunctionClick
+    end
+    object Maximum1: TMenuItem
+      Tag = 5
+      Caption = 'Minimum'
+      GroupIndex = 1
+      RadioItem = True
+      OnClick = mnuFunctionClick
+    end
+    object Sum1: TMenuItem
+      Tag = 6
+      Caption = 'Sum'
+      GroupIndex = 1
+      RadioItem = True
+      OnClick = mnuFunctionClick
+    end
+  end
+  object mnuGroup: TPopupMenu
+    AutoPopup = False
+    left = 520
+    top = 272
+    object Group1: TMenuItem
+      Caption = 'Group'
+      Checked = True
+      OnClick = mnuGroupClick
+    end
+  end
+  object mnuSort: TPopupMenu
+    AutoPopup = False
+    left = 456
+    top = 272
+    object Sort1: TMenuItem
+      Tag = 1
+      Caption = 'No Sort'
+      GroupIndex = 1
+      RadioItem = True
+      OnClick = mnuSortClick
+    end
+    object N2: TMenuItem
+      Caption = '-'
+      GroupIndex = 1
+      RadioItem = True
+    end
+    object Ascending1: TMenuItem
+      Tag = 2
+      Caption = 'Ascending'
+      GroupIndex = 1
+      RadioItem = True
+      OnClick = mnuSortClick
+    end
+    object Descending1: TMenuItem
+      Tag = 3
+      Caption = 'Descending'
+      GroupIndex = 1
+      RadioItem = True
+      OnClick = mnuSortClick
+    end
+  end
+  object mnuShow: TPopupMenu
+    AutoPopup = False
+    left = 424
+    top = 272
+    object Show1: TMenuItem
+      Caption = 'Show'
+      Checked = True
+      OnClick = mnuShowClick
+    end
+  end
+  object ResDataSource: TDataSource
+    AutoEdit = False
+    left = 422
+    top = 346
+  end
+  object ToolImages: TImageList
+    Height = 21
+    Width = 21
+    top = 37
+    Bitmap = {
+      4C690C0000001500000015000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      00007B7B7BFF7B7B7BFF7B7B7BFF7B7B7BFF7B7B7BFF7B7B7BFF7B7B7BFF7B7B
+      7BFF7B7B7BFF7B7B7BFF7B7B7BFF000000000000000000000000000000000000
+      000000000000000000000000000000000000000000007B7B7BFFFFFFFFFFFFFF
+      FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7B7B
+      7BFF7B7B7BFF0000000000000000000000000000000000000000000000000000
+      000000000000000000007B7B7BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+      FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7B7B7BFFFFFFFFFF7B7B7BFF0000
+      0000000000000000000000000000000000000000000000000000000000007B7B
+      7BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+      FFFFFFFFFFFF7B7B7BFFFFFFFFFFFFFFFFFF7B7B7BFF00000000000000000000
+      0000000000000000000000000000000000007B7B7BFFFFFFFFFFFFFFFFFFFFFF
+      FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FF0000
+      00FF000000FF000000FF000000FF000000000000000000000000000000000000
+      0000000000007B7B7BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+      FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000
+      00FF0000000000000000000000000000000000000000000000007B7B7BFFFFFF
+      FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+      FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FF00000000000000000000
+      00000000000000000000000000007B7B7BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+      FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+      FFFFFFFFFFFF000000FF00000000000000000000000000000000000000000000
+      00007B7B7BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+      FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FF0000
+      000000000000000000000000000000000000000000007B7B7BFFFFFFFFFFFFFF
+      FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+      FFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FF0000000000000000000000000000
+      000000000000000000007B7B7BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+      FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+      FFFF000000FF0000000000000000000000000000000000000000000000007B7B
+      7BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+      FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FF000000000000
+      0000000000000000000000000000000000007B7B7BFFFFFFFFFFFFFFFFFFFFFF
+      FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+      FFFFFFFFFFFFFFFFFFFF000000FF000000000000000000000000000000000000
+      0000000000007B7B7BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+      FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000
+      00FF0000000000000000000000000000000000000000000000007B7B7BFFFFFF
+      FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+      FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FF00000000000000000000
+      00000000000000000000000000007B7B7BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+      FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+      FFFFFFFFFFFF000000FF00000000000000000000000000000000000000000000
+      00007B7B7BFF000000FF000000FF000000FF000000FF000000FF000000FF0000
+      00FF000000FF000000FF000000FF000000FF000000FF000000FF000000FF0000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7B7B7BFF0000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000FFFFFFFF7B00
+      00FF7B0000FF7B0000FFFFFFFFFF7B7B7BFF7B7B7BFF00000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      00FF000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+      FFFFFFFFFFFFFFFFFFFF000000FF000000000000000000000000000000000000
+      000000000000000000000000000000000000000000FF000000FF000000000000
+      0000FFFFFFFF7B0000FF7B0000FF7B0000FF7B0000FF7B0000FFFFFFFFFF0000
+      00FF00000000000000000000000000000000000000007B7B7BFF000000FF0000
+      00FF000000FF000000FF000000FF000000FF00000000FFFFFFFFFFFFFFFFFFFF
+      FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FF00000000000000000000
+      00000000000000000000000000FF000000FF7B7B7BFF00000000000000FF0000
+      00FF0000000000000000FFFFFFFF7B0000FF7B0000FF7B0000FF7B0000FF7B00
+      00FFFFFFFFFF000000FF00000000000000000000000000000000000000000000
+      00FF000000FF0000000000000000000000FF000000000000000000000000FFFF
+      FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FF0000
+      000000000000000000000000000000000000000000FF000000FF000000000000
+      000000000000000000000000000000000000000000FF000000FF000000FF0000
+      00FF000000FF000000FF000000FF000000FF0000000000000000000000000000
+      000000000000000000FF000000FF000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000FF0000
+      00FF000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000000000000000000000000000000000000000000000FFFF
+      FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+      FFFFFFFFFFFFFFFFFFFF00000000000000FF0000000000000000000000000000
+      000000000000000000000000000000000000FFFFFFFF000000000000FFFF0000
+      FFFF000000000000000000000000000000000000000000000000000000007B7B
+      7BFF000000FF0000000000000000000000000000000000000000000000000000
+      000000000000FFFFFFFF00000000000000000000000000000000000000000000
+      0000000000000000000000000000000000007B7B7BFF000000FF000000000000
+      0000000000000000000000000000000000000000000000000000FFFFFFFF0000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000007B7B7BFF000000FF000000000000000000000000000000000000
+      0000000000000000000000000000000000007B7B7BFF7B7B7BFF7B7B7BFF7B7B
+      7BFF7B7B7BFF7B7B7BFF7B7B7BFF7B7B7BFF7B7B7BFF7B7B7BFF7B7B7BFF0000
+      00FF000000000000000000000000000000000000000000000000000000000000
+      0000000000FF000000FF000000FF000000FF000000FF000000FF000000FF0000
+      00FF000000FF000000FF000000FF000000FF000000FF00000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7B7B7BFF0000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000FFFFFFFF7B00
+      00FF7B0000FF7B0000FFFFFFFFFF7B7B7BFF7B7B7BFF00000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+      FFFFFFFFFFFFFFFFFFFF000000FF00000000000000FF000000FF000000FF0000
+      00FF7B7B7BFF0000000000000000000000000000000000000000000000000000
+      0000FFFFFFFF7B0000FF7B0000FF7B0000FF7B0000FF7B0000FFFFFFFFFF0000
+      00FF00000000000000FF000000FF000000FF000000FF000000FF000000000000
+      00000000000000000000000000000000000000000000FFFFFFFFFFFFFFFFFFFF
+      FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FF00000000000000000000
+      0000000000007B7B7BFF000000FF000000000000000000000000000000000000
+      00000000000000000000FFFFFFFF7B0000FF7B0000FF7B0000FF7B0000FF7B00
+      00FFFFFFFFFF000000FF00000000000000000000000000000000000000000000
+      00FF00000000000000000000000000000000000000000000000000000000FFFF
+      FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FF0000
+      000000000000000000000000000000000000000000FF00000000000000000000
+      000000000000000000000000000000000000000000FF000000FF000000FF0000
+      00FF000000FF000000FF000000FF000000FF0000000000000000000000000000
+      00FF000000FF000000FF000000FF000000FF0000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      00000000000000000000000000000000000000000000000000FF000000FF0000
+      00FF000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000FF0000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFF
+      FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000
+      0000000000FF0000000000000000000000000000000000000000000000000000
+      000000000000FFFFFFFF000000000000FFFF0000FFFF00000000000000000000
+      0000000000000000000000000000000000007B7B7BFF000000FF000000000000
+      0000000000000000000000000000000000000000000000000000FFFFFFFF0000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000007B7B7BFF000000FF000000000000000000000000000000000000
+      0000000000000000000000000000FFFFFFFF0000000000000000000000000000
+      00000000000000000000000000000000000000000000000000007B7B7BFF0000
+      00FF000000000000000000000000000000000000000000000000000000000000
+      0000000000007B7B7BFF7B7B7BFF7B7B7BFF7B7B7BFF7B7B7BFF7B7B7BFF7B7B
+      7BFF7B7B7BFF7B7B7BFF7B7B7BFF7B7B7BFF000000FF00000000000000000000
+      00000000000000000000000000000000000000000000000000FF000000FF0000
+      00FF000000FF000000FF000000FF000000FF000000FF000000FF000000FF0000
+      00FF000000FF000000FF00000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      00000000000000000000000000000000000000000000000000007B7B7BFF7B7B
+      7BFF7B7B7BFF7B7B7BFF7B7B7BFF7B7B7BFF7B7B7BFF7B7B7BFF7B7B7BFF7B7B
+      7BFF7B7B7BFF7B7B7BFF7B7B7BFF7B7B7BFF7B7B7BFF00000000000000000000
+      00000000000000000000000000007B7B7BFF000000007B7B7BFFFFFFFFFF0000
+      0000000000000000000000000000FFFFFFFF0000000000000000000000000000
+      0000000000007B7B7BFF00000000000000000000000000000000000000000000
+      00007B7B7BFF7B7B7BFF7B7B7BFF7B7B7BFF7B7B7BFF7B7B7BFF7B7B7BFF7B7B
+      7BFF7B7B7BFF7B7B7BFF7B7B7BFF7B7B7BFF7B7B7BFF7B7B7BFF7B7B7BFF0000
+      000000000000000000000000000000000000000000007B7B7BFF000000007B7B
+      7BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFFFFFF
+      FFFFFFFFFFFFFFFFFFFFFFFFFFFF7B7B7BFF0000000000000000000000000000
+      000000000000000000007B7B7BFFFFFFFFFF7B7B7BFFFFFFFFFF000000000000
+      0000FFFFFFFF00000000FFFFFFFF00000000000000000000000000000000FFFF
+      FFFF7B7B7BFF0000000000000000000000000000000000000000000000007B7B
+      7BFF000000007B7B7BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFF
+      FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7B7B7BFF000000000000
+      0000000000000000000000000000000000007B7B7BFFFFFFFFFF7B7B7BFFFFFF
+      FFFF0000000000000000FFFFFFFF00000000FFFFFFFF00000000000000000000
+      0000FFFFFFFFFFFFFFFF7B7B7BFF000000000000000000000000000000000000
+      0000000000007B7B7BFF000000007B7B7BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+      FFFF00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7B7B
+      7BFF0000000000000000000000000000000000000000000000007B7B7BFFFFFF
+      FFFF7B7B7BFFFFFFFFFF0000000000000000FFFFFFFF00000000FFFFFFFF0000
+      0000000000000000000000000000FFFFFFFF7B7B7BFF00000000000000000000
+      00000000000000000000000000007B7B7BFF000000007B7B7BFFFFFFFFFFFFFF
+      FFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+      FFFFFFFFFFFF7B7B7BFF00000000000000000000000000000000000000000000
+      00007B7B7BFF7B7B7BFF7B7B7BFF7B7B7BFF7B7B7BFF7B7B7BFF7B7B7BFF7B7B
+      7BFF7B7B7BFF7B7B7BFF7B7B7BFF7B7B7BFF7B7B7BFF7B7B7BFF7B7B7BFF0000
+      0000000000000000000000000000000000000000000000000000000000000000
+      00FF000000FF0000000000000000000000000000000000000000000000000000
+      00000000000000000000000000FF000000FF0000000000000000000000000000
+      0000000000000000000000000000000000FF00000000000000FF000000FF0000
+      0000000000000000000000000000000000000000000000000000000000FF0000
+      0000000000FF000000FF00000000000000000000000000000000000000000000
+      0000000000FF0000000000000000000000FF0000000000000000000000FF0000
+      00FF000000FF0000000000000000000000FF0000000000000000000000FF0000
+      00FF000000FF00000000000000000000000000000000000000FF000000000000
+      0000000000FF000000FF000000FF7B7B7BFFFFFFFFFF7B7B7BFF000000FF0000
+      00FF000000FF000000FF000000FF7B7B7BFFFFFFFFFF7B7B7BFF000000FF0000
+      0000000000000000000000000000000000FF0000000000000000000000FF7B7B
+      7BFFFFFFFFFFFFFFFFFFFFFFFFFF00000000000000FF000000FF000000FF7B7B
+      7BFFFFFFFFFFFFFFFFFFFFFFFFFF00000000000000FF00000000000000000000
+      0000000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+      FFFFFFFFFFFF000000FF00000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+      FFFFFFFFFFFF000000FF00000000000000000000000000000000000000000000
+      0000000000FF7B7B7BFFFFFFFFFFFFFFFFFFFFFFFFFF00000000000000FF0000
+      0000000000FF7B7B7BFFFFFFFFFFFFFFFFFFFFFFFFFF00000000000000FF0000
+      0000000000000000000000000000000000000000000000000000000000FF7B7B
+      7BFFFFFFFFFF00000000000000FF000000000000000000000000000000FF7B7B
+      7BFFFFFFFFFF00000000000000FF000000000000000000000000000000000000
+      000000000000000000000000000000000000000000FF000000FF000000FF0000
+      000000000000000000000000000000000000000000FF000000FF000000FF0000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      00000000000000000000000000000000000000000000000000007B7B7BFF7B7B
+      7BFF7B7B7BFF7B7B7BFF7B7B7BFF7B7B7BFF7B7B7BFF7B7B7BFF7B7B7BFF7B7B
+      7BFF7B7B7BFF7B7B7BFF7B7B7BFF7B7B7BFF7B7B7BFF7B7B7BFF000000000000
+      00000000000000000000000000007B7B7BFFFFFFFFFF00000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000007B7B7BFF000000000000000000000000000000000000
+      00007B7B7BFF000000000000000000000000FFFFFFFF00000000FFFFFFFFFFFF
+      FFFF00000000FFFFFFFF00000000FFFFFFFFFFFFFFFF00000000000000007B7B
+      7BFF00000000000000000000000000000000000000007B7B7BFFFFFFFFFFFFFF
+      FFFFFFFFFFFF00000000FFFFFFFF0000000000000000FFFFFFFF00000000FFFF
+      FFFF0000000000000000FFFFFFFF000000007B7B7BFF00000000000000000000
+      000000000000000000007B7B7BFF00000000FFFFFFFF00000000FFFFFFFF0000
+      0000FFFFFFFF0000000000000000FFFFFFFF0000000000000000FFFFFFFF0000
+      0000000000007B7B7BFF00000000000000000000000000000000000000007B7B
+      7BFFFFFFFFFF0000000000000000FFFFFFFF7B7B7BFF7B7B7BFF7B7B7BFF7B7B
+      7BFF7B7B7BFF7B7B7BFF7B7B7BFF7B7B7BFF7B7B7BFF7B7B7BFF7B7B7BFF0000
+      0000000000000000000000000000000000007B7B7BFFFFFFFFFFFFFFFFFFFFFF
+      FFFF000000007B7B7BFFFFFFFFFF0000000000000000000000007B7B7BFFFFFF
+      FFFF0000000000000000000000007B7B7BFF0000000000000000000000000000
+      000000000000000000007B7B7BFFFFFFFFFF000000007B7B7BFF000000007B7B
+      7BFF00000000000000007B7B7BFF000000007B7B7BFF00000000000000007B7B
+      7BFF000000000000000000000000000000000000000000000000000000007B7B
+      7BFF7B7B7BFF7B7B7BFF7B7B7BFF000000007B7B7BFF7B7B7BFF7B7B7BFF7B7B
+      7BFF000000007B7B7BFF7B7B7BFF7B7B7BFF7B7B7BFF00000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000FF000000FF00000000000000000000000000000000000000000000
+      0000000000000000000000000000000000FF000000FF00000000000000000000
+      000000000000000000000000000000000000000000FF00000000000000FF0000
+      00FF000000000000000000000000000000000000000000000000000000000000
+      00FF00000000000000FF000000FF000000000000000000000000000000000000
+      000000000000000000FF0000000000000000000000FF00000000000000000000
+      00FF000000FF000000FF0000000000000000000000FF00000000000000000000
+      00FF000000FF000000FF00000000000000000000000000000000000000FF0000
+      000000000000000000FF000000FF000000FF7B7B7BFFFFFFFFFF7B7B7BFF0000
+      00FF000000FF000000FF000000FF000000FF7B7B7BFFFFFFFFFF7B7B7BFF0000
+      00FF00000000000000000000000000000000000000FF00000000000000000000
+      00FF7B7B7BFFFFFFFFFFFFFFFFFFFFFFFFFF00000000000000FF000000FF0000
+      00FF7B7B7BFFFFFFFFFFFFFFFFFFFFFFFFFF00000000000000FF000000000000
+      000000000000000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFF
+      FFFFFFFFFFFFFFFFFFFF000000FF00000000000000FFFFFFFFFFFFFFFFFFFFFF
+      FFFFFFFFFFFFFFFFFFFF000000FF000000000000000000000000000000000000
+      000000000000000000FF7B7B7BFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000
+      00FF00000000000000FF7B7B7BFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000
+      00FF000000000000000000000000000000000000000000000000000000000000
+      00FF7B7B7BFFFFFFFFFF00000000000000FF0000000000000000000000000000
+      00FF7B7B7BFFFFFFFFFF00000000000000FF0000000000000000000000000000
+      00000000000000000000000000000000000000000000000000FF000000FF0000
+      00FF0000000000000000000000000000000000000000000000FF000000FF0000
+      00FF000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000FF000000FF000000FF000000FF000000FF000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      00000000000000000000000000000000000000000000000000FFFFFF00FFFFFF
+      00FFFFFF00FFFFFF00FFFFFF00FF000000FF0000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF
+      00FFFFFF00FF000000FF00000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000FF0000
+      00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FF000000FF000000FF0000
+      00FF000000FF000000FF00000000000000000000000000000000000000000000
+      0000000000000000000000000000000000FF00000000000000FF000000FF0000
+      00FF000000FF000000FF7B7B7BFF000000FFFF0000FFFF0000FFFF0000FF0000
+      00FF000000000000000000000000000000000000000000000000000000000000
+      0000000000FF7B7B7BFF00000000FFFFFFFFFFFFFFFF000000007B7B7BFF0000
+      0000000000FFFF0000FFFF0000FFFF0000FFFF0000FF000000FF000000000000
+      00000000000000000000000000000000000000000000000000FF00000000FFFF
+      FFFFFFFFFFFFFFFFFFFFFFFFFFFF000000007B7B7BFF000000FFFF0000FFFF00
+      00FFFF0000FF000000FF000000FF000000000000000000000000000000000000
+      00000000000000000000000000FF7B7B7BFF00000000FFFFFFFFFFFFFFFF0000
+      00007B7B7BFF00000000000000FF000000FF000000FF000000FF7B7B7BFF0000
+      00FF000000000000000000000000000000000000000000000000000000000000
+      00FF00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000007B7B7BFF0000
+      00FFFFFFFFFF000000007B7B7BFF00000000000000FF00000000000000000000
+      0000000000000000000000000000000000007B7B7BFF000000FF00000000FFFF
+      FFFFFFFFFFFF000000007B7B7BFF000000FF7B7B7BFFFFFFFFFFFFFFFFFF0000
+      00007B7B7BFF000000FF00000000000000000000000000000000000000000000
+      0000000000000000000000000000000000FF000000FF000000FF000000FF0000
+      00FFFFFFFFFFFFFFFFFFFFFFFFFF000000007B7B7BFF00000000000000FF0000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000FF00000000FFFFFFFFFFFFFFFFFFFF
+      FFFFFFFFFFFF000000007B7B7BFF000000FF0000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      00007B7B7BFF000000FF00000000FFFFFFFFFFFFFFFF000000007B7B7BFF0000
+      00FF7B7B7BFF0000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      00FF000000FF000000FF000000FF000000FF0000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      00000000000000000000000000000000000000000000000000007B0000FF0000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      00000000000000000000000000007B7B7BFF7B0000FF00000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      00007B0000FF7B7B7BFF7B0000FF000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000000000000000000000000000007B7B7BFF7B0000FF7B7B
+      7BFF7B0000FF0000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000007B0000FF7B7B7BFF7B0000FF7B7B7BFF7B0000FF0000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000007B7B
+      7BFF7B0000FF7B7B7BFF7B0000FF7B7B7BFF7B0000FF00000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000007B0000FF7B7B7BFF7B0000FF7B7B
+      7BFF7B0000FF7B7B7BFF7B0000FF000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000007B7B7BFF7B0000FF7B7B7BFF7B0000FF7B7B7BFF7B0000FF7B7B
+      7BFF7B0000FF0000000000000000000000000000000000000000000000000000
+      00000000000000000000000000000000000000000000000000007B0000FF7B7B
+      7BFF7B0000FF7B7B7BFF7B0000FF7B7B7BFF7B0000FF000000FF000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      00000000000000000000000000007B7B7BFF7B0000FF7B7B7BFF7B0000FF7B7B
+      7BFF7B0000FF000000FF00000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      00007B0000FF7B7B7BFF7B0000FF7B7B7BFF7B0000FF000000FF000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000000000000000000000000000007B7B7BFF7B0000FF7B7B
+      7BFF7B0000FF000000FF00000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000007B0000FF7B7B7BFF7B0000FF000000FF000000000000
+      00FF000000FF000000000000000000000000000000FF000000FF000000000000
+      000000000000000000FF00000000000000000000000000000000000000007B7B
+      7BFF7B0000FF000000FF00000000000000FF7B7B7BFF7B7B7BFF000000FF0000
+      0000000000FF7B7B7BFF7B7B7BFF000000FF0000000000000000000000FF7B7B
+      7BFF000000000000000000000000000000007B0000FF000000FF000000000000
+      00007B7B7BFF000000FF000000007B7B7BFF00000000000000FF7B7B7BFF0000
+      0000000000FF7B7B7BFF00000000000000FF7B7B7BFF00000000000000000000
+      000000000000000000FF00000000000000000000000000000000000000000000
+      00FF0000000000000000000000FF7B7B7BFF00000000000000FF7B7B7BFF0000
+      0000000000FF7B7B7BFF00000000000000000000000000000000000000000000
+      00000000000000000000000000FF0000000000000000000000FF000000000000
+      00FF00000000000000FF000000FF7B7B7BFF00000000000000FF7B7B7BFF0000
+      0000000000000000000000000000000000000000000000000000000000007B7B
+      7BFF000000FF000000FF7B7B7BFF000000007B7B7BFF000000FF000000FF0000
+      00FF7B7B7BFF00000000000000FF000000FF000000FF00000000000000000000
+      000000000000000000000000000000000000000000007B7B7BFF7B7B7BFF0000
+      00000000000000000000000000007B7B7BFF000000FF7B7B7BFF000000000000
+      00007B7B7BFF7B7B7BFF00000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000FF000000FF000000FF000000FF000000FF000000FF0000
+      00FF000000FF000000FF00000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000FFFFFF
+      FFFF00FFFFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFFFF000000FF7B7B7BFF0000
+      0000000000000000000000000000000000000000000000000000000000000000
+      00000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFF00FFFFFFFFFF
+      FFFFFFFFFFFF000000FF7B7B7BFF000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      00FF00FFFFFFFFFFFFFF00FFFFFFFFFFFFFF00FFFFFF000000FF7B7B7BFF0000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000FF00FFFFFFFFFFFFFF00FFFFFFFFFF
+      FFFF00FFFFFF000000FF7B7B7BFF000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000FFFFFFFFFF00FFFFFFFFFFFFFF00FFFFFF000000FF000000FF0000
+      00FF000000FF0000000000000000000000000000000000000000000000000000
+      000000000000000000000000000000000000000000FFFFFFFFFF00FFFFFFFFFF
+      FFFF00FFFFFFFFFFFFFF00FFFFFFFFFFFFFF00FFFFFF000000FF7B7B7BFF0000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000FF000000FF000000FF000000FF000000FF00FFFFFFFFFF
+      FFFF00FFFFFF000000FF7B7B7BFF000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000FF00FFFFFFFFFFFFFF00FFFFFF000000FF7B7B7BFF0000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000FFFFFF
+      FFFF00FFFFFF000000FF000000FF000000FF000000FF00000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      00000000000000000000000000FF00FFFFFF00FFFFFFFFFFFFFF00FFFFFF00FF
+      FFFF000000FF7B7B7BFF00000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      00FF000000FF000000FF000000FF00FFFFFF000000FF7B7B7BFF000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000FF00FF
+      FFFF000000FF7B7B7BFF00000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000FF000000FF7B7B7BFF000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      00FF000000FF7B7B7BFF00000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000000000000000000000000000FF7B7B7BFF000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      00000000000000000000000000000000000000000000000000007B7B7BFF7B00
+      00FF7B0000FF7B7B7BFF00000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      00000000000000000000000000007B0000FF7B0000FF7B0000FF7B0000FF0000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      00007B0000FF7B0000FF7B0000FF7B0000FF0000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000000000000000000000000000007B7B7BFF7B0000FF7B00
+      00FF7B7B7BFF0000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      00000000000000000000000000000000000000000000000000007B7B7BFF7B00
+      00FF7B0000FF7B0000FF7B7B7BFF000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000007B7B7BFF7B0000FF7B0000FF7B0000FF7B0000FF7B00
+      00FF7B7B7BFF0000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000007B00
+      00FF7B0000FF000000007B7B7BFF7B0000FF7B0000FF7B0000FF000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000007B7B7BFF00000000000000007B7B
+      7BFF7B0000FF7B0000FF7B0000FF000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000007B0000FF7B0000FF7B0000FF7B7B
+      7BFF000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      00007B7B7BFF7B0000FF7B0000FF7B7B7BFF0000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000007B7B7BFF7B0000FF7B0000FF7B00
+      00FF7B7B7BFF0000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000007B7B7BFF7B0000FF7B0000FF7B7B7BFF00000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000000000000000000000000000007B7B7BFF7B0000FF7B00
+      00FF7B0000FF0000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000007B0000FF7B0000FF7B0000FF7B7B7BFF000000000000
+      00007B7B7BFF0000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000007B00
+      00FF7B0000FF7B0000FF7B7B7BFF000000007B0000FF7B0000FF000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000007B7B7BFF7B0000FF7B0000FF7B00
+      00FF7B0000FF7B0000FF7B7B7BFF000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000007B7B7BFF7B0000FF7B0000FF7B0000FF7B7B7BFF0000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000000000000000000000000000FF000000FF000000FF0000
+      00FF000000FF000000FF000000FF000000FF000000FF000000FF000000FF0000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000FFFF0000FF000000FFFFFF00FFFFFF00FFFFFF00FFFFFF
+      00FFFFFF00FFFFFF00FFFFFF00FF000000FF0000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000FF0000
+      00FF000000FF000000FF000000FF000000FF000000FF000000FF000000FF0000
+      00FF000000FF0000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000FF00000000000000FFFFFFFFFFFFFF
+      FFFFFFFFFFFFFFFFFFFF7B7B7BFFFFFFFFFFFFFFFFFF000000FF000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000FFFFFFFFFF000000FFFFFFFFFF0000000000000000FFFFFFFF7B7B
+      7BFFFFFFFFFF00000000000000FF00000000000000FF000000FF000000FF7B7B
+      7BFF0000000000000000000000000000000000000000000000FF000000000000
+      00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7B7B7BFFFFFFFFFFFFFFFFFF0000
+      00FF00000000000000FF000000FF000000FF000000FF00000000000000000000
+      00000000000000000000000000FFFFFFFFFF000000FFFFFFFFFF000000000000
+      0000FFFFFFFF7B7B7BFFFFFFFFFF00000000000000FF00000000000000000000
+      00007B7B7BFF000000FF00000000000000000000000000000000000000000000
+      00FF00000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7B7B7BFFFFFF
+      FFFFFFFFFFFF000000FF00000000000000000000000000000000000000FF0000
+      000000000000000000000000000000000000000000FF00000000000000FFFFFF
+      FFFF0000000000000000FFFFFFFF7B7B7BFFFFFFFFFF00000000000000FF0000
+      0000000000000000000000000000000000FF0000000000000000000000000000
+      000000000000000000FF000000FF000000FF000000FF000000FF000000FF0000
+      00FF000000FF000000FF000000FF000000FF0000000000000000000000FF0000
+      00FF000000FF000000FF000000FF000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000000000000000000000000000FF000000FF000000FF0000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      00000000000000000000000000FF000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+      FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000
+      00FF000000000000000000000000000000000000000000000000000000000000
+      0000FFFFFFFF000000000000FFFF0000FFFF0000000000000000000000000000
+      00000000000000000000000000007B7B7BFF000000FF00000000000000000000
+      00000000000000000000000000000000000000000000FFFFFFFF000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      00007B7B7BFF000000FF00000000000000000000000000000000000000000000
+      00000000000000000000FFFFFFFF000000000000000000000000000000000000
+      000000000000000000000000000000000000000000007B7B7BFF000000FF0000
+      0000000000000000000000000000000000000000000000000000000000000000
+      00007B7B7BFF7B7B7BFF7B7B7BFF7B7B7BFF7B7B7BFF7B7B7BFF7B7B7BFF7B7B
+      7BFF7B7B7BFF7B7B7BFF7B7B7BFF000000FF0000000000000000000000000000
+      000000000000000000000000000000000000000000FF000000FF000000FF0000
+      00FF000000FF000000FF000000FF000000FF000000FF000000FF000000FF0000
+      00FF000000FF0000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      00000000000000000000000000000000000000000000000080FF000080FF0000
+      0000000000000000000000000000000000000000000000000000000000000000
+      80FF000080FF0000000000000000000000000000000000000000000000000000
+      00000000000000000000000080FF000080FF000080FF00000000000000000000
+      0000000000000000000000000000000080FF000080FF000080FF000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000080FF000080FF000080FF000000000000000000000000000000000000
+      80FF000080FF000080FF00000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000080FF0000
+      80FF000080FF0000000000000000000080FF000080FF000080FF000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000000000000000000000000080FF000080FF000080FF0000
+      80FF000080FF000080FF00000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      00000000000000000000000080FF000080FF000080FF000080FF000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      80FF000080FF000080FF000080FF000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000080FF000080FF000080FF000080FF0000
+      80FF000080FF0000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      80FF000080FF000080FF0000000000000000000080FF000080FF000080FF0000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000080FF000080FF000080FF000000000000
+      00000000000000000000000080FF000080FF000080FF00000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      80FF000080FF000080FF00000000000000000000000000000000000000000000
+      0000000080FF000080FF000080FF000000000000000000000000000000000000
+      000000000000000000000000000000000000000080FF000080FF000000000000
+      0000000000000000000000000000000000000000000000000000000080FF0000
+      80FF000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000008000FF008000FF000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      00000000000000000000000000000000000000000000008000FF008000FF0080
+      00FF008000FF0000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000008000FF008000FF008000FF008000FF00000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      00000000000000000000000000000000000000000000008000FF008000FF0080
+      00FF008000FF0000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000008000FF008000FF008000FF008000FF00000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      00000000000000000000000000000000000000000000008000FF008000FF0080
+      00FF008000FF0000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000008000FF0000000000000000000000000000
+      000000000000008000FF008000FF008000FF008000FF00000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000080
+      00FF008000FF008000FF000000000000000000000000008000FF008000FF0080
+      00FF008000FF0000000000000000000000000000000000000000000000000000
+      00000000000000000000000000000000000000000000008000FF008000FF0080
+      00FF00000000008000FF008000FF008000FF008000FF00000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000008000FF008000FF008000FF008000FF0080
+      00FF008000FF0000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000008000FF008000FF008000FF008000FF00000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000080
+      00FF008000FF0000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000000000000000000000000000000000000000000000
+    }
+  end
+  object DlgSave: TSaveDialog
+    Title = 'Save Query'
+    DefaultExt = '.*.qb'
+    Filter = 'QBuilder file (*.qb)|*.qb|All files (*.*)|*.*'
+    Options = [ofOverwritePrompt, ofHideReadOnly, ofPathMustExist]
+    left = 56
+    top = 37
+  end
+  object DlgOpen: TOpenDialog
+    Title = 'Open Query'
+    DefaultExt = '.qb'
+    Filter = 'QBuilder file (*.qb)|*.qb|All files (*.*)|*.*'
+    Options = [ofHideReadOnly, ofPathMustExist, ofFileMustExist]
+    left = 29
+    top = 37
+  end
+end

+ 2489 - 0
QBuilder.pas

@@ -0,0 +1,2489 @@
+{*******************************************************}
+{                                                       }
+{       Delphi Visual Component Library                 }
+{       QBuilder dialog component                       }
+{                                                       }
+{       Copyright (c) 1996-2003 Sergey Orlik            }
+{                                                       }
+{     Written by:                                       }
+{       Sergey Orlik                                    }
+{       product manager                                 }
+{       Russia, C.I.S. and Baltic States (former USSR)  }
+{       Borland Moscow office                           }
+{       Internet:  [email protected],             }
+{                  [email protected]                   }
+{                  http://www.fast-report.com           }
+{                                                       }
+{ Converted to Lazarus/Free Pascal by Jean Patrick      }
+{ Data: 14/02/2013                                      }
+{ E-mail: [email protected]                     }
+{                                                       }
+{ Modifications by Reinier Olislagers, 2014             }
+{*******************************************************}
+
+unit QBuilder;
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+interface
+
+uses
+  SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
+  Buttons, ExtCtrls, StdCtrls, ComCtrls, Menus, CheckLst, Grids,
+  DB, DBGrids, LMessages, LCLIntf, LCLType, LCLProc,
+  GraphType, InterfaceBase;
+
+type
+  TOQBbutton = (bSelectDBDialog, bOpenDialog, bSaveDialog,
+    bRunQuery, bSaveResultsDialog);
+  TOQBbuttons = set of TOQBbutton;
+
+  TOQBEngine = class;
+
+  { TOQBuilderDialog }
+
+  TOQBuilderDialog = class(TComponent)
+  private
+    FDatabase: string;
+    FSystemTables: Boolean;
+    FOQBForm: TForm;
+    FSQL: TStrings;
+    FOQBEngine: TOQBEngine;
+    FShowButtons: TOQBbuttons;
+    procedure SetOQBEngine(const Value: TOQBEngine);
+  protected
+    procedure Notification(AComponent: TComponent; Operation: TOperation); override;
+  public
+    constructor Create(AOwner: TComponent); override;
+    destructor Destroy; override;
+    function Execute: Boolean; virtual;
+    property SQL: TStrings read FSQL;
+    property SystemTables: Boolean read FSystemTables write FSystemTables default False;
+    property Database: string read FDatabase write FDatabase;
+  published
+    property OQBEngine: TOQBEngine read FOQBEngine write SetOQBEngine;
+    property ShowButtons: TOQBbuttons read FShowButtons write FShowButtons
+      default [bSelectDBDialog, bOpenDialog, bSaveDialog, bRunQuery, bSaveResultsDialog];
+  end;
+
+  TOQBEngine = class(TComponent)
+  private
+    FDatabaseName: string;
+    FUserName: string;
+    FPassword: string;
+    FShowSystemTables: Boolean;
+    FTableList: TStringList;
+    FAliasList: TStringList;
+    FFieldList: TStringList;
+    FSQL: TStringList;
+    FSQLcolumns: TStringList;
+    FSQLcolumns_table: TStringList;
+    FSQLcolumns_func: TStringList;
+    FSQLfrom: TStringList;
+    FSQLwhere: TStringList;
+    FSQLgroupby: TStringList;
+    FSQLorderby: TStringList;
+    FUseTableAliases: Boolean;
+    FOQBDialog: TOQBuilderDialog;
+    procedure SetShowSystemTables(const Value: Boolean);
+  protected
+    procedure Notification(AComponent: TComponent; Operation: TOperation); override;
+    procedure SetDatabaseName(const Value: string); virtual;
+    procedure SetUserName(const Value: string); virtual;
+    procedure SetPassword(const Value: string); virtual;
+    procedure SetQuerySQL(const Value: string); virtual; abstract;
+    procedure GenerateAliases; virtual;
+    // Read list of tables (system tables etc) into FTableList
+    procedure ReadTableList; virtual; abstract;
+    procedure ReadFieldList(const ATableName: string); virtual; abstract;
+  public
+    constructor Create(AOwner: TComponent); override;
+    destructor Destroy; override;
+    function SelectDatabase: Boolean; virtual; abstract;
+    function GenerateSQL: string; virtual;
+    procedure ClearQuerySQL; virtual; abstract;
+    function ResultQuery: TDataSet; virtual; abstract;
+    procedure OpenResultQuery; virtual; abstract;
+    procedure CloseResultQuery; virtual; abstract;
+    procedure SaveResultQueryData; virtual; abstract;
+    // All tables in the database
+    property TableList: TStringList read FTableList;
+    property AliasList: TStringList read FAliasList;
+    property FieldList: TStringList read FFieldList;
+    property SQL: TStringList read FSQL;
+    property SQLcolumns: TStringList read FSQLcolumns;
+    property SQLcolumns_table: TStringList read FSQLcolumns_table;
+    property SQLcolumns_func: TStringList read FSQLcolumns_func;
+    property SQLfrom: TStringList read FSQLfrom;
+    property SQLwhere: TStringList read FSQLwhere;
+    property SQLgroupby: TStringList read FSQLgroupby;
+    property SQLorderby: TStringList read FSQLorderby;
+    property UserName: string  read FUserName write SetUserName;
+    property Password: string  read FPassword write SetPassword;
+  published
+    property DatabaseName: string read FDatabaseName write SetDatabaseName;
+    property ShowSystemTables: Boolean read FShowSystemTables write SetShowSystemTables default False;
+    property UseTableAliases: Boolean read FUseTableAliases write FUseTableAliases default True;
+  end;
+
+type
+  TArr = array [0..0] of Integer;
+  PArr = ^TArr;
+
+  { TOQBLbx }
+
+  TOQBLbx = class(TCheckListBox)
+  private
+    FArrBold: PArr;
+    FLoading: Boolean;
+//    procedure CNDrawItem(var Message: TWMDrawItem); message CN_DrawItem;
+    procedure WMLButtonDown(var Message: TLMLButtonDblClk); message LM_LBUTTONDOWN;
+    procedure WMRButtonDown(var Message: TLMRButtonDblClk); message LM_RBUTTONDOWN;
+    function GetCheckW: Integer;
+    procedure AllocArrBold;
+    procedure SelectItemBold(Item: Integer);
+    procedure UnSelectItemBold(Item: Integer);
+    function GetItemY(Item: Integer): Integer;
+  public
+    constructor Create(AOwner: TComponent); override;
+    destructor Destroy; override;
+//    procedure ClickCheck; override;
+    procedure ItemClick(const AIndex: Integer); override;
+  end;
+
+  TOQBTable = class(TPanel)
+  private
+    ScreenDC: HDC;
+    OldX: Integer;
+    OldY: Integer;
+    OldLeft: Integer;
+    OldTop: Integer;
+    ClipRgn: HRGN;
+    ClipRect: TRect;
+    MoveRect: TRect;
+    Moving: Boolean;
+    FCloseBtn: TSpeedButton;
+    FUnlinkBtn: TSpeedButton;
+    FLbx: TOQBLbx;
+    FTableName: string;
+    FTableAlias: string;
+    PopMenu: TPopupMenu;
+    procedure WMRButtonDown(var Message: TLMRButtonDblClk); message LM_RBUTTONDOWN;
+    function Activate(const ATableName: string; X, Y: Integer): Boolean;
+    function GetRowY(FldN: Integer):Integer;
+    procedure _CloseBtn(Sender: TObject);
+    procedure _UnlinkBtn(Sender: TObject);
+    procedure _SelectAll(Sender: TObject);
+    procedure _UnSelectAll(Sender: TObject);
+    procedure _DragOver(Sender, Source: TObject; X, Y: Integer;
+      State: TDragState; var Accept: Boolean);
+    procedure _DragDrop(Sender, Source: TObject; X, Y: Integer);
+  protected
+    procedure SetParent(AParent: TWinControl); override;
+    procedure MouseDown(Button: TMouseButton; Shift: TShiftState;
+      X, Y: Integer); override;
+    procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
+    procedure MouseUp(Button: TMouseButton; Shift: TShiftState;
+      X, Y: Integer); override;
+    property Align;
+  public
+    constructor Create(AOwner: TComponent); override;
+    procedure Paint; override;
+  end;
+
+  { TOQBLink }
+
+  TOQBLink = class(TShape)
+  private
+    Tbl1: TOQBTable;
+    Tbl2: TOQBTable;
+    FldN1: Integer;
+    FldN2: Integer;
+    FldNam1: string;
+    FldNam2: string;
+    FLinkOpt: Integer;
+    FLinkType: Integer;
+    LnkX: Byte;
+    LnkY: Byte;
+    Rgn: HRgn;
+    PopMenu: TPopupMenu;
+    procedure _Click(X, Y: Integer);
+    procedure CMHitTest(var Message: TCMHitTest); message CM_HitTest;
+    function ControlAtPos(const Pos: TPoint): TControl;
+    function PtInRegion(RGN: HRGN; X, Y: Integer) : Boolean;
+  public
+    constructor Create(AOwner: TComponent); override;
+    destructor Destroy; override;
+    procedure WndProc(var Message: TLMessage); override;
+    procedure Paint; override;
+  end;
+
+  TOQBArea = class(TScrollBox)
+  public
+    procedure CreateParams(var Params: TCreateParams); override;
+    procedure SetOptions(Sender: TObject);
+    procedure InsertTable(X, Y: Integer);
+    function InsertLink(_tbl1, _tbl2: TOQBTable; _fldN1, _fldN2: Integer): TOQBLink;
+    function FindTable(const TableName: string): TOQBTable;
+    function FindLink(Link: TOQBLink): Boolean;
+    function FindOtherLink(Link: TOQBLink; Tbl: TOQBTable; FldN: Integer): Boolean;
+    procedure ReboundLink(Link: TOQBLink);
+    procedure ReboundLinks4Table(ATable: TOQBTable);
+    procedure Unlink(Sender: TObject);
+    procedure UnlinkTable(ATable: TOQBTable);
+    procedure _DragOver(Sender, Source: TObject; X, Y: Integer;
+      State: TDragState; var Accept: Boolean);
+    procedure _DragDrop(Sender, Source: TObject; X, Y: Integer);
+  end;
+
+  TOQBGrid = class(TStringGrid)
+  public
+    CurrCol: Integer;
+    IsEmpty: Boolean;
+    procedure CreateParams(var Params: TCreateParams); override;
+    procedure WndProc(var Message: TLMessage); override;
+    function MaxSW(const s1, s2: string): Integer;
+    procedure InsertDefault(aCol: Integer);
+    procedure Insert(aCol: Integer; const aField, aTable: string);
+    function FindColumn(const sCol: string): Integer;
+    function FindSameColumn(aCol: Integer): Boolean;
+    procedure RemoveColumn(aCol: Integer);
+    procedure RemoveColumn4Tbl(const Tbl: string);
+    procedure ClickCell(X, Y: Integer);
+    function SelectCell(ACol, ARow: Integer): Boolean; override;
+    procedure _DragOver(Sender, Source: TObject; X, Y: Integer;
+      State: TDragState; var Accept: Boolean);
+    procedure _DragDrop(Sender, Source: TObject; X, Y: Integer);
+  end;
+
+  TOQBForm = class(TForm)
+    QBPanel: TPanel;
+    Pages: TPageControl;
+    TabColumns: TTabSheet;
+    QBTables: TListBox;
+    VSplitter: TSplitter;
+    mnuTbl: TPopupMenu;
+    Remove1: TMenuItem;
+    mnuFunc: TPopupMenu;
+    Nofunction1: TMenuItem;
+    N1: TMenuItem;
+    Average1: TMenuItem;
+    Count1: TMenuItem;
+    Minimum1: TMenuItem;
+    Maximum1: TMenuItem;
+    Sum1: TMenuItem;
+    mnuGroup: TPopupMenu;
+    Group1: TMenuItem;
+    mnuSort: TPopupMenu;
+    Sort1: TMenuItem;
+    N2: TMenuItem;
+    Ascending1: TMenuItem;
+    Descending1: TMenuItem;
+    mnuShow: TPopupMenu;
+    Show1: TMenuItem;
+    HSplitter: TSplitter;
+    TabSQL: TTabSheet;
+    MemoSQL: TMemo;
+    TabResults: TTabSheet;
+    ResDBGrid: TDBGrid;
+    ResDataSource: TDataSource;
+    QBBar: TToolBar;
+    btnNew: TToolButton;
+    btnOpen: TToolButton;
+    btnSave: TToolButton;
+    ToolButton1: TToolButton;
+    btnTables: TToolButton;
+    ToolImages: TImageList;
+    btnPages: TToolButton;
+    ToolButton2: TToolButton;
+    DlgSave: TSaveDialog;
+    DlgOpen: TOpenDialog;
+    btnDB: TToolButton;
+    btnSQL: TToolButton;
+    btnResults: TToolButton;
+    ToolButton3: TToolButton;
+    btnAbout: TToolButton;
+    btnSaveResults: TToolButton;
+    btnOK: TToolButton;
+    btnCancel: TToolButton;
+    ToolButton6: TToolButton;
+    procedure mnuFunctionClick(Sender: TObject);
+    procedure mnuGroupClick(Sender: TObject);
+    procedure mnuRemoveClick(Sender: TObject);
+    procedure mnuShowClick(Sender: TObject);
+    procedure mnuSortClick(Sender: TObject);
+    procedure btnNewClick(Sender: TObject);
+    procedure btnOpenClick(Sender: TObject);
+    procedure btnSaveClick(Sender: TObject);
+    procedure btnTablesClick(Sender: TObject);
+    procedure btnPagesClick(Sender: TObject);
+    procedure btnDBClick(Sender: TObject);
+    procedure btnSQLClick(Sender: TObject);
+    procedure btnResultsClick(Sender: TObject);
+    procedure btnAboutClick(Sender: TObject);
+    procedure btnSaveResultsClick(Sender: TObject);
+    procedure btnOKClick(Sender: TObject);
+    procedure btnCancelClick(Sender: TObject);
+  protected
+    QBDialog: TOQBuilderDialog;
+    QBArea: TOQBArea;
+    QBGrid: TOQBGrid;
+    procedure CreateParams(var Params: TCreateParams); override;
+    procedure ClearAll;
+    procedure OpenDatabase;
+    procedure SelectDatabase;
+  end;
+
+implementation
+
+{$R QBBUTTON.RES}
+
+uses
+  QBLnkFrm, QBAbout;
+
+  {$R *.lfm}
+
+resourcestring
+  sMainCaption = 'QBuilder';
+  sNotValidTableParent = 'Parent must be TScrollBox or its descendant.';
+
+const
+  cFld = 0;
+  cTbl = 1;
+  cShow = 2;
+  cSort = 3;
+  cFunc = 4;
+  cGroup = 5;
+
+  sShow = 'Show';
+  sGroup = 'Group';
+  sSort: array [1..3] of string =
+    ('',
+     'Asc',
+     'Desc');
+  sFunc: array [1..6] of string =
+    ('',
+     'Avg',
+     'Count',
+     'Max',
+     'Min',
+     'Sum');
+
+  sLinkOpt: array [0..5] of string =
+    ('=',
+     '<',
+     '>',
+     '=<',
+     '=>',
+     '<>');
+
+  sOuterJoin: array [1..3] of string =
+    (' LEFT OUTER JOIN ',
+     ' RIGHT OUTER JOIN ',
+     ' FULL OUTER JOIN ');
+
+  Hand = 15;
+  Hand2 = 12;
+
+  QBSignature = '# QBuilder';
+
+
+{ TQueryBuilderDialog}
+
+constructor TOQBuilderDialog.Create(AOwner: TComponent);
+begin
+  inherited;
+  FSystemTables := False;
+  FShowButtons := [bSelectDBDialog, bOpenDialog, bSaveDialog,
+    bRunQuery, bSaveResultsDialog];
+  FSQL := TStringList.Create;
+end;
+
+destructor TOQBuilderDialog.Destroy;
+begin
+  if FSQL <> nil then
+    FSQL.Free;
+  FOQBEngine := nil;
+  inherited;
+end;
+
+function TOQBuilderDialog.Execute: Boolean;
+begin
+  Result := False;
+  if (not Assigned(FOQBForm)) and Assigned((FOQBEngine)) then
+  begin
+    TOQBForm(FOQBForm) := TOQBForm.Create(Application);
+    TOQBForm(FOQBForm).QBDialog := Self;
+    TOQBForm(FOQBForm).btnDB.Visible := bSelectDBDialog in FShowButtons;
+    TOQBForm(FOQBForm).btnOpen.Visible := bOpenDialog in FShowButtons;
+    TOQBForm(FOQBForm).btnSave.Visible := bSaveDialog in FShowButtons;
+    TOQBForm(FOQBForm).btnResults.Visible := bRunQuery in FShowButtons;
+    TOQBForm(FOQBForm).btnSaveResults.Visible := bSaveResultsDialog in FShowButtons;
+    if OQBEngine.DatabaseName <> EmptyStr then
+      TOQBForm(FOQBForm).OpenDatabase else
+      TOQBForm(FOQBForm).SelectDatabase;
+
+    if TOQBForm(FOQBForm).ShowModal = mrOk then
+    begin
+      FSQL.Assign(TOQBForm(FOQBForm).MemoSQL.Lines);
+      Result := True;
+    end;
+
+    OQBEngine.CloseResultQuery;
+    FOQBForm.Free;
+    FOQBForm := nil;
+  end;
+end;
+
+procedure TOQBuilderDialog.Notification(AComponent: TComponent;
+  Operation: TOperation);
+begin
+  inherited;
+  if (AComponent = FOQBEngine) and (Operation = opRemove) then
+    FOQBEngine := nil;
+end;
+
+procedure TOQBuilderDialog.SetOQBEngine(const Value: TOQBEngine);
+begin
+  if FOQBEngine <> nil then
+    FOQBEngine.FOQBDialog := nil;
+  FOQBEngine := Value;
+  if FOQBEngine <> nil then
+  begin
+    FOQBEngine.FOQBDialog := Self;
+    FOQBEngine.FreeNotification(Self);
+  end;
+end;
+
+
+{ TOQBEngine }
+
+constructor TOQBEngine.Create(AOwner: TComponent);
+begin
+  inherited;
+  FShowSystemTables := False;
+  FTableList := TStringList.Create;
+  FAliasList := TStringList.Create;
+  FFieldList := TStringList.Create;
+  FSQL := TStringList.Create;
+  FSQLcolumns := TStringList.Create;
+  FSQLcolumns_table := TStringList.Create;
+  FSQLcolumns_func := TStringList.Create;
+  FSQLfrom := TStringList.Create;
+  FSQLwhere := TStringList.Create;
+  FSQLgroupby := TStringList.Create;
+  FSQLorderby := TStringList.Create;
+  FUseTableAliases := True;
+end;
+
+destructor TOQBEngine.Destroy;
+begin
+  FSQL.Free;
+  FSQLcolumns.Free;
+  FSQLcolumns_table.Free;
+  FSQLcolumns_func.Free;
+  FSQLfrom.Free;
+  FSQLwhere.Free;
+  FSQLgroupby.Free;
+  FSQLorderby.Free;
+  FFieldList.Free;
+  FAliasList.Free;
+  FTableList.Free;
+  FreeNotification(Self);
+  inherited;
+end;
+
+procedure TOQBEngine.Notification(AComponent: TComponent;
+  Operation: TOperation);
+begin
+  inherited;
+  if (AComponent = FOQBDialog) and (Operation = opRemove) then
+    FOQBDialog := nil;
+end;
+
+procedure TOQBEngine.SetDatabaseName(const Value: string);
+begin
+  TableList.Clear;
+  FDatabaseName := Value;
+  if ResultQuery.Active then
+    ResultQuery.Close;
+end;
+
+procedure TOQBEngine.SetUserName(const Value: string);
+begin
+  FUserName := Value;
+end;
+
+procedure TOQBEngine.SetPassword(const Value: string);
+begin
+  FPassword := Value;
+end;
+
+procedure TOQBEngine.SetShowSystemTables(const Value: Boolean);
+begin
+  if FShowSystemTables <> Value then
+    FShowSystemTables := Value;
+end;
+
+procedure TOQBEngine.GenerateAliases;
+var
+  i, j: Integer;
+  s, s1: string;
+begin
+  FAliasList.Clear;
+  for i := 0 to FTableList.Count - 1 do
+  begin
+    s := ' ';
+    s[1] := FTableList[i][1]; // get the first character [1] of the table name [i]
+    if FAliasList.IndexOf(s) = -1 then
+      FAliasList.Add(s)
+    else
+    begin
+      j := 1;
+      repeat
+        Inc(j);
+        s1 := s + IntToStr(j);
+      until FAliasList.IndexOf(s1) = -1;
+      FAliasList.Add(s1);
+    end;
+  end;
+end;
+
+function TOQBEngine.GenerateSQL: string;
+var
+  s: string;
+  i: Integer;
+begin
+  SQL.Clear;
+
+  s := 'SELECT  ';
+  for i := 0 to SQLcolumns.Count - 1 do
+  begin
+    if SQLcolumns_func[i] = EmptyStr then
+      s := s + SQLcolumns[i] else
+      s := s + SQLcolumns_func[i] + '(' + SQLcolumns[i] + ')';
+    if (i < SQLcolumns.Count - 1) then
+      s := s + ', ';
+    if (Length(s) > 70) or (i = SQLcolumns.Count - 1) then
+    begin
+      SQL.Add(s);
+      s := '  ';
+    end;
+  end;
+
+  s := 'FROM  ';
+  for i := 0 to SQLfrom.Count - 1 do
+  begin
+    s := s + SQLfrom[i];
+    if (i < SQLfrom.Count - 1) then
+      s := s + ', ';
+    if (Length(s) > 70) or (i = SQLfrom.Count - 1) then
+    begin
+      SQL.Add(s);
+      s := '  ';
+    end;
+  end;
+
+  s := 'WHERE  ';
+  for i := 0 to SQLwhere.Count - 1 do
+  begin
+    if (i < SQLwhere.Count - 1) then
+      s := s + SQLwhere[i] + ' AND ' else
+      s := s + SQLwhere[i];
+    if (Length(s) > 70) or (i = SQLwhere.Count - 1) then
+    begin
+      SQL.Add(s);
+      s := '  ';
+    end;
+  end;
+
+  s := 'GROUP BY  ';
+  for i := 0 to SQLgroupby.Count - 1 do
+  begin
+    if (i < SQLgroupby.Count - 1) then
+      s := s + SQLgroupby[i] + ', ' else
+      s := s + SQLgroupby[i];
+    if (Length(s) > 70) or (i = SQLgroupby.Count - 1) then
+    begin
+      SQL.Add(s);
+      s := '  ';
+    end;
+  end;
+
+  s := 'ORDER BY  ';
+  for i := 0 to SQLorderby.Count - 1 do
+  begin
+    if (i < SQLorderby.Count - 1) then
+      s := s + SQLorderby[i] + ', ' else
+      s := s + SQLorderby[i];
+    if (Length(s) > 70) or (i = SQLorderby.Count - 1) then
+    begin
+      SQL.Add(s);
+      s := '  ';
+    end;
+  end;
+
+  Result := SQL.Text;
+end;
+
+
+{ TOQBLbx }
+
+constructor TOQBLbx.Create(AOwner: TComponent);
+begin
+  inherited;
+  Style := lbStandard;
+  ParentFont := False;
+  Font.Style := [];
+  Font.Size := 8;
+  FArrBold := nil;
+  FLoading := False;
+end;
+
+destructor TOQBLbx.Destroy;
+begin
+  if FArrBold <> nil then
+    FreeMem(FArrBold);
+  inherited;
+end;
+
+function TOQBLbx.GetCheckW: Integer;
+begin
+  Result := GetCheckW;
+end;
+
+{procedure TOQBLbx.CNDrawItem(var Message: TWMDrawItem);
+begin
+  with Message.DrawItemStruct^ do
+  begin
+    rcItem.Left := rcItem.Left + GetCheckW;  //*** check
+    Canvas.Font := Font;
+    Canvas.Brush := Brush;
+    if (Integer(itemID) >= 0) and (Integer(itemID) <= Items.Count - 1) then
+    begin
+      if (FArrBold <> nil) then
+        if FArrBold^[Integer(itemID)] = 1 then
+          Canvas.Font.Style := [fsBold];
+      DrawItem(itemID, rcItem, []);
+      if (FArrBold <> nil) then
+        if FArrBold^[Integer(itemID)] = 1 then
+          Canvas.Font.Style := [];
+    end
+    else
+      Canvas.FillRect(rcItem);
+  end;
+end;}
+
+procedure TOQBLbx.WMLButtonDown(var Message: TLMLButtonDblClk);
+begin
+  inherited;
+  BeginDrag(False);
+end;
+
+procedure TOQBLbx.WMRButtonDown(var Message: TLMRButtonDblClk);
+var
+  pnt: TPoint;
+begin
+  inherited;
+  pnt.X := Message.XPos;
+  pnt.Y := Message.YPos;
+  pnt := ClientToScreen(pnt);
+  PopupMenu.Popup(pnt.X, pnt.Y);
+end;
+
+{procedure TOQBLbx.ClickCheck;
+var
+  iCol: Integer;
+begin
+  inherited;
+  if FLoading then
+    Exit;
+
+  if Checked[ItemIndex] then
+  begin
+    TOQBForm(GetParentForm(Self)).QBGrid.Insert(
+      TOQBForm(GetParentForm(Self)).QBGrid.ColCount,
+      Items[ItemIndex], TOQBTable(Parent).FTableName);
+  end
+  else
+  begin
+    iCol := TOQBForm(GetParentForm(Self)).QBGrid.FindColumn(Items[ItemIndex]);
+    while iCol <> -1 do
+    begin
+      TOQBForm(GetParentForm(Self)).QBGrid.RemoveColumn(iCol);
+      iCol := TOQBForm(GetParentForm(Self)).QBGrid.FindColumn(Items[ItemIndex]);
+    end;
+  end;
+
+  TOQBForm(GetParentForm(Self)).QBGrid.Refresh; // StringGrid bug
+end; }
+
+procedure TOQBLbx.ItemClick(const AIndex: Integer);
+var
+  iCol: Integer;
+begin
+  inherited ItemClick(AIndex);
+  if FLoading then
+    Exit;
+
+  if Checked[ItemIndex] then
+  begin
+    TOQBForm(GetParentForm(Self)).QBGrid.Insert(
+      TOQBForm(GetParentForm(Self)).QBGrid.ColCount,
+      Items[ItemIndex], TOQBTable(Parent).FTableName);
+  end
+  else
+  begin
+    iCol := TOQBForm(GetParentForm(Self)).QBGrid.FindColumn(Items[ItemIndex]);
+    while iCol <> -1 do
+    begin
+      TOQBForm(GetParentForm(Self)).QBGrid.RemoveColumn(iCol);
+      iCol := TOQBForm(GetParentForm(Self)).QBGrid.FindColumn(Items[ItemIndex]);
+    end;
+  end;
+
+  TOQBForm(GetParentForm(Self)).QBGrid.Refresh; // StringGrid bug
+end;
+
+procedure TOQBLbx.AllocArrBold;
+begin
+  FArrBold := AllocMem(Items.Count * SizeOf(Integer));
+end;
+
+procedure TOQBLbx.SelectItemBold(Item: Integer);
+begin
+  if FArrBold <> nil then
+    if FArrBold[Item] = 0 then
+      FArrBold^[Item] := 1;
+end;
+
+procedure TOQBLbx.UnSelectItemBold(Item: Integer);
+begin
+  if FArrBold <> nil then
+    if FArrBold[Item] = 1 then
+      FArrBold^[Item] := 0;
+end;
+
+function TOQBLbx.GetItemY(Item: Integer): Integer;
+begin
+  Result := Item * ItemHeight + ItemHeight div 2  + 1;
+end;
+
+
+{ TOQBTable }
+
+constructor TOQBTable.Create(AOwner: TComponent);
+var
+  mnuArr: array [1..5] of TMenuItem;
+begin
+  inherited;
+  Visible := False;
+  ShowHint := True;
+  BevelInner := bvRaised;
+  BevelOuter := bvRaised;
+  BorderWidth := 1;
+  FCloseBtn := TSpeedButton.Create(Self);
+  FCloseBtn.Parent := Self;
+  FCloseBtn.Hint := 'Close';
+  FUnlinkBtn := TSpeedButton.Create(Self);
+  FUnlinkBtn.Parent := Self;
+  FUnlinkBtn.Hint := 'Unlink all';
+
+  FLbx := TOQBLbx.Create(Self);
+  FLbx.Parent := Self;
+  FLbx.Style := lbStandard;
+  FLbx.Align := alBottom;
+  FLbx.TabStop := False;
+  FLbx.Visible := False;
+
+  mnuArr[1] := NewItem('Select All', 0, False, True, _SelectAll, 0, 'mnuSelectAll');
+  mnuArr[2] := NewItem('Unselect All', 0, False, True, _UnSelectAll, 0, 'mnuUnSelectAll');
+  mnuArr[3] := NewLine;
+  mnuArr[4] := NewItem('Unlink', 0, False, True, _UnlinkBtn, 0, 'mnuUnLink');
+  mnuArr[5] := NewItem('Close', 0, False, True, _CloseBtn, 0, 'mnuClose');
+  PopMenu := NewPopupMenu(Self, 'mnu', paLeft, False, mnuArr);
+  PopMenu.PopupComponent := Self;
+
+  FLbx.PopupMenu := PopMenu;
+end;
+
+procedure TOQBTable.WMRButtonDown(var Message: TLMLButtonDblClk);
+var
+  pnt: TPoint;
+begin
+  inherited;
+  pnt.X := Message.XPos;
+  pnt.Y := Message.YPos;
+  pnt := ClientToScreen(pnt);
+  PopMenu.Popup(pnt.X, pnt.Y);
+end;
+
+procedure TOQBTable.Paint;
+begin
+  inherited;
+  if TOQBForm(GetParentForm(Self)).QBDialog.OQBEngine.UseTableAliases then
+    Canvas.TextOut(4, 4, FTableName + ' : ' + FTableAlias) else
+    Canvas.TextOut(4, 4, FTableName);
+end;
+
+function TOQBTable.GetRowY(FldN: Integer): Integer;
+var
+  pnt: TPoint;
+begin
+  pnt.X := FLbx.Left;
+  pnt.Y := FLbx.Top + FLbx.GetItemY(FldN);
+  pnt := Parent.ScreenToClient(ClientToScreen(pnt));
+  Result := pnt.Y;
+end;
+
+function TOQBTable.Activate(const ATableName: string; X, Y: Integer): Boolean;
+var
+  i: Integer;
+  W, W1: Integer;
+  OQBEngine: TOQBEngine;
+begin
+  Result := False;
+  Top := Y;
+  Left := X;
+  Font.Style := [fsBold];
+  Font.Size := 8;
+  Canvas.Font := Font;
+  Hint := ATableName;
+
+  FTableName := ATableName;
+  FTableAlias := TOQBForm(GetParentForm(Self)).QBDialog.FOQBEngine.AliasList[
+    TOQBForm(GetParentForm(Self)).QBDialog.FOQBEngine.TableList.IndexOf(ATableName)];
+  OQBEngine := TOQBForm(GetParentForm(Self)).QBDialog.FOQBEngine;
+  try
+    OQBEngine.ReadFieldList(ATableName);
+    FLbx.Items.Assign(OQBEngine.FieldList);
+  except
+    on E: EDatabaseError do
+      begin
+        ShowMessage(E.Message);
+        Exit;
+      end;
+  end;
+
+  FLbx.AllocArrBold;
+  FLbx.ParentFont := False;
+  FLbx.TabStop := False;
+
+  case WidgetSet.LCLPlatform of
+    lpGtk:   FLbx.Height := ((FLbx.ItemHeight + 6) * FLbx.Items.Count) + 4;
+    lpGtk2:  FLbx.Height := ((FLbx.ItemHeight + 6) * FLbx.Items.Count) + 4;
+    lpWin32: FLbx.Height := ((FLbx.ItemHeight + 4) * FLbx.Items.Count) + 4;
+    lpCarbon:FLbx.Height := ((FLbx.ItemHeight + 8) * FLbx.Items.Count) + 4;
+    lpQT:    FLbx.Height := ((FLbx.ItemHeight + 8) * FLbx.Items.Count) + 4;
+    lpfpGUI: FLbx.Height := ((FLbx.ItemHeight + 8) * FLbx.Items.Count) + 4;
+  else
+    FLbx.Height := ((FLbx.ItemHeight + 8) * FLbx.Items.Count) + 4;
+  end;
+
+  Height := FLbx.Height + 22;
+  W := 110;
+  for i := 0 to FLbx.Items.Count - 1 do
+  begin
+    W1 := Canvas.TextWidth(FLbx.Items[i]);
+    if W < W1 then
+      W := W1;
+  end;
+  Width := W + 20 + 22;//FLbx.GetCheckW; //*** check
+
+  if TOQBForm(GetParentForm(Self)).QBDialog.OQBEngine.UseTableAliases then
+  begin
+    if Canvas.TextWidth(FTableName + ' : ' + FTableAlias) > Width - 34 then
+      Width := Canvas.TextWidth(FTableName + ' : ' + FTableAlias) + 34
+  end
+  else if Canvas.TextWidth(FTableName) > Width - 34 then
+    Width := Canvas.TextWidth(FTableName) + 34;
+
+  Color := clForm;
+  FLbx.Visible := True;
+  FLbx.OnDragOver := _DragOver;
+  FLbx.OnDragDrop := _DragDrop;
+  FCloseBtn.Top := 4;
+  FCloseBtn.Left := Self.ClientWidth - 16;
+  FCloseBtn.Width := 12;
+  FCloseBtn.Height := 12;
+  FCloseBtn.Glyph.LoadFromResourceName(HInstance, 'CLOSEBMP');;
+  FCloseBtn.Margin := -1;
+  FCloseBtn.Spacing := 0;
+  FCloseBtn.OnClick := _CloseBtn;
+  FCloseBtn.Visible := True;
+  FUnlinkBtn.Top := 4;
+  FUnlinkBtn.Left := Self.ClientWidth - 16 - FCloseBtn.Width;
+  FUnlinkBtn.Width := 12;
+  FUnlinkBtn.Height := 12;
+  FUnlinkBtn.Glyph.LoadFromResourceName(HInstance, 'UNLINKBMP');;
+  FUnlinkBtn.Margin := -1;
+  FUnlinkBtn.Spacing := 0;
+  FUnlinkBtn.OnClick := _UnlinkBtn;
+  FUnlinkBtn.Visible := True;
+  Visible := True;
+  Result := True;
+end;
+
+procedure TOQBTable._CloseBtn(Sender: TObject);
+begin
+  TOQBArea(Parent).UnlinkTable(Self);
+  TOQBForm(GetParentForm(Self)).QBGrid.RemoveColumn4Tbl(FTableName);
+  Parent.RemoveControl(Self);
+  Free;
+end;
+
+procedure TOQBTable._UnlinkBtn(Sender: TObject);
+begin
+  TOQBArea(Parent).UnlinkTable(Self);
+end;
+
+procedure TOQBTable._SelectAll(Sender: TObject);
+var
+  i: Integer;
+begin
+  if FLbx.Items.Count = 1 then
+    Exit;
+  for i := 1 to (FLbx.Items.Count - 1) do
+  begin
+    FLbx.Checked[i] := True;
+    TOQBForm(GetParentForm(Self)).QBGrid.Insert(
+      TOQBForm(GetParentForm(Self)).QBGrid.ColCount,
+      FLbx.Items[i], FTableName);
+  end;
+end;
+
+procedure TOQBTable._UnSelectAll(Sender: TObject);
+var
+  i: Integer;
+begin
+  if FLbx.Items.Count = 1 then
+    Exit;
+  for i := 1 to (FLbx.Items.Count - 1) do
+  begin
+    FLbx.Checked[i] := False;
+    TOQBForm(GetParentForm(Self)).QBGrid.RemoveColumn4Tbl(FTableName);
+  end;
+end;
+
+procedure TOQBTable._DragOver(Sender, Source: TObject; X, Y: Integer;
+  State: TDragState; var Accept: Boolean);
+begin
+  if (Source is TCustomListBox) and (TWinControl(Source).Parent is TOQBTable) then
+    Accept := True;
+end;
+
+procedure TOQBTable._DragDrop(Sender, Source: TObject; X, Y: Integer);
+var
+  nRow: Integer;
+  hRow: Integer;
+begin
+  if (Source is TCustomListBox) then
+  begin
+    if (TWinControl(Source).Parent is TOQBTable) then
+    begin
+      hRow := FLbx.ItemHeight;
+      if hRow <> 0 then
+        nRow := Y div hRow else
+        nRow := 0;
+      if nRow > FLbx.Items.Count - 1 then
+        nRow := FLbx.Items.Count - 1;
+      // handler for target's '*' row
+      if nRow = 0 then
+        Exit;
+      // handler for source's '*' row
+      if TOQBTable(TWinControl(Source).Parent).FLbx.ItemIndex = 0 then
+        Exit;
+      if Source <> FLbx then
+        TOQBArea(Parent).InsertLink(
+          TOQBTable(TWinControl(Source).Parent), Self,
+          TOQBTable(TWinControl(Source).Parent).FLbx.ItemIndex, nRow)
+      else if nRow <> FLbx.ItemIndex then
+        TOQBArea(Parent).InsertLink(Self, Self, FLbx.ItemIndex, nRow);
+    end
+    else
+      if Source = TOQBForm(GetParentForm(Self)).QBTables then
+      begin
+        X := X + Left + TWinControl(Sender).Left;
+        Y := Y + Top + TWinControl(Sender).Top;
+        TOQBArea(Parent).InsertTable(X, Y);
+      end;
+  end
+end;
+
+procedure TOQBTable.SetParent(AParent: TWinControl);
+begin
+  if (AParent <> nil) and (not (AParent is TScrollBox)) then
+    raise Exception.Create(sNotValidTableParent);
+  inherited;
+end;
+
+procedure TOQBTable.MouseDown(Button: TMouseButton; Shift: TShiftState;
+  X, Y: Integer);
+begin
+  inherited;
+  BringToFront;
+  if (Button = mbLeft) then
+  begin
+    SetCapture(Self.Handle);
+    ScreenDC := GetDC(0);
+
+    ClipRect := Bounds(Parent.Left, Parent.Top, Parent.Width, Parent.Height);
+    ClipRect.TopLeft := Parent.Parent.ClientToScreen(ClipRect.TopLeft);
+    ClipRect.BottomRight := Parent.Parent.ClientToScreen(ClipRect.BottomRight);
+    ClipRgn := CreateRectRgn(ClipRect.Left, ClipRect.Top, ClipRect.Right, ClipRect.Bottom);
+    SelectClipRgn(ScreenDC, ClipRgn);
+//    ClipCursor(@ClipRect);
+    OldX := X;
+    OldY := Y;
+    OldLeft := X;
+    OldTop := Y;
+    MoveRect := Rect(Self.Left, Self.Top, Self.Left + Self.Width, Self.Top + Self.Height);
+    MoveRect.TopLeft := Parent.ClientToScreen(MoveRect.TopLeft);
+    MoveRect.BottomRight := Parent.ClientToScreen(MoveRect.BottomRight);
+    DrawFocusRect(ScreenDC, MoveRect);
+    Moving := True;
+  end;
+end;
+
+procedure TOQBTable.MouseMove(Shift: TShiftState; X, Y: Integer);
+begin
+  inherited;
+  if Moving then
+  begin
+    DrawFocusRect(ScreenDC, MoveRect);
+    OldX := X;
+    OldY := Y;
+    MoveRect := Rect(Self.Left + OldX - OldLeft, Self.Top + OldY - OldTop,
+      Self.Left + Self.Width + OldX - OldLeft, Self.Top + Self.Height + OldY - OldTop);
+    MoveRect.TopLeft := Parent.ClientToScreen(MoveRect.TopLeft);
+    MoveRect.BottomRight := Parent.ClientToScreen(MoveRect.BottomRight);
+    DrawFocusRect(ScreenDC, MoveRect);
+  end;
+end;
+
+procedure TOQBTable.MouseUp(Button: TMouseButton; Shift: TShiftState;
+  X, Y: Integer);
+begin
+  inherited;
+  if Button = mbLeft then
+  begin
+    ReleaseCapture;
+    DrawFocusRect(ScreenDC, MoveRect);
+    if (Self.Left <> Self.Left + X + OldLeft) or (Self.Top <> Self.Top + Y - OldTop) then
+    begin
+      Self.Visible := False;
+      Self.Left := Self.Left + X - OldLeft;
+      Self.Top := Self.Top + Y - OldTop;
+      Self.Visible := True;
+    end;
+    ClipRect := Rect(0, 0, Screen.Width, Screen.Height);
+//    ClipCursor(@ClipRect);
+    DeleteObject(ClipRgn);
+    ReleaseDC(0, ScreenDC);
+    Moving := False;
+  end;
+
+  TOQBArea(Parent).ReboundLinks4Table(Self);
+end;
+
+{ TOQBLink }
+
+constructor TOQBLink.Create(AOwner: TComponent);
+var
+  mnuArr: array [1..4] of TMenuItem;
+begin
+  inherited;
+  ControlStyle := ControlStyle + [csReplicatable];
+  Width := 105;
+  Height := 105;
+  Rgn := CreateRectRgn(0, 0, Hand, Hand);
+  mnuArr[1] := NewItem('', 0, False, False, nil, 0, 'mnuLinkName');
+  mnuArr[2] := NewLine;
+  mnuArr[3] := NewItem('Link options', 0, False, True, TOQBArea(AOwner).SetOptions, 0, 'mnuOptions');
+  mnuArr[4] := NewItem('Unlink', 0, False, True, TOQBArea(AOwner).Unlink, 0, 'mnuUnlink');
+  PopMenu := NewPopupMenu(Self, 'mnu', paLeft, False, mnuArr);
+  PopMenu.PopupComponent := Self;
+end;
+
+destructor TOQBLink.Destroy;
+begin
+  DeleteObject(Rgn);
+  inherited;
+end;
+
+procedure TOQBLink.Paint;
+var
+  ArrRgn, pntArray: array [1..4] of TPoint;
+  ArrCnt: Integer;
+begin
+  if tbl1 <> tbl2 then
+  begin
+    if ((LnkX = 1) and (LnkY = 1)) or ((LnkX = 4) and (LnkY = 2)) then
+    begin
+      pntArray[1].X := 0;
+      pntArray[1].Y := Hand div 2;
+      pntArray[2].X := Hand;
+      pntArray[2].Y := Hand div 2;
+      pntArray[3].X := Width - Hand;
+      pntArray[3].Y := Height - Hand div 2;
+      pntArray[4].X := Width;
+      pntArray[4].Y := Height - Hand div 2;
+      ArrRgn[1].X := pntArray[2].X + 5;
+      ArrRgn[1].Y := pntArray[2].Y - 5;
+      ArrRgn[2].X := pntArray[2].X - 5;
+      ArrRgn[2].Y := pntArray[2].Y + 5;
+      ArrRgn[3].X := pntArray[3].X - 5;
+      ArrRgn[3].Y := pntArray[3].Y + 5;
+      ArrRgn[4].X := pntArray[3].X + 5;
+      ArrRgn[4].Y := pntArray[3].Y - 5;
+    end;
+    if Width > Hand + Hand2 then
+    begin
+      if ((LnkX = 2) and (LnkY = 1)) or ((LnkX = 3) and (LnkY = 2)) then
+      begin
+        pntArray[1].X := 0;
+        pntArray[1].Y := Hand div 2;
+        pntArray[2].X := Hand;
+        pntArray[2].Y := Hand div 2;
+        pntArray[3].X := Width - 5;
+        pntArray[3].Y := Height - Hand div 2;
+        pntArray[4].X := Width - Hand;
+        pntArray[4].Y := Height - Hand div 2;
+        ArrRgn[1].X := pntArray[2].X + 5;
+        ArrRgn[1].Y := pntArray[2].Y - 5;
+        ArrRgn[2].X := pntArray[2].X - 5;
+        ArrRgn[2].Y := pntArray[2].Y + 5;
+        ArrRgn[3].X := pntArray[3].X - 5;
+        ArrRgn[3].Y := pntArray[3].Y + 5;
+        ArrRgn[4].X := pntArray[3].X + 5;
+        ArrRgn[4].Y := pntArray[3].Y - 5;
+      end;
+      if ((LnkX = 3) and (LnkY = 1)) or ((LnkX = 2) and (LnkY = 2)) then
+      begin
+        pntArray[1].X := Width - Hand;
+        pntArray[1].Y := Hand div 2;
+        pntArray[2].X := Width - 5;
+        pntArray[2].Y := Hand div 2;
+        pntArray[3].X := Hand;
+        pntArray[3].Y := Height - Hand div 2;
+        pntArray[4].X := 0;
+        pntArray[4].Y := Height - Hand div 2;
+        ArrRgn[1].X := pntArray[2].X - 5;
+        ArrRgn[1].Y := pntArray[2].Y - 5;
+        ArrRgn[2].X := pntArray[2].X + 5;
+        ArrRgn[2].Y := pntArray[2].Y + 5;
+        ArrRgn[3].X := pntArray[3].X + 5;
+        ArrRgn[3].Y := pntArray[3].Y + 5;
+        ArrRgn[4].X := pntArray[3].X - 5;
+        ArrRgn[4].Y := pntArray[3].Y - 5;
+      end;
+    end
+    else
+    begin
+      if ((LnkX = 2) and (LnkY = 1)) or ((LnkX = 3) and (LnkY = 2)) or
+         ((LnkX = 3) and (LnkY = 1)) or ((LnkX = 2) and (LnkY = 2)) then
+      begin
+        pntArray[1].X := 0;
+        pntArray[1].Y := Hand div 2;
+        pntArray[2].X := Width - Hand2;
+        pntArray[2].Y := Hand div 2;
+        pntArray[3].X := Width - Hand2;
+        pntArray[3].Y := Height - Hand div 2;
+        pntArray[4].X := 0;
+        pntArray[4].Y := Height - Hand div 2;
+        ArrRgn[1].X := pntArray[2].X - 5;
+        ArrRgn[1].Y := pntArray[2].Y - 5;
+        ArrRgn[2].X := pntArray[2].X + 5;
+        ArrRgn[2].Y := pntArray[2].Y + 5;
+        ArrRgn[3].X := pntArray[3].X + 5;
+        ArrRgn[3].Y := pntArray[3].Y + 5;
+        ArrRgn[4].X := pntArray[3].X - 5;
+        ArrRgn[4].Y := pntArray[3].Y - 5;
+      end;
+    end;
+    if ((LnkX = 4) and (LnkY = 1)) or ((LnkX = 1) and (LnkY = 2)) then
+    begin
+      pntArray[1].X := Width;
+      pntArray[1].Y := Hand div 2;
+      pntArray[2].X := Width - Hand;
+      pntArray[2].Y := Hand div 2;
+      pntArray[3].X := Hand;
+      pntArray[3].Y := Height - Hand div 2;
+      pntArray[4].X := 0;
+      pntArray[4].Y := Height - Hand div 2;
+      ArrRgn[1].X := pntArray[2].X - 5;
+      ArrRgn[1].Y := pntArray[2].Y - 5;
+      ArrRgn[2].X := pntArray[2].X + 5;
+      ArrRgn[2].Y := pntArray[2].Y + 5;
+      ArrRgn[3].X := pntArray[3].X + 5;
+      ArrRgn[3].Y := pntArray[3].Y + 5;
+      ArrRgn[4].X := pntArray[3].X - 5;
+      ArrRgn[4].Y := pntArray[3].Y - 5;
+    end;
+  end
+  else
+  begin
+    pntArray[1].X := 0;
+    pntArray[1].Y := Hand div 2;
+    pntArray[2].X := Hand - 5;
+    pntArray[2].Y := Hand div 2;
+    pntArray[3].X := Hand - 5;
+    pntArray[3].Y := Height - Hand div 2;
+    pntArray[4].X := 0;
+    pntArray[4].Y := Height - Hand div 2;
+    ArrRgn[1].X := pntArray[2].X + 5;
+    ArrRgn[1].Y := pntArray[2].Y - 5;
+    ArrRgn[2].X := pntArray[2].X - 5;
+    ArrRgn[2].Y := pntArray[2].Y + 5;
+    ArrRgn[3].X := pntArray[3].X - 5;
+    ArrRgn[3].Y := pntArray[3].Y + 5;
+    ArrRgn[4].X := pntArray[3].X + 5;
+    ArrRgn[4].Y := pntArray[3].Y - 5;
+  end;
+
+  Canvas.PolyLine(pntArray);
+  Canvas.Brush := Parent.Brush;
+  DeleteObject(Rgn);
+  ArrCnt := 4;
+  Rgn := CreatePolygonRgn(@ArrRgn, ArrCnt, ALTERNATE);
+end;
+
+procedure TOQBLink._Click(X, Y: Integer);
+var
+  pnt: TPoint;
+begin
+  pnt.X := X;
+  pnt.Y := Y;
+  pnt := ClientToScreen(pnt);
+  PopMenu.Popup(pnt.X, pnt.Y);
+end;
+
+procedure TOQBLink.CMHitTest(var Message: TCMHitTest);
+begin
+  if PtInRegion(Rgn, Message.XPos, Message.YPos) then
+    Message.Result := 1;
+end;
+
+function TOQBLink.ControlAtPos(const Pos: TPoint): TControl;
+var
+  I: Integer;
+  scrnP, P: TPoint;
+begin
+  scrnP := ClientToScreen(Pos);
+  for I := Parent.ControlCount - 1 downto 0 do
+  begin
+    Result := Parent.Controls[I];
+    if (Result is TOQBLink) and (Result <> Self) then
+    with Result do
+    begin
+      P := Result.ScreenToClient(scrnP);
+      if Perform(CM_HITTEST, 0, Integer(PointToSmallPoint(P))) <> 0 then
+        Exit;
+    end;
+  end;
+  Result := nil;
+end;
+
+function TOQBLink.PtInRegion(RGN: HRGN; X, Y: Integer): Boolean;
+{$IFDEF MSWINDOWS}
+begin
+  Result := LCLIntf.PtInRegion(RGN, X, Y);
+{$ELSE}
+var
+  APoint   : TPoint;
+  ARect : TRect;
+begin
+  GetRgnBox(RGN, @ARect);
+  APoint.X := X;
+  APoint.Y := Y;
+  Result := LclIntf.PtInRect(ARect, APoint);
+{$ENDIF}
+end;
+
+procedure TOQBLink.WndProc(var Message: TLMessage);
+begin
+  if (Message.Msg = LM_RBUTTONDOWN) or (Message.Msg = LM_LBUTTONDOWN) then
+    if not PtInRegion(Rgn, TLMMouse(Message).XPos, TLMMouse(Message).YPos) then
+      ControlAtPos(SmallPointToPoint(TLMMouse(Message).Pos)) else
+      _Click(TLMMouse(Message).XPos, TLMMouse(Message).YPos);
+  inherited;
+end;
+
+
+{ TOQBArea }
+
+procedure TOQBArea.CreateParams(var Params: TCreateParams);
+begin
+  inherited;
+  OnDragOver := _DragOver;
+  OnDragDrop := _DragDrop;
+end;
+
+procedure TOQBArea.SetOptions(Sender: TObject);
+var
+  AForm: TOQBLinkForm;
+  ALink: TOQBLink;
+begin
+  if TPopupMenu(Sender).Owner is TOQBLink then
+  begin
+    ALink := TOQBLink(TPopupMenu(Sender).Owner);
+    AForm := TOQBLinkForm.Create(Application);
+    AForm.txtTable1.Caption := ALink.tbl1.FTableName;
+    AForm.txtCol1.Caption := ALink.fldNam1;
+    AForm.txtTable2.Caption := ALink.tbl2.FTableName;
+    AForm.txtCol2.Caption := ALink.fldNam2;
+    AForm.RadioOpt.ItemIndex := ALink.FLinkOpt;
+    AForm.RadioType.ItemIndex := ALink.FLinkType;
+    if AForm.ShowModal = mrOk then
+    begin
+      ALink.FLinkOpt := AForm.RadioOpt.ItemIndex;
+      ALink.FLinkType := AForm.RadioType.ItemIndex;
+    end;
+    AForm.Free;
+  end;
+end;
+
+procedure TOQBArea.InsertTable(X, Y: Integer);
+var
+  NewTable: TOQBTable;
+begin
+  if FindTable(TOQBForm(GetParentForm(Self)).QBTables.Items[
+    TOQBForm(GetParentForm(Self)).QBTables.ItemIndex]) <> nil then
+  begin
+    ShowMessage('This table is already inserted.');
+    Exit;
+  end;
+
+  NewTable := TOQBTable.Create(Self);
+  NewTable.Parent := Self;
+  try
+    NewTable.Activate(TOQBForm(GetParentForm(Self)).QBTables.Items[
+      TOQBForm(GetParentForm(Self)).QBTables.ItemIndex], X, Y);
+  except
+    NewTable.Free;
+  end;
+end;
+
+function TOQBArea.InsertLink(_tbl1, _tbl2: TOQBTable;
+  _fldN1, _fldN2: Integer): TOQBLink;
+begin
+  Result := TOQBLink.Create(Self);
+  with Result do
+  begin
+    Parent := Self;
+    Application.ProcessMessages; // importante no gtk2
+    tbl1 := _tbl1;
+    tbl2 := _tbl2;
+    fldN1 := _fldN1;
+    fldN2 := _fldN2;
+    fldNam1 := tbl1.FLbx.Items[fldN1];
+    fldNam2 := tbl2.FLbx.Items[fldN2];
+  end;
+  if FindLink(Result) then
+  begin
+    ShowMessage('These tables are already linked.');
+    Result.Free;
+    Result := nil;
+    Exit;
+  end;
+  with Result do
+  begin
+    tbl1.FLbx.SelectItemBold(fldN1);
+    tbl1.FLbx.Refresh;
+    tbl2.FLbx.SelectItemBold(fldN2);
+    tbl2.FLbx.Refresh;
+    OnDragOver := _DragOver;
+    OnDragDrop := _DragDrop;
+  end;
+  ReboundLink(Result);
+  Result.Visible := True;
+end;
+
+function TOQBArea.FindTable(const TableName: string): TOQBTable;
+var
+  i: Integer;
+  TempTable: TOQBTable;
+begin
+  Result := nil;
+  for i := ControlCount - 1 downto 0 do
+    if Controls[i] is TOQBTable then
+    begin
+      TempTable := TOQBTable(Controls[i]);
+      if (TempTable.FTableName = TableName) then
+      begin
+        Result := TempTable;
+        Exit;
+      end;
+    end;
+end;
+
+function TOQBArea.FindLink(Link: TOQBLink): Boolean;
+var
+  i: Integer;
+  TempLink: TOQBLink;
+begin
+  Result := False;
+  for i := ControlCount - 1 downto 0 do
+    if Controls[i] is TOQBLink then
+    begin
+      TempLink := TOQBLink(Controls[i]);
+      if (TempLink <> Link) then
+        if (((TempLink.tbl1 = Link.tbl1) and (TempLink.fldN1 = Link.fldN1)) and
+          ((TempLink.tbl2 = Link.tbl2) and (TempLink.fldN2 = Link.fldN2))) or
+          (((TempLink.tbl1 = Link.tbl2) and (TempLink.fldN1 = Link.fldN2)) and
+          ((TempLink.tbl2 = Link.tbl1) and (TempLink.fldN2 = Link.fldN1))) then
+        begin
+          Result := True;
+          Exit;
+        end;
+    end;
+end;
+
+function TOQBArea.FindOtherLink(Link: TOQBLink; Tbl: TOQBTable;
+  FldN: Integer): Boolean;
+var
+  i: Integer;
+  OtherLink: TOQBLink;
+begin
+  Result := False;
+  for i := ControlCount - 1 downto 0 do
+    if Controls[i] is TOQBLink then
+    begin
+      OtherLink := TOQBLink(Controls[i]);
+      if (OtherLink <> Link) then
+        if ((OtherLink.tbl1 = Tbl) and (OtherLink.fldN1 = FldN)) or
+           ((OtherLink.tbl2 = Tbl) and (OtherLink.fldN2 = FldN)) then
+        begin
+          Result := True;
+          Exit;
+        end;
+    end;
+end;
+
+procedure TOQBArea.ReboundLink(Link: TOQBLink);
+var
+  X1, X2, Y1, Y2: Integer;
+begin
+  Link.PopMenu.Items[0].Caption := Link.tbl1.FTableName + ' :: ' +
+    Link.tbl2.FTableName;
+  with Link do
+  begin
+    if Tbl1 = Tbl2 then
+    begin
+      X1 := Tbl1.Left + Tbl1.Width;
+      X2 := Tbl1.Left + Tbl1.Width + Hand;
+    end
+    else
+    begin
+      if Tbl1.Left < Tbl2.Left then
+      begin
+        if Tbl1.Left + Tbl1.Width + Hand < Tbl2.Left then
+        begin    //A
+          X1 := Tbl1.Left + Tbl1.Width;
+          X2 := Tbl2.Left;
+          LnkX := 1;
+        end
+        else
+        begin    //B
+          if Tbl1.Left + Tbl1.Width > Tbl2.Left + Tbl2.Width then
+          begin
+            X1 := Tbl2.Left + Tbl2.Width;
+            X2 := Tbl1.Left + Tbl1.Width + Hand;
+            LnkX := 3;
+          end
+          else
+          begin
+            X1 := Tbl1.Left + Tbl1.Width;
+            X2 := Tbl2.Left + Tbl2.Width + Hand;
+            LnkX := 2;
+          end;
+        end;
+      end
+      else
+      begin
+        if Tbl2.Left + Tbl2.Width + Hand > Tbl1.Left then
+        begin    //C
+          if Tbl2.Left + Tbl2.Width > Tbl1.Left + Tbl1.Width then
+          begin
+            X1 := Tbl1.Left + Tbl1.Width;
+            X2 := Tbl2.Left + Tbl2.Width + Hand;
+            LnkX := 2;
+          end
+          else
+          begin
+            X1 := Tbl2.Left + Tbl2.Width;
+            X2 := Tbl1.Left + Tbl1.Width + Hand;
+            LnkX := 3;
+          end;
+        end
+        else
+        begin    //D
+          X1 := Tbl2.Left + Tbl2.Width;
+          X2 := Tbl1.Left;
+          LnkX := 4;
+        end;
+      end;
+    end;
+
+    Y1 := Tbl1.GetRowY(FldN1);
+    Y2 := Tbl2.GetRowY(FldN2);
+    if Y1 < Y2 then
+    begin        //M
+      Y1 := Tbl1.GetRowY(FldN1) - Hand div 2;
+      Y2 := Tbl2.GetRowY(FldN2) + Hand div 2;
+      LnkY := 1;
+    end
+    else
+    begin         //N
+      Y2 := Tbl1.GetRowY(FldN1) + Hand div 2;
+      Y1 := Tbl2.GetRowY(FldN2) - Hand div 2;
+      LnkY := 2;
+    end;
+    SetBounds(X1, Y1, X2 - X1, Y2 - Y1);
+  end;
+end;
+
+procedure TOQBArea.ReboundLinks4Table(ATable: TOQBTable);
+var
+  i: Integer;
+  Link: TOQBLink;
+begin
+  for i := 0 to ControlCount - 1 do
+  begin
+    if Controls[i] is TOQBLink then
+    begin
+      Link := TOQBLink(Controls[i]);
+      if (Link.Tbl1 = ATable) or (Link.Tbl2 = ATable) then
+        ReboundLink(Link);
+    end;
+  end;
+end;
+
+procedure TOQBArea.Unlink(Sender: TObject);
+var
+  Link: TOQBLink;
+begin
+  if TPopupMenu(Sender).Owner is TOQBLink then
+  begin
+    Link := TOQBLink(TPopupMenu(Sender).Owner);
+    RemoveControl(Link);
+
+    if not FindOtherLink(Link, Link.tbl1, Link.fldN1) then
+    begin
+      Link.tbl1.FLbx.UnSelectItemBold(Link.fldN1);
+      Link.tbl1.FLbx.Refresh;
+    end;
+    if not FindOtherLink(Link, Link.tbl2, Link.fldN2) then
+    begin
+      Link.tbl2.FLbx.UnSelectItemBold(Link.fldN2);
+      Link.tbl2.FLbx.Refresh;
+    end;
+
+    Link.Free;
+  end;
+end;
+
+procedure TOQBArea.UnlinkTable(ATable: TOQBTable);
+var
+  i: Integer;
+  TempLink: TOQBLink;
+begin
+  for i := ControlCount - 1 downto 0 do
+  begin
+    if Controls[i] is TOQBLink then
+    begin
+      TempLink := TOQBLink(Controls[i]);
+
+      if (TempLink.Tbl1 = ATable) or (TempLink.Tbl2 = ATable) then
+      begin
+        RemoveControl(TempLink);
+        if not FindOtherLink(TempLink, TempLink.tbl1, TempLink.fldN1) then
+        begin
+          TempLink.tbl1.FLbx.UnSelectItemBold(TempLink.fldN1);
+          TempLink.tbl1.FLbx.Refresh;
+        end;
+        if not FindOtherLink(TempLink, TempLink.tbl2, TempLink.fldN2) then
+        begin
+          TempLink.tbl2.FLbx.UnSelectItemBold(TempLink.fldN2);
+          TempLink.tbl2.FLbx.Refresh;
+        end;
+
+        TempLink.Free;
+      end;
+    end;
+  end;
+end;
+
+procedure TOQBArea._DragOver(Sender, Source: TObject; X, Y: Integer;
+  State: TDragState; var Accept: Boolean);
+begin
+  if (Source = TOQBForm(GetParentForm(Self)).QBTables) then
+    Accept := True;
+end;
+
+procedure TOQBArea._DragDrop(Sender, Source: TObject; X, Y: Integer);
+begin
+  if not (Sender is TOQBArea) then
+  begin
+    X := X + TControl(Sender).Left;
+    Y := Y + TControl(Sender).Top;
+  end;
+
+  if Source = TOQBForm(GetParentForm(Self)).QBTables then
+    InsertTable(X, Y);
+end;
+
+
+{ TOQBGrid }
+
+procedure TOQBGrid.CreateParams(var Params: TCreateParams);
+begin
+  inherited;
+  FocusRectVisible := False;
+  DefaultColWidth := 64;
+  Options := [goFixedVertLine, goFixedHorzLine, goVertLine, goHorzLine,
+    goColSizing, goColMoving];
+  ColCount := 2;
+  RowCount := 6;
+  Height := Parent.ClientHeight;
+//  DefaultRowHeight := Parent.Height div (6 + 1) - GridLineWidth;
+  DefaultRowHeight := 20;
+  Cells[0, cFld] := 'Field';
+  Cells[0, cTbl] := 'Table';
+  Cells[0, cShow] := 'Show';
+  Cells[0, cSort] := 'Sort';
+  Cells[0, cFunc] := 'Function';
+  Cells[0, cGroup] := 'Group';
+  OnDragOver := _DragOver;
+  OnDragDrop := _DragDrop;
+  IsEmpty := True;
+end;
+
+procedure TOQBGrid.WndProc(var Message: TLMessage);
+begin
+  if (Message.Msg = LM_RBUTTONDOWN) then
+    ClickCell(TLMMouse(Message).XPos, TLMMouse(Message).YPos);
+  inherited;
+end;
+
+function TOQBGrid.MaxSW(const s1, s2: string): Integer;
+begin
+  Result := Canvas.TextWidth(s1);
+  if Result < Canvas.TextWidth(s2) then
+    Result := Canvas.TextWidth(s2);
+end;
+
+procedure TOQBGrid.InsertDefault(aCol: Integer);
+begin
+  Cells[aCol, cShow] := sShow;
+  Cells[aCol, cSort] := '';
+  Cells[aCol, cFunc] := '';
+  Cells[aCol, cGroup] := '';
+end;
+
+procedure TOQBGrid.Insert(aCol: Integer; const aField, aTable: string);
+var
+  i: Integer;
+begin
+  if IsEmpty then
+  begin
+    IsEmpty := False;
+    aCol := 1;
+    Cells[aCol, cFld] := aField;
+    Cells[aCol, cTbl] := aTable;
+    InsertDefault(aCol);
+  end
+  else
+  begin
+    if aCol = -1 then
+    begin
+      ColCount := ColCount + 1;
+      aCol := ColCount - 1;
+      Cells[aCol, cFld] := aField;
+      Cells[aCol, cTbl] := aTable;
+      InsertDefault(aCol);
+    end
+    else
+    begin
+      ColCount := ColCount + 1;
+      for i := ColCount - 1 downto aCol + 1 do
+        MoveColRow(True,i - 1, i);
+      Cells[aCol, cFld] := aField;
+      Cells[aCol, cTbl] := aTable;
+      InsertDefault(aCol);
+    end;
+    //* Fix StringGrid Bug *
+    if aCol > 1 then
+      ColWidths[aCol - 1] := MaxSW(Cells[aCol - 1, cFld], Cells[aCol - 1, cTbl]) + 8;
+    if aCol < ColCount - 1 then
+      ColWidths[aCol + 1] := MaxSW(Cells[aCol + 1, cFld], Cells[aCol + 1, cTbl]) + 8;
+    ColWidths[ColCount - 1] := MaxSW(Cells[ColCount - 1, cFld],
+      Cells[ColCount - 1, cTbl]) + 8;
+  end;
+
+  ColWidths[aCol] := MaxSW(aTable, aField) + 8;
+end;
+
+function TOQBGrid.FindColumn(const sCol: string): Integer;
+var
+  i: Integer;
+begin
+  Result := -1;
+  for i := 1 to ColCount - 1 do
+    if Cells[i, cFld] = sCol then
+    begin
+      Result := i;
+      Exit;
+    end;
+end;
+
+function TOQBGrid.FindSameColumn(aCol: Integer): Boolean;
+var
+  i: Integer;
+begin
+  Result := False;
+  for i := 1 to ColCount - 1 do
+    if i = aCol then
+      Continue
+    else if Cells[i, cFld] = Cells[aCol, cFld] then
+    begin
+      Result := True;
+      Exit;
+    end;
+end;
+
+procedure TOQBGrid.RemoveColumn(aCol: Integer);
+var
+  i: Integer;
+begin
+  if (ColCount > 2) then
+    DeleteCol(aCol)
+  else
+  begin
+    for i := 0 to RowCount - 1 do
+      Cells[1, i] := '';
+    IsEmpty := True;
+  end;
+end;
+
+procedure TOQBGrid.RemoveColumn4Tbl(const Tbl: string);
+var
+  i: Integer;
+begin
+  for i := ColCount - 1 downto 1 do
+    if Cells[i, cTbl] = Tbl then
+      RemoveColumn(i);
+end;
+
+procedure TOQBGrid.ClickCell(X, Y: Integer);
+var
+  P: TPoint;
+  mCol, mRow: Integer;
+begin
+  MouseToCell(X, Y, mCol, mRow);
+  CurrCol := mCol;
+  P.X := X;
+  P.Y := Y;
+  P := ClientToScreen(P);
+  if (mCol > 0) and (mCol < ColCount) and (not IsEmpty) then
+  begin
+    if (Cells[mCol, 0] = '*') and (mRow <> cFld) then
+      Exit;
+    case mRow of
+      cFld:
+        TOQBForm(GetParentForm(Self)).mnuTbl.Popup(P.X, P.Y);
+      cShow:
+        begin
+          TOQBForm(GetParentForm(Self)).mnuShow.Items[0].Checked := Cells[mCol, cShow] = sShow;
+          TOQBForm(GetParentForm(Self)).mnuShow.Popup(P.X, P.Y);
+        end;
+      cSort:
+        begin
+          if Cells[mCol, cSort] = sSort[1] then
+            TOQBForm(GetParentForm(Self)).mnuSort.Items[0].Checked := True
+          else if Cells[mCol, cSort] = sSort[2] then
+            TOQBForm(GetParentForm(Self)).mnuSort.Items[2].Checked := True else
+            TOQBForm(GetParentForm(Self)).mnuSort.Items[3].Checked := True;
+          TOQBForm(GetParentForm(Self)).mnuSort.Popup(P.X, P.Y);
+        end;
+      cFunc:
+        begin
+          if Cells[mCol, cFunc] = sFunc[1] then
+            TOQBForm(GetParentForm(Self)).mnuFunc.Items[0].Checked := True
+          else if Cells[mCol, cFunc] = sFunc[2] then
+            TOQBForm(GetParentForm(Self)).mnuFunc.Items[2].Checked := True
+          else if Cells[mCol, cFunc] = sFunc[3] then
+            TOQBForm(GetParentForm(Self)).mnuFunc.Items[3].Checked := True
+          else if Cells[mCol, cFunc] = sFunc[4] then
+            TOQBForm(GetParentForm(Self)).mnuFunc.Items[4].Checked := True
+          else if Cells[mCol, cFunc] = sFunc[5] then
+            TOQBForm(GetParentForm(Self)).mnuFunc.Items[5].Checked := True
+          else
+            TOQBForm(GetParentForm(Self)).mnuFunc.Items[6].Checked := True;
+          TOQBForm(GetParentForm(Self)).mnuFunc.Popup(P.X, P.Y);
+        end;
+      cGroup:
+        begin
+          TOQBForm(GetParentForm(Self)).mnuGroup.Items[0].Checked := Cells[mCol, cGroup] = sGroup;
+          TOQBForm(GetParentForm(Self)).mnuGroup.Popup(P.X, P.Y);
+        end;
+    end;
+  end;
+end;
+
+function TOQBGrid.SelectCell(ACol, ARow: Integer): Boolean;
+begin
+  inherited SelectCell(ACol, ARow);
+  Result := ARow > cGroup;
+end;
+
+procedure TOQBGrid._DragOver(Sender, Source: TObject; X, Y: Integer;
+  State: TDragState; var Accept: Boolean);
+begin
+  if (Source <> TOQBForm(GetParentForm(Self)).QBTables) then
+    Accept := True;
+end;
+
+procedure TOQBGrid._DragDrop(Sender, Source: TObject; X, Y: Integer);
+var
+  dCol, dRow: Integer;
+begin
+  if ((Source is TOQBLbx) and
+    (Source <> TOQBForm(GetParentForm(Self)).QBTables)) then
+  begin
+    TOQBTable(TWinControl(Source).Parent).FLbx.Checked[
+      TOQBTable(TWinControl(Source).Parent).FLbx.ItemIndex] := True;//*** check
+    MouseToCell(X, Y, dCol, dRow);
+    if dCol = 0 then
+      Exit;
+    Insert(dCol,
+      TOQBTable(TWinControl(Source).Parent).FLbx.Items[TOQBTable(TWinControl(Source).Parent).FLbx.ItemIndex],
+      TOQBTable(TWinControl(Source).Parent).FTableName);
+  end;
+end;
+
+
+{ TOQBForm }
+
+procedure TOQBForm.CreateParams(var Params: TCreateParams);
+begin
+  inherited;
+  QBArea := TOQBArea.Create(Self);
+  QBArea.Parent := QBPanel;
+  QBArea.Align := alClient;
+  QBArea.Color := $009E9E9E;
+  QBGrid := TOQBGrid.Create(Self);
+  QBGrid.DefaultRowHeight := 22;
+  QBGrid.DefaultColWidth := 150;
+  QBGrid.Parent := TabColumns;
+  QBGrid.Align := alClient;
+  VSplitter.Tag := VSplitter.Left;
+  HSplitter.Tag := HSplitter.Top;
+  Application.ProcessMessages;
+end;
+
+procedure TOQBForm.mnuFunctionClick(Sender: TObject);
+var
+  Item: TMenuItem;
+begin
+  if Sender is TMenuItem then
+  begin
+    Item := (Sender as TMenuItem);
+    if not Item.Checked then
+    begin
+      Item.Checked := True;
+      QBGrid.Cells[QBGrid.CurrCol, cFunc] := sFunc[Item.Tag];
+    end;
+  end;
+end;
+
+procedure TOQBForm.mnuGroupClick(Sender: TObject);
+begin
+  if mnuGroup.Items[0].Checked then
+  begin
+    QBGrid.Cells[QBGrid.CurrCol, cGroup] := '';
+    mnuGroup.Items[0].Checked := False;
+  end
+  else
+  begin
+    QBGrid.Cells[QBGrid.CurrCol, cGroup] := sGroup;
+    mnuGroup.Items[0].Checked := True;
+  end;
+end;
+
+procedure TOQBForm.mnuRemoveClick(Sender: TObject);
+var
+  TempTable: TOQBTable;
+begin
+  TempTable := QBArea.FindTable(QBGrid.Cells[QBGrid.CurrCol, cTbl]);
+  if not QBGrid.FindSameColumn(QBGrid.CurrCol) then
+    TempTable.FLbx.Checked[TempTable.FLbx.Items.IndexOf(QBGrid.Cells[QBGrid.CurrCol, cFld])] := False;
+  QBGrid.RemoveColumn(QBGrid.CurrCol);
+  QBGrid.Refresh; // fix for StringGrid bug
+end;
+
+procedure TOQBForm.mnuShowClick(Sender: TObject);
+begin
+  if mnuShow.Items[0].Checked then
+  begin
+    QBGrid.Cells[QBGrid.CurrCol, cShow] := '';
+    mnuShow.Items[0].Checked := False;
+  end
+  else
+  begin
+    QBGrid.Cells[QBGrid.CurrCol, cShow] := sShow;
+    mnuShow.Items[0].Checked := True;
+  end;
+end;
+
+procedure TOQBForm.mnuSortClick(Sender: TObject);
+var
+  Item: TMenuItem;
+begin
+  if Sender is TMenuItem then
+  begin
+    Item := (Sender as TMenuItem);
+    if not Item.Checked then
+    begin
+      Item.Checked := True;
+      QBGrid.Cells[QBGrid.CurrCol, cSort] := sSort[Item.Tag];
+    end;
+  end;
+end;
+
+procedure TOQBForm.ClearAll;
+var
+  i: Integer;
+  TempTable: TOQBTable;
+begin
+  for i := QBArea.ControlCount - 1 downto 0 do
+    if QBArea.Controls[i] is TOQBTable then
+    begin
+      TempTable := TOQBTable(QBArea.Controls[i]);
+      QBGrid.RemoveColumn4Tbl(TempTable.FTableName);
+      TempTable.Free;
+    end
+    else
+      QBArea.Controls[i].Free; // QBLink
+
+  MemoSQL.Lines.Clear;
+  QBDialog.OQBEngine.ResultQuery.Close;
+  QBDialog.OQBEngine.ClearQuerySQL;
+  Pages.ActivePage := TabColumns;
+end;
+
+procedure TOQBForm.btnNewClick(Sender: TObject);
+begin
+  ClearAll;
+end;
+
+procedure TOQBForm.btnOpenClick(Sender: TObject);
+var
+  i, ii, j: Integer;
+  s, ss: string;
+  TempDatabaseName: string;
+  ShowSystemTables: Boolean;
+  NewTable: TOQBTable;
+  TableName: string;
+  X, Y: Integer;
+  NewLink: TOQBLink;
+  Table1, Table2: TOQBTable;
+  FieldN1, FieldN2: Integer;
+  ColField, ColTable: string;
+  StrList: TStringList;
+
+  function GetNextVal(var s: string): string;
+  var
+    p: Integer;
+  begin
+    Result := EmptyStr;
+    p := Pos(',', s);
+    if p = 0 then
+    begin
+      p := Pos(';', s);
+      if p = 0 then
+         Exit;
+    end;
+    Result := System.Copy(s, 1, p - 1);
+    System.Delete(s, 1, p);
+  end;
+
+begin
+  j := -1;
+  if not DlgOpen.Execute then
+    Exit;
+  StrList := TStringList.Create;
+  StrList.LoadFromFile(DlgOpen.FileName);
+  if StrList[0] <> QBSignature then
+  begin
+    ShowMessage('File ' + DlgOpen.FileName + ' is not QBuilder''s query file.');
+    StrList.Free;
+    Exit;
+  end;
+
+  ClearAll;
+  try
+    s := StrList[3];  // read options
+    if s = '+' then
+      WindowState := wsMaximized
+    else
+    begin
+      WindowState := wsNormal;
+      Top := StrToInt(GetNextVal(s));
+      Left := StrToInt(GetNextVal(s));
+      Height := StrToInt(GetNextVal(s));
+      Width := StrToInt(GetNextVal(s));
+    end;
+
+    s := StrList[4];
+    btnTables.Down := Boolean(StrToInt(GetNextVal(s)));
+    VSplitter.Visible := btnTables.Down;
+    QBTables.Visible := btnTables.Down;
+    QBTables.Width := StrToInt(GetNextVal(s));
+    btnPages.Down := Boolean(StrToInt(GetNextVal(s)));
+    HSplitter.Visible := btnPages.Down;
+    Pages.Visible := btnPages.Down;
+    Pages.Height := StrToInt(GetNextVal(s));
+
+    s := StrList[6];  // read database
+    TempDatabaseName := GetNextVal(s);
+    ShowSystemTables := Boolean(StrToInt(GetNextVal(s)));
+
+    QBDialog.OQBEngine.DatabaseName := TempDatabaseName;
+    QBDialog.OQBEngine.ShowSystemTables := ShowSystemTables;
+    OpenDatabase;
+
+    for i := 8 to StrList.Count - 1 do  // read tables
+    begin
+      if StrList[i] = '[Links]' then
+      begin
+        j := i + 1;
+        Break;
+      end;
+      s := StrList[i];
+      TableName := GetNextVal(s);
+      Y := StrToInt(GetNextVal(s));
+      X := StrToInt(GetNextVal(s));
+      NewTable := TOQBTable.Create(Self);
+      NewTable.Parent := QBArea;
+      try
+        NewTable.Activate(TableName, X, Y);
+        NewTable.FLbx.FLoading := True;
+        for ii := 0 to NewTable.FLbx.Items.Count - 1 do
+        begin
+          ss := GetNextVal(s);
+          if ss <> EmptyStr then
+            NewTable.FLbx.Checked[ii] := Boolean(StrToInt(ss));
+        end;
+        NewTable.FLbx.FLoading := False;
+      except
+        NewTable.Free;
+      end;
+    end;
+
+    if j <> -1 then
+      for i := j to StrList.Count - 1 do  // read links
+      begin
+        if StrList[i] = '[Columns]' then
+        begin
+          j := i + 1;
+          Break;
+        end;
+        s := StrList[i];
+        ss := GetNextVal(s);
+        Table1 := QBArea.FindTable(ss);
+        ss := GetNextVal(s);
+        FieldN1 := StrToInt(ss);
+        ss := GetNextVal(s);
+        Table2 := QBArea.FindTable(ss);
+        ss := GetNextVal(s);
+        FieldN2 := StrToInt(ss);
+        NewLink := QBArea.InsertLink(Table1, Table2, FieldN1, FieldN2);
+        ss := GetNextVal(s);
+        NewLink.FLinkOpt := StrToInt(ss);
+        ss := GetNextVal(s);
+        NewLink.FLinkType := StrToInt(ss);
+      end;
+
+    if j <> -1 then
+      for i := j to StrList.Count - 1 do  // read columns
+      begin
+        if StrList[i] = '[End]' then
+          Break;
+        s := StrList[i];
+        ii := StrToInt(GetNextVal(s));
+        ColField := GetNextVal(s);
+        ColTable := GetNextVal(s);
+        QBGrid.Insert(ii, ColField, ColTable);
+        QBGrid.Cells[ii, cShow] := GetNextVal(s);
+        QBGrid.Cells[ii, cSort] := GetNextVal(s);
+        QBGrid.Cells[ii, cFunc] := GetNextVal(s);
+        QBGrid.Cells[ii, cGroup] := GetNextVal(s);
+      end;
+
+  finally
+    StrList.Free;
+  end;
+end;
+
+procedure TOQBForm.btnSaveClick(Sender: TObject);
+var
+  i, j: Integer;
+  s: string;
+  TempTable: TOQBTable;
+  TempLink: TOQBLink;
+  StrList: TStringList;
+begin
+  if not DlgSave.Execute then Exit;
+  StrList := TStringList.Create;
+  StrList.Add(QBSignature);
+  StrList.Add('# Don''t change this file !');
+  StrList.Add('[Options]');
+  if WindowState = wsMaximized then
+    s := '+' else
+    s := IntToStr(Top) + ',' + IntToStr(Left) + ',' + IntToStr(Height) + ',' +
+      IntToStr(Width) + ';';
+  StrList.Add(s);
+  s := IntToStr(Integer(btnTables.Down)) + ',' + IntToStr(QBTables.Width) +
+    ',' + IntToStr(Integer(btnPages.Down)) + ',' + IntToStr(Pages.Height) + ';';
+  StrList.Add(s);
+
+  StrList.Add('[Database]');
+  s := QBDialog.OQBEngine.DatabaseName + ',' + IntToStr(Integer(QBDialog.OQBEngine.ShowSystemTables)) + ';';
+  StrList.Add(s);
+
+  StrList.Add('[Tables]');  // save tables
+  for i := 0 to QBArea.ControlCount - 1 do
+    if QBArea.Controls[i] is TOQBTable then
+    begin
+      TempTable := TOQBTable(QBArea.Controls[i]);
+      s := TempTable.FTableName + ',' +
+        IntToStr(TempTable.Top + QBArea.VertScrollBar.ScrollPos) + ',' +
+        IntToStr(TempTable.Left + QBArea.HorzScrollBar.ScrollPos);
+      for j := 0 to TempTable.FLbx.Items.Count - 1 do
+        if TempTable.FLbx.Checked[j] then
+          s := s + ',1' else
+          s := s + ',0';
+      s := s + ';';
+      StrList.Add(s);
+    end;
+
+  StrList.Add('[Links]');   // save links
+  for i := 0 to QBArea.ControlCount - 1 do
+    if QBArea.Controls[i] is TOQBLink then
+    begin
+      TempLink := TOQBLink(QBArea.Controls[i]);
+      s := TempLink.Tbl1.FTableName + ',' + IntToStr(TempLink.FldN1) + ',' +
+        TempLink.Tbl2.FTableName + ',' + IntToStr(TempLink.FldN2) + ',' +
+        IntToStr(TempLink.FLinkOpt) + ',' + IntToStr(TempLink.FLinkType);
+      s := s + ';';
+      StrList.Add(s);
+    end;
+
+  StrList.Add('[Columns]');   // save columns
+  if not QBGrid.IsEmpty then
+    for i := 1 to QBGrid.ColCount - 1 do
+    begin
+      s := IntToStr(i) + ',' + QBGrid.Cells[i, cFld] + ',' + QBGrid.Cells[i, cTbl];
+      s := s + ',' + QBGrid.Cells[i, cShow] + ',' + QBGrid.Cells[i, cSort] +
+        ',' + QBGrid.Cells[i, cFunc] + ',' + QBGrid.Cells[i, cGroup];
+      s := s + ';';
+      StrList.Add(s);
+    end;
+
+  StrList.Add('[End]');   // end of QBuilder information
+
+  StrList.SaveToFile(DlgSave.FileName);
+  StrList.Free;
+end;
+
+procedure TOQBForm.btnTablesClick(Sender: TObject);
+begin
+  VSplitter.Visible := TToolButton(Sender).Down;
+  QBTables.Visible := TToolButton(Sender).Down;
+  if not VSplitter.Visible then
+    VSplitter.Tag := VSplitter.Left
+  else
+    VSplitter.Left := VSplitter.Tag;
+end;
+
+procedure TOQBForm.btnPagesClick(Sender: TObject);
+begin
+  HSplitter.Visible := TToolButton(Sender).Down;
+  Pages.Visible := TToolButton(Sender).Down;
+  if not HSplitter.Visible then
+    HSplitter.Tag := HSplitter.Top
+  else
+    HSplitter.Top := HSplitter.Tag;
+end;
+
+procedure TOQBForm.OpenDatabase;
+begin
+  try
+    QBDialog.OQBEngine.ReadTableList;
+    QBDialog.OQBEngine.GenerateAliases;
+    QBTables.Items.Assign(QBDialog.OQBEngine.TableList);
+    ResDataSource.DataSet := QBDialog.OQBEngine.ResultQuery;
+    Caption := sMainCaption + ' [' + QBDialog.OQBEngine.DatabaseName + ']';
+  except
+    // ignore errors
+  end;
+end;
+
+procedure TOQBForm.SelectDatabase;
+begin
+  if QBDialog.OQBEngine.SelectDatabase then
+  begin
+    ClearAll;
+    QBTables.Items.Clear;
+    OpenDatabase;
+  end
+end;
+
+procedure TOQBForm.btnDBClick(Sender: TObject);
+begin
+  SelectDatabase;
+end;
+
+procedure TOQBForm.btnSQLClick(Sender: TObject);
+var
+  Lst, Lst1, Lst2: TStringList;   // temporary string lists
+  i: Integer;
+  s: string;
+  tbl1, tbl2: string;
+  Link: TOQBLink;
+
+  function ExtractName(s: string):string;
+  var
+    p: Integer;
+  begin
+    Result := s;
+    p := Pos('.', s);
+    if p = 0 then
+      Exit;
+    Result := System.Copy(s, 1, p - 1);
+  end;
+begin
+  if QBGrid.IsEmpty then
+  begin
+    ShowMessage('Columns are not selected.');
+    Exit;
+  end;
+  Lst := TStringList.Create;
+  try
+    with QBDialog.OQBEngine do
+    begin
+      SQLcolumns.Clear;
+      SQLcolumns_func.Clear;
+      SQLcolumns_table.Clear;
+      SQLfrom.Clear;
+      SQLwhere.Clear;
+      SQLgroupby.Clear;
+      SQLorderby.Clear;
+    end;
+
+  //  SELECT clause
+    with QBGrid do
+    begin
+      for i := 1 to ColCount - 1 do
+        if Cells[i, cShow] = sShow then
+        begin
+          if QBDialog.OQBEngine.UseTableAliases then
+            tbl1 := QBDialog.OQBEngine.AliasList[QBDialog.OQBEngine.TableList.IndexOf(Cells[i, cTbl])]
+          else
+            tbl1 := Cells[i, cTbl];
+          s := tbl1 + '.' + Cells[i, cFld];
+          Lst.Add(LowerCase(s));
+          if Cells[i, cFunc] <> EmptyStr then
+            s := UpperCase(Cells[i, cFunc]) else
+            s := EmptyStr;
+          if QBDialog.OQBEngine.UseTableAliases then
+            QBDialog.OQBEngine.SQLcolumns_table.Add(LowerCase(
+              QBDialog.OQBEngine.AliasList[QBDialog.OQBEngine.TableList.IndexOf(Cells[i, cTbl])]))
+          else
+            QBDialog.OQBEngine.SQLcolumns_table.Add(LowerCase(Cells[i, cTbl]));
+          QBDialog.OQBEngine.SQLcolumns_func.Add(s);
+        end;
+
+      if Lst.Count = 0 then
+      begin
+        ShowMessage('Columns are not selected.');
+        Lst.Free;
+        Exit;
+      end;
+      QBDialog.OQBEngine.SQLcolumns.Assign(Lst);
+      Lst.Clear;
+    end;
+
+  //  FROM clause
+    with QBArea do
+    begin
+      Lst1 := TSTringList.Create;  // tables in joins
+      Lst2 := TSTringList.Create;  // outer joins
+      for i := 0 to ControlCount - 1 do  // search tables for joins
+        if Controls[i] is TOQBLink then
+        begin
+          Link := TOQBLink(Controls[i]);
+          if Link.FLinkType > 0 then
+          begin
+            if QBDialog.OQBEngine.UseTableAliases then
+            begin
+              tbl1 := LowerCase(Link.Tbl1.FTableAlias);
+              tbl2 := LowerCase(Link.Tbl2.FTableAlias);
+            end
+            else
+            begin
+              tbl1 := LowerCase(Link.Tbl1.FTableName);
+              tbl2 := LowerCase(Link.Tbl2.FTableName);
+            end;
+            if Lst1.IndexOf(tbl1) = -1 then
+              Lst1.Add(tbl1);
+            if Lst1.IndexOf(tbl2) = -1 then
+              Lst1.Add(tbl2);
+            if QBDialog.OQBEngine.UseTableAliases then
+              Lst2.Add(LowerCase(Link.Tbl1.FTableName) + ' ' + tbl1 +
+                sOuterJoin[Link.FLinkType] +
+                LowerCase(Link.Tbl2.FTableName) + ' ' + tbl2 + ' ON ' +
+                tbl1 + '.' + LowerCase(Link.FldNam1) + sLinkOpt[Link.FLinkOpt] +
+                tbl2 + '.' + LowerCase(Link.FldNam2))
+            else
+              Lst2.Add(tbl1 + sOuterJoin[Link.FLinkType] + tbl2 + ' ON ' +
+                tbl1 + '.' + LowerCase(Link.FldNam1) +
+                sLinkOpt[Link.FLinkOpt] + tbl2 + '.' + LowerCase(Link.FldNam2));
+          end;
+        end;
+
+      for i := 0 to ControlCount - 1 do
+        if Controls[i] is TOQBTable then
+        begin
+          if QBDialog.OQBEngine.UseTableAliases then
+            tbl1 := LowerCase(TOQBTable(Controls[i]).FTableAlias) else
+            tbl1 := LowerCase(TOQBTable(Controls[i]).FTableName);
+          if (Lst.IndexOf(tbl1) = -1) and (Lst1.IndexOf(tbl1) = -1) then
+            if QBDialog.OQBEngine.UseTableAliases then
+              Lst.Add(LowerCase(TOQBTable(Controls[i]).FTableName) + ' ' + tbl1) else
+              Lst.Add(tbl1);
+        end;
+
+      Lst1.Free;
+
+      QBDialog.OQBEngine.SQLfrom.Assign(Lst2);
+      QBDialog.OQBEngine.SQLfrom.AddStrings(Lst);
+      Lst2.Free;
+      Lst.Clear;
+    end;
+
+  //  WHERE clause
+    with QBArea do
+    begin
+      for i := 0 to ControlCount - 1 do
+        if Controls[i] is TOQBLink then
+        begin
+          Link := TOQBLink(Controls[i]);
+          if Link.FLinkType = 0 then
+          begin
+            if QBDialog.OQBEngine.UseTableAliases then
+              s := Link.tbl1.FTableAlias + '.' + Link.fldNam1 + sLinkOpt[Link.FLinkOpt] +
+                Link.tbl2.FTableAlias + '.' + Link.fldNam2
+            else
+              s := Link.tbl1.FTableName + '.' + Link.fldNam1 + sLinkOpt[Link.FLinkOpt] +
+                Link.tbl2.FTableName + '.' + Link.fldNam2;
+
+            Lst.Add(LowerCase(s));
+          end;
+        end;
+      QBDialog.OQBEngine.SQLwhere.Assign(Lst);
+      Lst.Clear;
+    end;
+
+  // GROUP BY clause
+    with QBGrid do
+    begin
+      for i := 1 to ColCount - 1 do
+      begin
+        if Cells[i, cGroup] <> EmptyStr then
+        begin
+          if QBDialog.OQBEngine.UseTableAliases then
+            tbl1 := QBDialog.OQBEngine.AliasList[QBDialog.OQBEngine.TableList.IndexOf(Cells[i, cTbl])]
+          else
+            tbl1 := Cells[i, cTbl];
+          s := tbl1 + '.' + Cells[i, cFld];
+          Lst.Add(LowerCase(s));
+        end;
+      end;
+      QBDialog.OQBEngine.SQLgroupby.Assign(Lst);
+      Lst.Clear;
+    end;
+
+  // ORDER BY clause
+    with QBGrid do
+    begin
+      for i := 1 to ColCount - 1 do
+      begin
+        if Cells[i, cSort] <> EmptyStr then
+        begin
+          if QBDialog.OQBEngine.UseTableAliases then
+            tbl1 := QBDialog.OQBEngine.AliasList[QBDialog.OQBEngine.TableList.IndexOf(Cells[i, cTbl])]
+          else
+            tbl1 := Cells[i, cTbl];
+          // --- to order result set by the result of an aggregate function
+          if Cells[i, cFunc] = EmptyStr then
+            s := LowerCase(tbl1 + '.' + Cells[i, cFld]) else
+            s := IntToStr(i);
+          // ---
+
+          if Cells[i, cSort] = sSort[3] then
+            s := s + ' DESC';
+          Lst.Add(s);
+        end;
+      end;
+      QBDialog.OQBEngine.SQLorderby.Assign(Lst);
+      Lst.Clear;
+    end;
+
+    MemoSQL.Lines.Text := QBDialog.OQBEngine.GenerateSQL;
+    Pages.ActivePage := TabSQL;
+  finally
+    Lst.Free;
+  end;
+end;
+
+procedure TOQBForm.btnResultsClick(Sender: TObject);
+begin
+  // We may be able to generate the SQL if the user has
+  // visually created one
+  if MemoSQL.Lines.Text='' then
+    btnSQLClick(Sender);
+  QBDialog.OQBEngine.CloseResultQuery; // OQB 4.0a
+  QBDialog.OQBEngine.SetQuerySQL(MemoSQL.Lines.Text);
+  QBDialog.OQBEngine.OpenResultQuery;
+  Pages.ActivePage := TabResults;
+end;
+
+procedure TOQBForm.btnAboutClick(Sender: TObject);
+var
+  QBAboutForm: TOQBAboutForm;
+begin
+  QBAboutForm := TOQBAboutForm.Create(Application);
+  QBAboutForm.ShowModal;
+  QBAboutForm.Free;
+end;
+
+procedure TOQBForm.btnSaveResultsClick(Sender: TObject);
+begin
+  QBDialog.OQBEngine.SaveResultQueryData;
+end;
+
+procedure TOQBForm.btnOKClick(Sender: TObject);
+begin
+  ModalResult := mrOk;
+end;
+
+procedure TOQBForm.btnCancelClick(Sender: TObject);
+begin
+  ModalResult := mrCancel;
+end;
+
+end.

+ 65 - 0
license.txt

@@ -0,0 +1,65 @@
+All copyrights to Open QBuilder are owned by Sergey Orlik and 
+Fast Reports, Inc.
+
+The Open QBuilder is freeware. This means:
+
+  You may use this software during any period of time.
+
+  The  Open QBuilder  may be  freely  distributed,  provided  the
+distribution  package is  not  modified. No person or  company may
+charge a fee for the distribution of Open QBuilder without written
+permission from the copyright holder.
+
+  THE  FAST FONT SET IS  DISTRIBUTED "AS  IS". NO WARRANTY OF ANY 
+KIND IS EXPRESSED OR IMPLIED. YOU USE AT YOUR OWN RISK. THE AUTHOR 
+WILL NOT BE LIABLE  FOR DATA LOSS, DAMAGES, LOSS OF PROFITS OR ANY 
+OTHER KIND OF LOSS WHILE USING OR MISUSING THIS SOFTWARE.
+
+  You   may  not  emulate,  clone,  rent,  lease,  sell,  modify,
+decompile,  disassemble, otherwise reverse engineer Open QBuilder, 
+except  as  provided  for in this agreement. Any such unauthorized   
+use shall result in immediate and automatic  termination  of  this 
+license and may result in criminal and/or civil prosecution.
+
+  All rights not expressly  granted here are reserved by Fast 
+Reports, Inc.
+
+  This  license  is not distributed to the distribution  packages
+created  with  the  Open QBuilder. You may freely dispose of your 
+distribution packages.
+
+  Installing  and  using  Open QBuilder signifies acceptance of 
+these terms and conditions of the license.
+
+  If  you  do not agree with the terms of this license  you  must
+remove Open QBuilder files  from your storage devices and cease to 
+use the product.
+
+
+=============================================================================
+Copyright (c) 1996-2003 Sergey Orlik 
+Copyright (c) 2003 Fast Reports, Inc
+=============================================================================
+http://www.fast-report.com/en/oqb.php
+
+=============================================================================
+Converted to Lazarus/Free Pascal by Jean Patrick      
+Data: 14/02/2013                                      
+E-mail: [email protected]                     
+=============================================================================
+
+Clarification on license:
+http://support.fast-report.com/tickets/260019?key=4f6db20d1c96007
+Question:
+"I created a modified version of the Open Query Builder to compile in Lazarus. It&#039;s working perfectly, with all the resources in Windows and Linux GTK2 and QT. I created also an enginer to connect with a suite of components ZEOS.
+
+Download: http://github.com/jepafi/Laz_Query_Builder/archive/master.zip
+
+I wonder if you have any objections to what I did? And what you allow me to do with the modified code? Can I use the code converted to Lazarus in commercial software?
+
+Link to Laz Query builder: https://github.com/jepafi/Laz_Query_Builder
+
+Discussion what is happening in Lazarus forum: http://www.lazarus.freepascal.org/index.php/topic, 19927.0.html "
+Response from Den Zubov:
+"Hello,
+We don't have any objections it's an open source software you can use it whatever you want. "

BIN
project1.ico


+ 153 - 0
project1.lpi

@@ -0,0 +1,153 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<CONFIG>
+  <ProjectOptions>
+    <Version Value="9"/>
+    <General>
+      <SessionStorage Value="InProjectDir"/>
+      <MainUnit Value="0"/>
+      <Title Value="project1"/>
+      <ResourceType Value="res"/>
+      <UseXPManifest Value="True"/>
+      <Icon Value="0"/>
+    </General>
+    <i18n>
+      <EnableI18N LFM="False"/>
+    </i18n>
+    <VersionInfo>
+      <StringTable ProductVersion=""/>
+    </VersionInfo>
+    <BuildModes Count="1">
+      <Item1 Name="Default" Default="True"/>
+    </BuildModes>
+    <PublishOptions>
+      <Version Value="2"/>
+      <IncludeFileFilter Value="*.(pas|pp|inc|lfm|lpr|lrs|lpi|lpk|sh|xml)"/>
+      <ExcludeFileFilter Value="*.(bak|ppu|o|so);*~;backup"/>
+    </PublishOptions>
+    <RunParams>
+      <local>
+        <FormatVersion Value="1"/>
+        <LaunchingApplication PathPlusParams="/usr/bin/xterm -T 'Lazarus Run Output' -e $(LazarusDir)/tools/runwait.sh $(TargetCmdLine)"/>
+      </local>
+    </RunParams>
+    <RequiredPackages Count="1">
+      <Item1>
+        <PackageName Value="LCL"/>
+      </Item1>
+    </RequiredPackages>
+    <Units Count="11">
+      <Unit0>
+        <Filename Value="project1.lpr"/>
+        <IsPartOfProject Value="True"/>
+      </Unit0>
+      <Unit1>
+        <Filename Value="unit1.pas"/>
+        <IsPartOfProject Value="True"/>
+        <ComponentName Value="Form1"/>
+        <HasResources Value="True"/>
+        <ResourceBaseClass Value="Form"/>
+        <UnitName Value="Unit1"/>
+      </Unit1>
+      <Unit2>
+        <Filename Value="QBDBFrm.pas"/>
+        <IsPartOfProject Value="True"/>
+        <HasResources Value="True"/>
+        <UnitName Value="QBDBFrm"/>
+      </Unit2>
+      <Unit3>
+        <Filename Value="QBDBFrm2.pas"/>
+        <IsPartOfProject Value="True"/>
+        <ComponentName Value="OQBDBForm2"/>
+        <HasResources Value="True"/>
+        <ResourceBaseClass Value="Form"/>
+        <UnitName Value="QBDBFrm2"/>
+      </Unit3>
+      <Unit4>
+        <Filename Value="QBAbout.pas"/>
+        <IsPartOfProject Value="True"/>
+        <HasResources Value="True"/>
+        <UnitName Value="QBAbout"/>
+      </Unit4>
+      <Unit5>
+        <Filename Value="QBuilder.pas"/>
+        <IsPartOfProject Value="True"/>
+        <ComponentName Value="OQBForm"/>
+        <HasResources Value="True"/>
+        <ResourceBaseClass Value="Form"/>
+        <UnitName Value="QBuilder"/>
+      </Unit5>
+      <Unit6>
+        <Filename Value="QBEZEOS.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="QBEZEOS"/>
+      </Unit6>
+      <Unit7>
+        <Filename Value="QBDirFrm.pas"/>
+        <IsPartOfProject Value="True"/>
+        <HasResources Value="True"/>
+        <UnitName Value="QBDirFrm"/>
+      </Unit7>
+      <Unit8>
+        <Filename Value="QBLnkFrm.pas"/>
+        <IsPartOfProject Value="True"/>
+        <ComponentName Value="OQBLinkForm"/>
+        <HasResources Value="True"/>
+        <ResourceBaseClass Value="Form"/>
+        <UnitName Value="QBLnkFrm"/>
+      </Unit8>
+      <Unit9>
+        <Filename Value="QBESqlDb.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="QBESqlDb"/>
+      </Unit9>
+      <Unit10>
+        <Filename Value="QBEIBX.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="QBEIBX"/>
+      </Unit10>
+    </Units>
+  </ProjectOptions>
+  <CompilerOptions>
+    <Version Value="11"/>
+    <Target>
+      <Filename Value="project1"/>
+    </Target>
+    <SearchPaths>
+      <IncludeFiles Value="$(ProjOutDir)"/>
+      <UnitOutputDirectory Value="lib/$(TargetCPU)-$(TargetOS)"/>
+    </SearchPaths>
+    <CodeGeneration>
+      <Optimizations>
+        <OptimizationLevel Value="0"/>
+      </Optimizations>
+    </CodeGeneration>
+    <Linking>
+      <Debugging>
+        <DebugInfoType Value="dsDwarf2Set"/>
+        <StripSymbols Value="True"/>
+      </Debugging>
+      <Options>
+        <Win32>
+          <GraphicApplication Value="True"/>
+        </Win32>
+      </Options>
+    </Linking>
+    <Other>
+      <CustomOptions Value="-dQBESQLDB
+-O-1"/>
+    </Other>
+  </CompilerOptions>
+  <Debugging>
+    <Exceptions Count="3">
+      <Item1>
+        <Name Value="EAbort"/>
+      </Item1>
+      <Item2>
+        <Name Value="ECodetoolError"/>
+      </Item2>
+      <Item3>
+        <Name Value="EFOpenError"/>
+      </Item3>
+    </Exceptions>
+  </Debugging>
+</CONFIG>

+ 32 - 0
project1.lpr

@@ -0,0 +1,32 @@
+program project1;
+
+{$mode objfpc}{$H+}
+
+uses
+  {$IFDEF UNIX}{$IFDEF UseCThreads}
+  cthreads,
+  {$ENDIF}{$ENDIF}
+  Interfaces, // this includes the LCL widgetset
+  Forms, Unit1, QBDBFrm, QBDBFrm2, QBAbout, QBuilder
+  {$IFDEF QBESQLDB}
+  , QBESqlDb
+  {$ENDIF}
+  {$IFDEF QBEZEOS}
+  , QBEZEOS
+  {$ENDIF}
+  {$IFDEF QBEIBX}
+  , QBEIBX
+  {$ENDIF}
+  , QBDirFrm, QBLnkFrm
+  ;
+
+{$R *.res}
+
+begin
+  RequireDerivedFormResource := True;
+  Application.Initialize;
+  Application.CreateForm(TForm1, Form1);
+  //Application.CreateForm(TOQBForm, OQBForm);
+  Application.Run;
+end.
+

BIN
project1.res


+ 58 - 0
readme.txt

@@ -0,0 +1,58 @@
+15.10.03
+ver. 4.01
+for Delphi 4-7 and C++Builder 4-6
+
+========================================================================
+             The Open QBuilder for Delphi and C++Builder
+========================================================================
+
+The Open QBuilder (OQBuilder) is a simple visual query builder component set
+for Delphi and C++Builder developers. 
+Open QBuilder is the next generation of well-known QBuilder.
+
+Please, read more about OQBuilder's in the short documentation file: 
+/Doc/oqbuilder.html
+
+Please, check the /Doc/history.txt file to read about the latest changes and 
+additions.
+
+The latest version of OQBuilder and additional components you can find on
+OQBuilder home page at:
+http://www.fast-report.com/en/qbuilder.php
+
+========================================================================
+
+About using OQBuilder in your projects
+--------------------------------------
+
+Open QBuilder and another my tools and components are freeware. 
+I can't provide the technical support for these tools, but you have all 
+source code and you can modify it without restriction for any non-commercial 
+projects. 
+
+Please, let me know if you want to use my software in your commercial projects 
+by e-mail: [email protected] 
+with tool name in a message subject.
+
+========================================================================
+
+About Author
+------------
+
+  Sergey Orlik
+  product manager 
+  Borland Moscow office
+  Russia, CIS and Baltic States
+
+  E-mail: [email protected]
+  Home page: 
+    http://www.fast-report.com/en/qbuilder.php
+
+========================================================================
+Copyright (c) 1996-2003 Sergey Orlik 
+Copyright (c) 2003 Fast Reports, Inc
+========================================================================
+
+Adapted for Lazarus Zeosdb by Jepafi.
+Modified (added SQLDB, IBX from original Open QBuilder) by Reinier Olislagers
+See license.txt and source files.

+ 37 - 0
unit1.lfm

@@ -0,0 +1,37 @@
+object Form1: TForm1
+  Left = 420
+  Height = 368
+  Top = 205
+  Width = 489
+  Caption = 'Form1'
+  ClientHeight = 368
+  ClientWidth = 489
+  OnCreate = FormCreate
+  OnDestroy = FormDestroy
+  LCLVersion = '1.3'
+  object Button1: TButton
+    Left = 16
+    Height = 25
+    Top = 20
+    Width = 105
+    Caption = 'Query Builder'
+    OnClick = Button1Click
+    TabOrder = 0
+  end
+  object Memo1: TMemo
+    Left = 0
+    Height = 304
+    Top = 64
+    Width = 489
+    Align = alBottom
+    Font.CharSet = ANSI_CHARSET
+    Font.Height = -13
+    Font.Name = 'Courier New'
+    Font.Pitch = fpFixed
+    Font.Quality = fqDraft
+    ParentFont = False
+    ScrollBars = ssAutoBoth
+    TabOrder = 1
+    WordWrap = False
+  end
+end

+ 161 - 0
unit1.pas

@@ -0,0 +1,161 @@
+unit Unit1;
+
+{$mode objfpc}{$H+}
+
+// Please define at project level (Project Options/Other, defines) either
+
+// -dQBEZEOS: Use Zeos in Visual Query Builder
+// Please add a project requirement to Zeos zcomponent
+// The example uses a Firebird connection (see code below).
+// You can of course change this
+
+// or
+
+// -dQBESQLDB: Use SQLDB in Visual Query Builder
+// This example uses a Firebird ibconnection.
+// You can of course change this.
+
+// or
+
+// -dQBEIBX: Use IBX objects in Visual Query Builder
+// to do: needs to be tested/implemented in this demo form
+
+{ todo:
+- rework as package
+- doubleclick in sort cell sorts asc/desc/none not only rightclick
+- reinstate registering engines such as sqldb, zeos, ibx so package requirements
+  can be easily specified
+- extract icons rework them as png or whatever so we have source
+- test on Linux, OSX
+}
+interface
+
+uses
+  SysUtils, Forms, StdCtrls, QBuilder
+  {$IFDEF QBEIBX}
+  , {IBDatabase? ,} QBEIBX
+  {$ENDIF}
+  {$IFDEF QBESQLDB}
+  , sqldb, QBESqlDb
+  , IBConnection {change this if you want another db}
+  {$ENDIF}
+  {$IFDEF QBEZEOS}
+  , ZConnection, QBEZEOS
+  {$ENDIF}
+  , Classes;
+
+type
+
+  { TForm1 }
+
+  TForm1 = class(TForm)
+    Button1: TButton;
+    Memo1: TMemo;
+    {$IFDEF QBESQLDB}
+    FDbConnection: TIBConnection;
+    FDBTrans: TSQLTransaction;
+    {$ENDIF}
+    {$IFDEF QBEZEOS}
+    FDbConnection: TZConnection;
+    {$ENDIF}
+    //todo: add support for QBEIBX
+    procedure Button1Click(Sender: TObject);
+    procedure FormCreate(Sender: TObject);
+    procedure FormDestroy(Sender: TObject);
+  private
+    { private declarations }
+  public
+    { public declarations }
+  end;
+
+var
+  Form1: TForm1;
+
+implementation
+
+{ TForm1 }
+
+procedure TForm1.Button1Click(Sender: TObject);
+var
+  meuqb: TOQBuilderDialog;
+  {$IFDEF QBEIBX}
+  VisualQueryEngine: TOQBEngineIBX;
+  {$ENDIF}
+  {$IFDEF QBESQLDB}
+  VisualQueryEngine: TOQBEngineSQLDB;
+  {$ENDIF}
+  {$IFDEF QBEZEOS}
+  VisualQueryEngine: TOQBEngineZEOS;
+  {$ENDIF}
+begin
+  try
+    //todo: add ibx code
+    {$IFDEF QBESQLDB}
+    FDbConnection.DatabaseName := ExtractFilePath(Application.ExeName)+'EMPLOYEE.FDB';
+    {$ENDIF}
+    {$IFDEF QBEZEOS}
+    DbConnection.Database := ExtractFilePath(Application.ExeName)+'EMPLOYEE.FDB';
+    {$ENDIF}
+    meuqb := TOQBuilderDialog.Create(nil);
+    {$IFDEF QBESQLDB}
+    VisualQueryEngine := TOQBEngineSQLDB.Create(nil);
+    {$ENDIF}
+    {$IFDEF QBEZEOS}
+    VisualQueryEngine := TOQBEngineZEOS.Create(nil);
+    {$ENDIF}
+    VisualQueryEngine.Connection := FDbConnection;
+    meuqb.OQBEngine := VisualQueryEngine;
+    {$IFDEF QBESQLDB}
+    meuqb.OQBEngine.DatabaseName := FDbConnection.DatabaseName;
+    {$ENDIF}
+    {$IFDEF QBEZEOS}
+    meuqb.OQBEngine.DatabaseName := DbConnection.Database;
+    // If using OQBEngineZEOS: to specify a  PostgreSQL schema, set
+    // VisualQueryEngine.SchemaPostgreSQL := 'my_schema';
+    VisualQueryEngine.ShowSystemTables := False;
+    {$ENDIF}
+    {$IFDEF QBESQLDB}
+    FDbConnection.Open;
+    {$ENDIF}
+    {$IFDEF QBEZEOS}
+    DbConnection.Connect;
+    {$ENDIF}
+    if meuqb.Execute then Memo1.Text := meuqb.SQL.Text;
+  finally
+    meuqb.Free;
+    VisualQueryEngine.Free;
+  end;
+end;
+
+procedure TForm1.FormCreate(Sender: TObject);
+begin
+  // Example using Firebird embedded for both QBESQLDB and QBEZEOS
+  //todo: add ibx code
+  {$IFDEF QBESQLDB}
+  FDbConnection := TIBConnection.Create(nil);
+  FDbConnection.HostName := '';
+  FDbConnection.UserName := 'SYSDBA';
+  FDBTrans := TSQLTransaction.Create(nil);
+  FDbConnection.Transaction := FDBTrans;
+  {$ENDIF}
+  {$IFDEF QBEZEOS}
+  DbConnection:=ZConnection.Create(nil);
+  DbConnection.Protocol := 'firebird-2.5';
+  DbConnection.ControlsCodePage := cCP_UTF8;
+  DbConnection.User := 'SYSDBA';
+  {$ENDIF}
+  FDbConnection.Password := ''; //leave empty to avoid lookup in FB security db
+end;
+
+procedure TForm1.FormDestroy(Sender: TObject);
+begin
+  {$IFDEF QBESQLDB}
+  FDBTrans.Free;
+  {$ENDIF}
+  FDbConnection.Free;
+end;
+
+{$R *.lfm}
+
+end.
+