{***************************************************************************}
{ TMS IntraWeb Component Pack Pro                                           }
{ for Delphi & C++Builder                                                   }
{                                                                           }
{ written by TMS Software                                                   }
{            copyright © 2002 - 2009                                        }
{            Email : info@tmssoftware.com                                   }
{            Web : http://www.tmssoftware.com                               }
{                                                                           }
{ The source code is given as is. The author is not responsible             }
{ for any possible damage done due to the use of this code.                 }
{ The component can be freely used in any application. The complete         }
{ source code remains property of the author and may not be distributed,    }
{ published, given or sold in any form as such. No parts of the source      }
{ code can be included in any other component or application without        }
{ written authorization of the author.                                      }
{***************************************************************************}

unit IWWebGrid;

{$I TMSDEFS.INC}

interface

{$R tmsiwgrid.res}
{$R tmsiwgridjs.res}
{$R tmsiwgridcal.res}
                                                                 
uses
  {$IFDEF LINUX}
  QControls, QGraphics, QIWPicCntnr, QImgList, IWJPEG,
  {$ELSE}
  Controls, Windows, Graphics, IWPicCntnr, IWTMSImg, JPEG,
  {$ENDIF}
  {$IFDEF DELPHI6_LVL}
  Types,
  {$ENDIF}
  Classes,
  IWControl, IWTypes, SysUtils, IWTMSBase, IWExtCtrls, IWHTMLTag,
  IWFont, IWGlobal
  {$IFDEF TMSIW51}
  , IWColor
  {$ENDIF}
  {$IFDEF FREEWARE}
  {$IFDEF TMSIW51}
  , IWKlooch
  {$ELSE}                                
  {$IFNDEF DELPHI7_LVL}
  , IWKlooch
  {$ENDIF}
  {$ENDIF}
  {$ENDIF}
  {$IFDEF TMSIW6}
  , IWRenderContext
  {$ENDIF}
  {$IFDEF TMSIW9}
  , IWXMLTag
  {$ENDIF}
  ;              


const
  Months: array[1..12] of string = ('January','February','March','April','May','June','July','August','September','October','November','December');
{$IFDEF FREEWARE}
  FWNOTICE = 'TMS IntraWeb Grid Components evaluation';
{$ENDIF}

type
  TTIWCustomWebGrid = class;

  TTIWWebGridColumns = class;

  TTIWWidthType = (wtNone, wtAbsolute, wtPercent);

  TTIWGridState = (gsInsert, gsEdit, gsBrowse);

  TTIWColumnType = (ctNormal, ctCheckbox, ctButton, ctRowIndicator, ctRowNumber,
    ctScroll, ctPopup, ctLink, ctLinkField, ctLinkRowNumber, ctDataCheckbox, ctImage,
    ctDataImage, ctURL, ctEmail, ctDataButton, ctRadioButton, ctDynEdit,
    ctDynText, ctDynMemo, ctDynCombo, ctDynCheckBox, ctNode, ctPassword, ctProgress, ctPopupImage,
    ctImageCheckBox, ctDataImageCheckBox, ctNoWrap);

  TTIWDynEditType = (deText, deUnsigned, deSigned, deFloatUnsigned,
    deFloatSigned);

  TTIWFooterType = (ftText, ftPageSum, ftPageMin, ftPageMax, ftPageAvg, ftNone,
    ftDynSum, ftDynMin, ftDynMax, ftDynAvg);

  TTIWMouseSelect = (msNone, msSingleCell, msRow, msRowCheck, msSingleRowCheck, msMove, msClient, msEdit);

  TTIWDetailRowShow = (dsNormal, dsOneOpen, dsAllOpen, dsServerOpen, dsServerOneOpen);

  TTIWGridDateFormat = (gdEU, gdUS);

  TIWRGColumnHeaderClick = procedure(Sender: TObject; ColumnIndex: Integer) of
    object;

  TIWRGButtonClick = procedure(Sender: TObject; RowIndex, ColumnIndex: Integer)
    of object;

  {$IFDEF TMSIW9}
  TIWAsyncButtonEvent = procedure (Sender: TObject; EventParams: TStringList;
    RowIndex, ColumnIndex: Integer) of object;
  TIWAsyncComboChangeEvent = procedure (Sender: TObject; EventParams: TStringList;
    RowIndex, ColumnIndex: Integer;
  AValue: string) of object;
  TIWAsyncEditDoneEvent = procedure (Sender: TObject; EventParams: TStringList;
    RowIndex, ColumnIndex: Integer;  AValue: string) of object;
  TIWAsyncValidateEvent = procedure (Sender: TObject; EventParams: TStringList;
    RowIndex, ColumnIndex: Integer; var AValue: string; var AMessage: string) of object;
  TIWAsyncPageEvent = procedure (Sender: TObject; EventParams: TStringList; Page: Integer) of object;
  TIWAsyncColumnEvent = procedure (Sender: TObject; EventParams: TStringList; ColumnIndex: Integer) of object;
  TIWAsyncPostValidateEvent = procedure(Sender: TObject; PostData: TStringList;
    var Allow: Boolean; var EditMode: Boolean; var AlertMessage: string) of object;
  TIWAsyncRowSelectEvent = procedure (Sender: TObject; EventParams: TStringList;
    RowIndex: integer; Checked: boolean) of object;
  TIWAsyncRowEvent = procedure(Sender: TObject; EventParams: TStringList; Row: Integer) of object;
  {$ENDIF}

  TIWRowCountEvent = procedure(Sender: TObject; RowCount: Integer) of object;

  TIWComboChangeEvent = procedure(Sender: TObject; RowIndex, ColumnIndex: Integer; AValue: string)
    of object;

  TIWRGCellDataEvent = procedure(Sender: TObject; RowIndex, ColumnIndex:
    Integer; var AValue: string) of object;

  TIWRowHeaderTextEvent = procedure(Sender: TObject; RowIndex:
    Integer; var AValue: string) of object;

  TIWRGCellEditorEnabled = procedure(Sender: TObject; RowIndex, ColumnIndex:
    Integer; var Enabled: Boolean) of object;

  TIWRGCellValueEvent = procedure(Sender: TObject; RowIndex, ColumnIndex:
    Integer; AValue: string) of object;

  TIWRGDetailGridEvent = procedure(Sender: TObject; RowIndex: Integer;
    var AGrid: TTIWCustomWebGrid) of object;

  TIWRGCellPropEvent = procedure(Sender: TObject; RowIndex, ColumnIndex:
    Integer; AValue: string;
    var AColor: TIWColor; var AAlignment: TAlignment; Font: TIWFont) of object;

  TTIWRGImageIndexEvent = procedure(Sender: TObject; RowIndex, ColumnIndex:
    Integer;
    var AValue: integer) of object;

  TTIWColumnEditor = (edNone, edEdit, edPassword, edCombo, edMemo, edCheckbox,
    edEditNumeric, edEditFloat,
    edEditLower, edEditUpper, edEditHex, edDatePicker, edSpinEdit, edPopupEdit);

  TIWRGCellType = procedure(Sender: TObject; RowIndex, ColumnIndex:
    Integer; var AColumnType: TTIWColumnType; var Editor: TTIWColumnEditor; var DynEditor: TTIWDynEditType) of object;

  TTIWPageEvent = procedure(Sender: TObject; Page: Integer) of object;

  TTIWRowEvent = procedure(Sender: TObject; Row: Integer) of object;

  TTIWNodeShowEvent = procedure(Sender: TObject; Row: Integer; var Show: Boolean) of object;

  TTIWCellAllowEvent = procedure(Sender: TObject; RowIndex, ColumnIndex: Integer;
    var Allow: Boolean) of object;

  TTIWBeforeLinkEvent = procedure(Sender: TObject; RowIndex, ColumnIndex:
    Integer; var Allow: Boolean) of object;

  TTIWAfterLinkEvent = procedure(Sender: TObject; RowIndex, ColumnIndex: Integer) of object;

  TTIWFilterEvent = procedure(Sender: TObject; ColumnIndex: Integer; FilterValue: string) of object;

  TTIWPostValidateEvent = procedure(Sender: TObject; PostData: TStringList; var Allow: Boolean) of object;

  TTIWGetDynText = procedure(Sender: TObject; RowIndex, ColumnIndex: Integer; var
    AValue: string) of object;

  TTIWDirectEditUpdate = procedure(Sender: TObject; ACol,ARow: Integer; var Value: string; var Allow: Boolean) of object;

  TTIWVAlign = (vaNone, vaTop, vaBottom, vaMiddle);

  TTIWGradientDirection = (gdHorizontal, gdVertical);

  TInnerBorders = (ibAll, ibRows, ibColumns, ibNone);

  TOuterBorders = (obAll, obVertical, obHorizontal, obNone);

  TCollapse = (coCollapse, coSeperate);

  TTIWRGBorders = class(TPersistent)
  private
    FOwner: TTIWCustomWebGrid;
    FInner: TInnerBorders;
    FOuter: TOuterBorders;
    FWidth: Integer;
    FColor: TIWColor;
    FSpacing: Integer;
    FPadding: Integer;
    FColorLight: TIWColor;
    FColorDark: TIWColor;
    FCollapsed: Boolean;
    procedure SetInner(const Value: TInnerBorders);
    procedure SetOuter(const Value: TOuterBorders);
    procedure SetWidth(const Value: Integer);
    procedure SeTIWColor(const Value: TIWColor);
    procedure SetPadding(const Value: Integer);
    procedure SetSpacing(const Value: Integer);
    procedure SeTIWColorDark(const Value: TIWColor);
    procedure SeTIWColorLight(const Value: TIWColor);
    procedure SetCollapsed(const Value: Boolean);
  public
    constructor Create(AOwner: TTIWCustomWebGrid);
  published
    property Inner: TInnerBorders read FInner write SetInner;
    property Outer: TOuterBorders read FOuter write SetOuter;
    property Padding: Integer read FPadding write SetPadding;
    property Spacing: Integer read FSpacing write SetSpacing;
    property Width: Integer read FWidth write SetWidth;
    property Collapsed: Boolean read FCollapsed write SetCollapsed;
    property Color: TIWColor read FColor write SeTIWColor;
    property ColorDark: TIWColor read FColorDark write SeTIWColorDark;
    property ColorLight: TIWColor read FColorLight write SeTIWColorLight;
  end;

  TTIWScroll = (scNever, scAlways, scAuto);

  TTIWHeaderStyle = (hsFlat, hsRaised);

  TTIWWebGridOuterBorder = class(TPersistent)
  private
    FShow: Boolean;
    FColor: TIWColor;
  protected
  public
  published
    property Show: Boolean read FShow write FShow;
    property Color: TIWColor read FColor write FColor;
  end;

  TTIWWebGridScroll = class(TPersistent)
  private
    FStyle: TTIWScroll;
    FOnChange: TNotifyEvent;
    FPersistent: Boolean;
    FScrollbar3DLightColor: TIWColor;
    FScrollbarArrowColor: TIWColor;
    FScrollbarBaseColor: TIWColor;
    FScrollbarTrackColor: TIWColor;
    FScrollbarDarkshadowColor: TIWColor;
    FScrollbarFaceColor: TIWColor;
    FScrollbarHighlightColor: TIWColor;
    FScrollbarShadowColor: TIWColor;
    FScrollIntoView: boolean;
    procedure SetStyle(const Value: TTIWScroll);
  protected
    procedure Changed;
  public
    constructor Create;
  published
    property Style: TTIWScroll read FStyle write SetStyle;
    property Persistent: Boolean read FPersistent write FPersistent default true;
    property OnChange: TNotifyEvent read FOnChange write FOnChange;
    property Scrollbar3DLightColor: TIWColor read FScrollbar3DLightColor write FScrollbar3DLightColor;
    property ScrollbarArrowColor: TIWColor read FScrollbarArrowColor write FScrollbarArrowColor;
    property ScrollbarBaseColor: TIWColor read FScrollbarBaseColor write FScrollbarBaseColor;
    property ScrollbarTrackColor: TIWColor read FScrollbarTrackColor write FScrollbarTrackColor;
    property ScrollbarDarkshadowColor: TIWColor read FScrollbarDarkshadowColor write FScrollbarDarkshadowColor;
    property ScrollbarFaceColor: TIWColor read FScrollbarFaceColor write FScrollbarFaceColor;
    property ScrollbarHighlightColor: TIWColor read FScrollbarHighlightColor write FScrollbarHighlightColor;
    property ScrollbarShadowColor: TIWColor read FScrollbarShadowColor write FScrollbarShadowColor;
    property ScrollIntoView: boolean read FScrollIntoView write FScrollIntoView default true;
  end;

  TTIWDataButtonType = (dbtButton, dbtImage, dbtLink);

  TTIWWebGridRowHeader = class(TPersistent)
  private
    FShowRowHeader: Boolean;
    FRowHeaderWidth: Integer;
    FRowHeaderColor: TIWColor;
    FRowHeaderGradient1: TIWColor;
    FRowHeaderGradient2: TIWColor;
    FRowHeaderGradientDirection: TTIWGradientDirection;
    FRowHeaderBorders: TTIWRGBorders;
  protected
//    procedure Changed;
  public
    constructor Create(AOwner: TTIWCustomWebGrid);
    destructor Destroy; override;
  published
    property Show: Boolean read FShowRowHeader write FShowRowHeader;
    property Width: Integer read FRowHeaderWidth write FRowHeaderWidth;
    property Borders: TTIWRGBorders read FRowHeaderBorders write FRowHeaderBorders;
    property Color: TIWColor read FRowHeaderColor write FRowHeaderColor;
    property Gradient1: TIWColor read FRowHeaderGradient1 write FRowHeaderGradient1;
    property Gradient2: TIWColor read FRowHeaderGradient2 write FRowHeaderGradient2;
    property GradientDirection: TTIWGradientDirection read FRowHeaderGradientDirection write FRowHeaderGradientDirection;
//    property OnChange: TNotifyEvent read FOnChange write FOnChange;
  end;

  TTIWWebGridColumn = class(TCollectionItem)
  private
    FCalcValue: Double;
    FOwner: TTIWWebGridColumns;
    FTemplate: string;
    FWidth: integer;
    FTitle: string;
    FColor: TIWColor;
    FColumnHeaderColor: TIWColor;
    FWidthType: TTIWWidthType;
    FAlignment: TAlignment;
    FColumnType: TTIWColumnType;
    FButtonText: string;
    FColumnHeaderClick: boolean;
    FColumnHeaderAlignment: TAlignment;
    FFont: TIWFont;
    FColumnHeaderFont: TIWFont;
    FPopupWidth: Integer;
    FPopupColor: TIWColor;
    FPopupColorTo: TIWColor;
    FPopupColorGradientDirection: TTIWGradientDirection;
    FImageHeight: Integer;
    FImageWidth: Integer;
    FShowHint: Boolean;
    FEditor: TTIWColumnEditor;
    FComboItems: TStringList;
    FComboValues: TStringList;
    FAllowSizing: Boolean;
    FFooterText: string;
    FFooterType: TTIWFooterType;
    FFooterAlignment: TAlignment;
    FTag: Integer;
    FFooterFormat: string;
    FImageIndex: Integer;
    FColumnHeaderGradient1: TIWColor;
    FColumnHeaderGradient2: TIWColor;
    FFooterGradient1: TIWColor;
    FFooterGradient2: TIWColor;
    FFilter: Boolean;
    FFilterList: TStringList;
    FFilterIndex: Integer;
    FFormula: string;
    FDynPrecision: Integer;
    FTitleSpan: Integer;
    FSubTitleSpan: Integer;
    FSubTitle: string;
    FName: string;
    FCheckTrue: string;
    FCheckFalse: string;
    FColumnHeaderCheckBox: Boolean;
    FDynEditor: TTIWDynEditType;
    FClickConfirm: string;
    FHint: string;
    FRequiredMsg: string;
    FMaxLength: Integer;
    FGradientDirection: TTIWGradientDirection;
    FVisible: Boolean;
    FTitleRowSpan: Boolean;
    FSubTitleVAlign: TTIWVAlign;
    FTitleVAlign: TTIWValign;
    FVAlign: TTIWVAlign;
    FDetailSpan: Integer;
    FDetailTemplate: string;
    FDetailColor: TIWColor;
    FDetailFont: TIWFont;
    FColumnHeaderNode: Boolean;
    FEnabled: Boolean;
    FProgressColor: TIWColor;
    FPopupHeight: Integer;
    FButtonWidth: integer;
    FButtonColor: TIWColor;
    FDataButtonType: TTIWDataButtonType;
    FDefaultDynEdit: string;
    FDefaultDynText: string;
    FSpinEditMaxValue: Integer;
    FSpinEditMinValue: Integer;
    FSpinEditAutoSpin: Boolean;
    FCanSort: boolean;
    {$IFDEF TMSIW6}
    FCursor: TIWCursor;
    {$ENDIF}
    procedure SetTemplate(const Value: string);
    procedure SeTIWColor(const Value: TIWColor);
    procedure SetTitle(const Value: string);
    procedure SetColumnHeaderColor(const Value: TIWColor);
    procedure SetWidth(const Value: integer);
    procedure SetWidthType(const Value: TTIWWidthType);
    procedure SetAlignment(const Value: TAlignment);
    procedure SetColumnType(const Value: TTIWColumnType);
    procedure SetButtonText(const Value: string);
    procedure SetColumnHeaderClick(const Value: boolean);
    procedure SetColumnHeaderAlignment(const Value: TAlignment);
    procedure SetFont(const Value: TIWFont);
    procedure SetDetailFont(const Value: TIWFont);
    procedure SetColumnHeaderFont(const Value: TIWFont);
    procedure SetComboItems(const Value: TStringList);
    procedure SetComboValues(const Value: TStringList);
    procedure SetFooterText(const Value: string);
    procedure SetFooterType(const Value: TTIWFooterType);
    procedure SetFooterAlignment(const Value: TAlignment);
    property CalcValue: Double read FCalcValue write FCalcValue;
    procedure SetFooterFormat(const Value: string);
    procedure SetImageIndex(const Value: Integer);
    procedure SetFilterList(const Value: TStringList);
    procedure SetSubTitle(const Value: string);
    procedure SetSubTitleSpan(const Value: Integer);
    procedure SetTitleSpan(const Value: Integer);
    procedure SetVisible(const Value: Boolean);
    procedure SetTitleRowSpan(const Value: Boolean);
  protected
    function GetDisplayName: string; override;
  public
    constructor Create(AOwner: TCollection); override;
    destructor Destroy; override;
    procedure Changed;
    procedure Assign(Source: TPersistent); override;
    procedure AssignVisualProperties(Source: TPersistent); virtual;
  published
    property Alignment: TAlignment read FAlignment write SetAlignment default taLeftJustify;
    property AllowSizing: Boolean read FAllowSizing write FAllowSizing default False;
    property ButtonColor: TIWColor read FButtonColor write FButtonColor default clNone;
    property ButtonText: string read FButtonText write SetButtonText;
    property ButtonWidth: integer read FButtonWidth write FButtonWidth default 64;
    property CanSort: boolean read FCanSort write FCanSort default true;
    property CheckTrue: string read FCheckTrue write FCheckTrue;
    property CheckFalse: string read FCheckFalse write FCheckFalse;
    property ClickConfirm: string read FClickConfirm write FClickConfirm;
    property Color: TIWColor read FColor write SeTIWColor default clNone;
    property ColumnHeaderAlignment: TAlignment read FColumnHeaderAlignment write
      SetColumnHeaderAlignment default taLeftJustify;
    property ColumnHeaderClick: boolean read FColumnHeaderClick write
      SetColumnHeaderClick default true;
    property ColumnHeaderColor: TIWColor read FColumnHeaderColor write
      SetColumnHeaderColor default clNone;
    property ColumnHeaderFont: TIWFont read FColumnHeaderFont write
      SetColumnHeaderFont;
    property ColumnHeaderGradient1: TIWColor read FColumnHeaderGradient1 write
      FColumnHeaderGradient1 default clNone;
    property ColumnHeaderGradient2: TIWColor read FColumnHeaderGradient2 write
      FColumnHeaderGradient2 default clNone;
    property ColumnHeaderGradientDirection: TTIWGradientDirection read
      FGradientDirection write FGradientDirection default gdHorizontal;
    property ColumnHeaderCheckBox: Boolean read FColumnHeaderCheckBox write
      FColumnHeaderCheckBox default false;
    property ColumnHeaderNode: Boolean read FColumnHeaderNode write
      FColumnHeaderNode default false;
    property ColumnType: TTIWColumnType read FColumnType write SetColumnType default ctNormal;
    property ComboItems: TStringList read FComboItems write SetComboItems;
    property ComboValues: TStringList read FComboValues write SetComboValues;
    {$IFDEF TMSIW6}
    property Cursor: TIWCursor read FCursor write FCursor default crAuto;
    {$ENDIF}
    property DataButtonType: TTIWDataButtonType read FDataButtonType write
      FDataButtonType default dbtButton;
    property DefaultDynEdit: string read FDefaultDynEdit write FDefaultDynEdit;
    property DefaultDynText: string read FDefaultDynText write FDefaultDynText;
    property DetailColor: TIWColor read FDetailColor write FDetailColor default clNone;
    property DetailFont: TIWFont read FDetailFont write SetDetailFont;    
    property DetailTemplate: string read FDetailTemplate write FDetailTemplate;
    property DetailSpan: Integer read FDetailSpan write FDetailSpan default 0;
    property DynPrecision: Integer read FDynPrecision write FDynPrecision default 0;
    property DynEditor: TTIWDynEditType read FDynEditor write FDynEditor default deText;
    property Hint: string read FHint write FHint;
    property ImageIndex: Integer read FImageIndex write SetImageIndex default -1;
    property Editor: TTIWColumnEditor read FEditor write FEditor default edNone;
    property Enabled: Boolean read FEnabled write FEnabled default true;
    property Filter: Boolean read FFilter write FFilter default false;
    property FilterIndex: Integer read FFilterIndex write FFilterIndex default 0;
    property FilterList: TStringList read FFilterList write SetFilterList;
    property Font: TIWFont read FFont write SetFont;
    property FooterAlignment: TAlignment read FFooterAlignment write SetFooterAlignment
      default taLeftJustify;
    property FooterFormat: string read FFooterFormat write SetFooterFormat;
    property FooterGradient1: TIWColor read FFooterGradient1 write FFooterGradient1
      default clNone;
    property FooterGradient2: TIWColor read FFooterGradient2 write FFooterGradient2
      default clNone;
    property FooterText: string read FFooterText write SetFooterText;
    property FooterType: TTIWFooterType read FFooterType write SetFooterType
      default ftText;
    property Formula: string read FFormula write FFormula;
    property MaxLength: Integer read FMaxLength write FMaxLength default 0;
    property Name: string read FName write FName;
    property PopupColor: TIWColor read FPopupColor write FPopupColor default clWebWHITE;
    property PopupColorTo: TIWColor read FPopupColorTo write FPopupColorTo default clNone;       
    property PopupColorGradientDirection: TTIWGradientDirection read
    FPopupColorGradientDirection write FPopupColorGradientDirection default gdHorizontal;
    property ImageHeight: Integer read FImageHeight write FImageHeight default 0;
    property ImageWidth: Integer read FImageWidth write FImageWidth default 0;
    property PopupHeight: Integer read FPopupHeight write FPopupHeight default 200;
    property PopupWidth: Integer read FPopupWidth write FPopupWidth default 200;
    property ProgressColor: TIWColor read FProgressColor write FProgressColor default clWebRED;
    property RequiredMsg: string read FRequiredMsg write FRequiredMsg;
    property ShowHint: Boolean read FShowHint write FShowHint default false;
    property SpinEditMaxValue: Integer read FSpinEditMaxValue write FSpinEditMaxValue default 0;
    property SpinEditMinValue: Integer read FSpinEditMinValue write FSpinEditMinValue default 100;
    property SpinEditAutoSpin: Boolean read FSpinEditAutoSpin write FSpinEditAutoSpin default True;     
    property SubTitle: string read FSubTitle write SetSubTitle;
    property SubTitleSpan: Integer read FSubTitleSpan write SetSubTitleSpan default 0;
    property SubTitleVAlign: TTIWVAlign read FSubTitleVAlign write FSubTitleVAlign default vaNone;
    property Template: string read FTemplate write SetTemplate;
    property Tag: Integer read FTag write FTag default 0;
    property Title: string read FTitle write SetTitle;
    property TitleRowSpan: Boolean read FTitleRowSpan write SetTitleRowSpan default false;
    property TitleSpan: Integer read FTitleSpan write SetTitleSpan default 0;
    property TitleVAlign: TTIWValign read FTitleVAlign write FTitleVAlign default vaNone;
    property VAlign: TTIWVAlign read FVAlign write FVAlign default vaNone;
    property Visible: Boolean read FVisible write SetVisible default true;
    property Width: integer read FWidth write SetWidth default 128;
    property WidthType: TTIWWidthType read FWidthType write SetWidthType default wtAbsolute;
  end;

  TTIWWebGridColumns = class(TCollection)
  private
    FOwner: TTIWCustomWebGrid;
    function GetItem(Index: Integer): TTIWWebGridColumn;
    procedure SetItem(Index: Integer; const Value: TTIWWebGridColumn);
  public
    function GetItemClass: TCollectionItemClass; virtual;
    function Add: TTIWWebGridColumn;
    procedure Update(Item: TCollectionItem); override;
    function Insert(index: Integer): TTIWWebGridColumn;
    property Items[Index: Integer]: TTIWWebGridColumn read GetItem write
    SetItem; default;
    constructor Create(AOwner: TTIWCustomWebGrid);
    function GetOwner: TPersistent; override;
    property Grid: TTIWCustomWebGrid read FOwner;
  end;

  TControllerPosition = (cpTop, cpBottom, cpNone, cpBoth);

  TControllerPager = (cpPrevNext, cpPageList, cpAlphaList, cpPrevNextFirstLast, cpDropDownList);

  TControllerPagerType = (cptLink, cptButton, cptImage, cptImageButton, ctpNone);

  TControllerIndicatorType = (itNone, itRecordNr, itPageNr, itRecordFromTo);

  TTIWAdvWebGridController = class(TPersistent)
  private
    FPosition: TControllerPosition;
    FControllerPager: TControllerPager;
    FTextNext: string;
    FTextPrev: string;
    FAlignment: TAlignment;
    FControllerBorders: TTIWRGBorders;
    FFont: TIWFont;
    FHeight: Integer;
    FColor: TIWColor;
    FTextLast: string;
    FTextFirst: string;
    FIndicatorFormat: string;
    FIndicatorType: TControllerIndicatorType;
    FGradient1: TIWColor;
    FGradient2: TIWColor;
    FPageType: TControllerPagerType;
    FCaption: string;
    FImgPrev: TIPicture;
    FImgPrevURL: string;
    FImgNext: TIPicture;
    FImgNextURL: string;
    FImgLast: TIPicture;
    FImgLastURL: string;
    FImgFirst: TIPicture;
    FImgFirstURL: string;
    FGradientDirection: TTIWGradientDirection;
    FMaxPages: Integer;
    FHintFirst: string;
    FHintPrev: string;
    FHintNext: string;
    FHintLast: string;
    FShowPagersAlways: Boolean;
    FOnChange: TNotifyEvent;
    FRowCountSelect: Boolean;
    FRowCountValues: TStringList;
    FShowFind: Boolean;
    FHintFind: string;
    FRowCountSelectLabelBefore: string;
    FRowCountSelectLabelAfter: string;
    procedure SetPosition(const Value: TControllerPosition);
    procedure SetControllerPager(const Value: TControllerPager);
    procedure SetTextNext(const Value: string);
    procedure SetTextPrev(const Value: string);
    procedure SetAlignment(const Value: TAlignment);
    procedure SetFont(const Value: TIWFont);
    procedure SeTIWColor(const Value: TIWColor);
    procedure SetHeight(const Value: Integer);
    procedure SetTextFirst(const Value: string);
    procedure SetTextLast(const Value: string);
    procedure SetIndicatorFormat(const Value: string);
    procedure SetIndicatorType(const Value: TControllerIndicatorType);
    procedure SetPagerType(const Value: TControllerPagerType);
    procedure SetCaption(const Value: string);
    procedure SetImgFirst(const Value: TIPicture);
    procedure SetImgLast(const Value: TIPicture);
    procedure SetImgNext(const Value: TIPicture);
    procedure SetImgPrev(const Value: TIPicture);
    procedure SetRowCountValues(const Value: TStringList);
  protected
  public
    constructor Create;
    destructor Destroy; override;
    procedure Changed;
  published
    property Alignment: TAlignment read FAlignment write SetAlignment;
    property Borders: TTIWRGBorders read FControllerBorders write FControllerBorders;
    property Caption: string read FCaption write SetCaption;
    property Color: TIWColor read FColor write SeTIWColor;
    property Font: TIWFont read FFont write SetFont;
    property Gradient1: TIWColor read FGradient1 write FGradient1;
    property Gradient2: TIWColor read FGradient2 write FGradient2;
    property GradientDirection: TTIWGradientDirection read FGradientDirection
      write FGradientDirection;
    property Height: Integer read FHeight write SetHeight;
    property MaxPages: Integer read FMaxPages write FMaxPages;
    property Position: TControllerPosition read FPosition write SetPosition;
    property Pager: TControllerPager read FControllerPager write
      SetControllerPager;
    property PagerType: TControllerPagerType read FPageType write SetPagerType;

    property IndicatorFormat: string read FIndicatorFormat write
      SetIndicatorFormat;
    property IndicatorType: TControllerIndicatorType read FIndicatorType write
      SetIndicatorType;

    property TextPrev: string read FTextPrev write SetTextPrev;
    property TextNext: string read FTextNext write SetTextNext;
    property TextFirst: string read FTextFirst write SetTextFirst;
    property TextLast: string read FTextLast write SetTextLast;

    property ImgPrev: TIPicture read FImgPrev write SetImgPrev;
    property ImgNext: TIPicture read FImgNext write SetImgNext;
    property ImgFirst: TIPicture read FImgFirst write SetImgFirst;
    property ImgLast: TIPicture read FImgLast write SetImgLast;

    property ImgPrevURL: string read FImgPrevURL write FImgPrevURL;
    property ImgNextURL: string read FImgNextURL write FImgNextURL;
    property ImgFirstURL: string read FImgFirstURL write FImgFirstURL;
    property ImgLastURL: string read FImgLastURL write FImgLastURL;

    property HintPrev: string read FHintPrev write FHintPrev;
    property HintNext: string read FHintNext write FHintNext;
    property HintFirst: string read FHintFirst write FHintFirst;
    property HintLast: string read FHintLast write FHintLast;

    property RowCountSelect: Boolean read FRowCountSelect write FRowCountSelect;
    property RowCountSelectLabelBefore: string read FRowCountSelectLabelBefore write FRowCountSelectLabelBefore;
    property RowCountSelectLabelAfter: string read FRowCountSelectLabelAfter write FRowCountSelectLabelAfter;
    property RowCountValues: TStringList read FRowCountValues write SetRowCountValues;

    property ShowFind: Boolean read FShowFind write FShowFind default False;
    property HintFind: string read FHintFind write FHintFind;

    property ShowPagersAlways: Boolean read FShowPagersAlways write FShowPagersAlways;

    property OnChange: TNotifyEvent read FOnChange write FOnChange;
  end;

  TTIWAdvWebGridBands = class(TPersistent)
  private
    FOwner: TTIWCustomWebGrid;
    FActive: Boolean;
    FPrimaryColor: TIWColor;
    FSecondaryColor: TIWColor;
    procedure SetActive(const Value: Boolean);
    procedure SetPrimaryColor(const Value: TIWColor);
    procedure SetSecondaryColor(const Value: TIWColor);
  protected
  public
    constructor Create(AOwner: TTIWCustomWebGrid);
  published
    property Active: Boolean read FActive write SetActive;
    property PrimaryColor: TIWColor read FPrimaryColor write SetPrimaryColor;
    property SecondaryColor: TIWColor read FSecondaryColor write
      SetSecondaryColor;
  end;


  TTIWRGIndicators = class(TPersistent)
  private
    FOwner: TTIWCustomWebGrid;
    FInsert: TBitmap;
    FInsertURL: string;
    FEdit: TBitmap;
    FEditURL: string;
    FBrowse: TBitmap;
    FBrowseURL: string;
    procedure SetBrowse(const Value: TBitmap);
    procedure SetEdit(const Value: TBitmap);
    procedure SetInsert(const Value: TBitmap);
  public
    constructor Create(AOwner: TTIWCustomWebGrid);
    destructor Destroy; override;
  published
    property Browse: TBitmap read FBrowse write SetBrowse;
    property BrowseURL: string read FBrowseURL write FBrowseURL;
    property Insert: TBitmap read FInsert write SetInsert;
    property InsertURL: string read FInsertURL write FInsertURL;
    property Edit: TBitmap read FEdit write SetEdit;
    property EditURL: string read FEditURL write FEditURL;
  end;

  TSortDirection = (sdAscending, sdDescending);

  TTIWRGSortSettings = class(TPersistent)
  private
    FOwner: TTIWCustomWebGrid;
    FShow: Boolean;
    FColumn: Integer;
    FAscending: TBitmap;
    FAscendingURL: string;
    FDescending: TBitmap;
    FDescendingURL: string;
    FDirection: TSortDirection;
    FInitSortDir: TSortDirection;
    procedure SetAscending(const Value: TBitmap);
    procedure SetColumn(const Value: Integer);
    procedure SetDescending(const Value: TBitmap);
    procedure SetDirection(const Value: TSortDirection);
    procedure SetShow(const Value: Boolean);
  public
    constructor Create(AOwner: TTIWCustomWebGrid);
    destructor Destroy; override;
  published
    property Show: Boolean read FShow write SetShow;
    property Column: Integer read FColumn write SetColumn;
    property Direction: TSortDirection read FDirection write SetDirection;
    property Ascending: TBitmap read FAscending write SetAscending;
    property AscendingURL: string read FAscendingURL write FAscendingURL;
    property Descending: TBitmap read FDescending write SetDescending;
    property DescendingURL: string read FDescendingURL write FDescendingURL;
    property InitSortDir: TSortDirection read FInitSortDir write FInitSortDir;
  end;

  TTIWRGGlyphs = class(TPersistent)
  private
    FOwner: TTIWCustomWebGrid;
    FCancelButton: TBitmap;
    FCancelButtonURL: string;
    FPostButton: TBitmap;
    FPostButtonURL: string;
    FEditButton: TBitmap;
    FEditButtonURL: string;
    FEditHint: string;
    FPostHint: string;
    FCancelHint: string;
    FDropDownImage: TBitmap;
    FDropDownImageURL: string;
    FSpinEditButtonDownImage: TIPicture;
    FSpinEditButtonDownImageURL: string;
    FSpinEditButtonUpImage: TIPicture;
    FSpinEditButtonUpImageURL: string;
    procedure SetCancelButton(const Value: TBitmap);
    procedure SetEditButton(const Value: TBitmap);
    procedure SetPostButton(const Value: TBitmap);
    procedure SetDropDownImage(const Value: TBitmap);
    procedure SetSpinEditButtonDownImage(const Value: TIPicture);
    procedure SetSpinEditButtonUpImage(const Value: TIPicture);
  public
    constructor Create(AOwner: TTIWCustomWebGrid);
    destructor Destroy; override;
  published
    property EditButton: TBitmap read FEditButton write SetEditButton;
    property EditButtonURL: string read FEditButtonURL write FEditButtonURL;
    property EditHint: string read FEditHint write FEditHint;
    property PostButton: TBitmap read FPostButton write SetPostButton;
    property PostButtonURL: string read FPostButtonURL write FPostButtonURL;
    property PostHint: string read FPostHint write FPostHint;
    property CancelButton: TBitmap read FCancelButton write SetCancelButton;
    property CancelButtonURL: string read FCancelButtonURL write FCancelButtonURL;
    property CancelHint: string read FCancelHint write FCancelHint;
    property DropDownImage: TBitmap read FDropDownImage write SetDropDownImage;
    property DropDownImageURL: string read FDropDownImageURL write FDropDownImageURL;
    property SpinEditButtonDownImage: TIPicture read FSpinEditButtonDownImage write SetSpinEditButtonDownImage;
    property SpinEditButtonDownImageURL: string read FSpinEditButtonDownImageURL write FSpinEditButtonDownImageURL;
    property SpinEditButtonUpImage: TIPicture read FSpinEditButtonUpImage write SetSpinEditButtonUpImage;
    property SpinEditButtonUpImageURL: string read FSpinEditButtonUpImageURL write FSpinEditButtonUpImageURL;
  end;

  TIntList = class(TList)
  private
    FOnChange: TNotifyEvent;
    procedure SetInteger(Index: Integer; Value: Integer);
    function GetInteger(Index: Integer): Integer;
    function GetStrValue: string;
    procedure SetStrValue(const Value: string);
  public
    constructor Create;
    property Items[index: Integer]: Integer read GetInteger write SetInteger;
    default;
    procedure Add(Value: Integer);
    procedure Delete(Index: Integer);
    property StrValue: string read GetStrValue write SetStrValue;
    property OnChange: TNotifyEvent read FOnChange write FOnChange;
  end;

  TIWGridNode = class(TPersistent)
  private
    FOwner: TTIWCustomWebGrid;
    FHintClosed: string;
    FHintOpen: string;
    FNodeOpen: TIPicture;
    FNodeOpenURL: string;
    FNodeClosed: TIPicture;
    FNodeClosedURL: string;
    procedure SetNodeClosed(const Value: TIPicture);
    procedure SetNodeOpen(const Value: TIPicture);
  public
    constructor Create(AOwner: TTIWCustomWebGrid);
    destructor Destroy; override;
    procedure Assign(Source: TPersistent); override;
  published
    property NodeOpen: TIPicture read FNodeOpen write SetNodeOpen;
    property NodeOpenURL: string read FNodeOpenURL write FNodeOpenURL;
    property NodeClosed: TIPicture read FNodeClosed write SetNodeClosed;
    property NodeClosedURL: string read FNodeClosedURL write FNodeClosedURL;
    property HintOpen: string read FHintOpen write FHintOpen;
    property HintClosed: string read FHintClosed write FHintClosed;
  end;

  TIWGridBackground = class(TPersistent)
  private
    FGradient1: TIWColor;
    FGradient2: TIWColor;
    FPicture: TIPicture;
    FPictureURL: string;
    FGradientDirection: TTIWGradientDirection;
    procedure SetPicture(const Value: TIPicture);
  public
    constructor Create;
    destructor Destroy; override;
    procedure Assign(Source: TPersistent); override;
  published
    property GradientDirection: TTIWGradientDirection read FGradientDirection
      write FGradientDirection;
    property Gradient1: TIWColor read FGradient1 write FGradient1;
    property Gradient2: TIWColor read FGradient2 write FGradient2;
    property Picture: TIPicture read FPicture write SetPicture;
    property PictureURL: string read FPictureURL write FPictureURL;
  end;

  TIWGridClientEvents = class(TPersistent)
  private
    FButtonClick: TStringList;
    FImageClick: TStringList;
    FEditChange: TStringList;
    FEditDone: TStringList;
    FCellClick: TStringList;
    FCheckClick: TStringList;
    FComboChange: TStringList;
    FDynEditDone: TStringList;
    FDynEditChange: TStringList;
    FNodeClick: TStringList;
    FDynComboChange: TStringList;
    FDynCheckClick: TStringList;
    FGridKeyDown: TStringList;
    FPopupEditOk: TStringList;
    FPopupEditCancel: TStringList;
    FHoverRow: TStringList;
    procedure SetButtonClick(const Value: TStringList);
    procedure SetImageClick(const Value: TStringList);
    procedure SetEditChange(const Value: TStringList);
    procedure SetEditDone(const Value: TStringList);
    procedure SetCellClick(const Value: TStringList);
    procedure SetCheckClick(const Value: TStringList);
    procedure SetComboChange(const Value: TStringList);
    procedure SetDynEditChange(const Value: TStringList);
    procedure SetDynEditDone(const Value: TStringList);
    procedure SetNodeClick(const Value: TStringList);
    procedure SetDynComboChange(const Value: TStringList);
    procedure SetDynCheckClick(const Value: TStringList);
    procedure SetGridKeyDown(const Value: TStringList);
    procedure SetPopupEditOk(const Value: TStringList);
    procedure SetPopupEditCancel(const Value: TStringList);
    procedure SetHoverRow(const Value: TStringList);
  public
    constructor Create;
    destructor Destroy; override;
    procedure Assign(Source: TPersistent); override;
    function GetJSFunction(PropName: string): string;
  published
    property ButtonClick: TStringList read FButtonClick write SetButtonClick;
    property CellClick: TStringList read FCellClick write SetCellClick;
    property CheckClick: TStringList read FCheckClick write SetCheckClick;
    property EditChange: TStringList read FEditChange write SetEditChange;
    property EditDone: TStringList read FEditDone write SetEditDone;
    property ImageClick: TStringList read FImageClick write SetImageClick;
    property ComboChange: TStringList read FComboChange write SetComboChange;
    property DynCheckClick: TStringList read FDynCheckClick write SetDynCheckClick;
    property DynComboChange: TStringList read FDynComboChange write SetDynComboChange;
    property DynEditChange: TStringList read FDynEditChange write SetDynEditChange;
    property DynEditDone: TStringList read FDynEditDone write SetDynEditDone;
    property NodeClick: TStringList read FNodeClick write SetNodeClick;
    property GridKeyDown: TStringList read FGridKeyDown write SetGridKeyDown;
    property PopupEditOk: TStringList read FPopupEditOk write SetPopupEditOk;
    property PopupEditCancel: TStringList read FPopupEditCancel write SetPopupEditCancel;
    property HoverRow: TStringList read FHoverRow write SetHoverRow;
  end;

  TTIWCustomWebGrid = class(TIWControl)
  private
    FRowOffset: Integer;
    FPageOffset: Integer;
    FPrevPageOffset: Integer;
    FNumRows: Integer;
    FRowCount: Integer;
    FColumns: TTIWWebGridColumns;
    FController: TTIWAdvWebGridController;
    FShowColumnHeader: Boolean;
    FColumnHeaderColor: TIWColor;
    FOnColumnHeaderClick: TIWRGColumnHeaderClick;
    FPage: Integer;
    FOnButtonClick: TIWRGButtonClick;
    FOnLinkClick: TIWRGButtonClick;
    FOnComboChange: TIWComboChangeEvent;
    FSelectColor: TIWColor;
    FHoverColor: TIWColor;
    FHoverFontColor: TIWColor;
    FSelectFontColor: TIWColor;
    FHeaderStyle: TTIWHeaderStyle;
    FOnGetCellData: TIWRGCellDataEvent;
    FOnGetCellEditorEnabled: TIWRGCellEditorEnabled;
    FOnGetCellType: TIWRGCellType;    
    FOnGetURLText: TIWRGCellDataEvent;
    FOnGetCellProp: TIWRGCellPropEvent;
    FDefaultRowHeight: Integer;
    FColumnHeaderFont: TIWFont;
    FColumnHeaderBorders: TTIWRGBorders;
    FBands: TTIWAdvWebGridBands;
    FOnCheckClick: TIWRGButtonClick;
    FOnGetCellHint: TIWRGCellDataEvent;
    FOnGetRowHeaderText: TIWRowHeaderTextEvent;
    FDecimalPoint: char;
    FIndicators: TTIWRGIndicators;
    FAdvanceOnReturn: Boolean;
    FBorders: TTIWRGBorders;
    FColumnSizing: Boolean;
    FSortSettings: TTIWRGSortSettings;
    FShowFooter: Boolean;
    FFooterBorders: TTIWRGBorders;
    FFooterColor: TIWColor;
    FFooterFont: TIWFont;
    FImages: TImageList;
    FOnGetImageIdx: TTIWRGImageIndexEvent;
    FOnImageClick: TIWRGButtonClick;
    FAutoEdit: Boolean;
    FMouseSelect: TTIWMouseSelect;
    FEditColor: TIWColor;
    FOnPrevPage: TNotifyEvent;
    FOnFirstPage: TNotifyEvent;
    FOnNextPage: TNotifyEvent;
    FOnLastPage: TNotifyEvent;
    FOnGotoPage: TTIWPageEvent;
    FGlyphs: TTIWRGGlyphs;
    FOnGotoRow: TTIWRowEvent;
    FOnRowCountChange: TIWRowCountEvent;
    FRadioSelection: Integer;
    FScrollPos: Integer;
    FScrollLeft: Integer;
    FSelectList: TIntList;
    FSelectPersistent: Boolean;
    FStretchColumn: Integer;
    FDynEdits: TStringList;
    FOnFilterSelect: TTIWFilterEvent;
    FOnGetDynText: TTIWGetDynText;
    FOnCellClick: TIWRGButtonClick;
    FisIE: boolean;
    {$IFDEF TMSIW9}
    FAsyncActiveRowMove: Boolean;
    FAsyncEdit: Boolean;
    FAsyncPaging: Boolean;
    FAsyncSorting: Boolean;
    FOnAsyncButtonClick: TIWAsyncButtonEvent;
    FOnAsyncCellClick: TIWAsyncButtonEvent;
    FOnAsyncCheckClick: TIWAsyncButtonEvent;
    FOnAsyncColumnHeaderClick: TIWAsyncColumnEvent;
    FOnAsyncComboChange: TIWAsyncComboChangeEvent;
    FOnAsyncEditDone: TIWAsyncEditDoneEvent;
    FOnAsyncValidate: TIWAsyncValidateEvent;
    FOnAsyncGotoRow: TIWAsyncRowEvent;
    FOnAsyncImageClick: TIWAsyncButtonEvent;
    FOnAsyncLinkClick: TIWAsyncButtonEvent;
    FOnAsyncPost: TIWAsyncEvent;
    FOnAsyncEdit: TIWAsyncEvent;
    FOnAsyncCancel: TIWAsyncEvent;
    FOnAsyncNextPage: TIWAsyncEvent;
    FOnAsyncPrevPage: TIWAsyncEvent;
    FOnAsyncFirstPage: TIWAsyncEvent;
    FOnAsyncLastPage: TIWAsyncEvent;
    FOnAsyncGotoPage: TIWAsyncPageEvent;
    FOnAsyncPostValidate: TIWAsyncPostValidateEvent;
    FOnAsyncRowSelect: TIWAsyncRowSelectEvent;
    FCellCol: integer;
    FCellRow: integer;
    FChecked: boolean;
    FCellValue: string;
    FAsyncDoCancel: boolean;
    FAsyncDoEdit: boolean;
    FAsyncDoPost: boolean;
    FAsyncDoPostInvalid: boolean;
    FAsyncInvalidPostMessage: string;
    FAsyncInvalidPostEditMode: boolean;
    FAsyncSetCell: string;
    FAsyncSetCtrl: string;    
    FAsyncSetEditMode: integer;
    {$ENDIF}
    FID: Integer;
    FIDS: string;
    FEditID: Integer;
    FEditRow: Integer;
    FEditRowIndicator: Integer;
    FDateSeparator: char;
    FDateFormat: TTIWGridDateFormat;
    FActiveRowColor: TIWColor;
    FOnBeforeGotoLink: TTIWBeforeLinkEvent;
    FOnAfterGotoLink: TTIWAfterLinkEvent;
    FOnGetCellDetail: TIWRGCellDataEvent;
    FActiveRowFontColor: TIWColor;
    FCache: TStringList;
    FActiveColumn: Integer;
    FEditSelectAll: Boolean;
    FCheckTruePicture: TIPicture;
    FCheckTruePictureURL: string;
    FCheckFalsePicture: TIPicture;
    FCheckFalsePictureURL: string;
    FShowSelect: Boolean;
    FDetailHeight: Integer;
    FDetailRowShow: TTIWDetailRowShow;
    FNodes: TIWGridNode;
    FBackground: TIWGridBackground;
    FOnGetCellPopupText: TIWRGCellDataEvent;
    FClientEvents: TIWGridClientEvents;
    FOnNodeOpen: TTIWRowEvent;
    FOnNodeClose: TTIWRowEvent;
    FOnNodeShow: TTIWNodeShowEvent;
    FOnValueClick: TIWRGCellValueEvent;
    FScroll: TTIWWebGridScroll;
    FRowHeader: TTIWWebGridRowHeader;
    FOuterBorder: TTIWWebGridOuterBorder;
    FDetailGrid: TTIWCustomWebGrid;
    FNumDetails: Integer;
    FDetailStates: TIntList;
    dState: TTIWGridState;
    FIsDetail: Boolean;
    FAutoHTMLAdapt: Boolean;
    FOnGetDetailGrid: TIWRGDetailGridEvent;
    FOnSetCellData: TIWRGCellDataEvent;
    FOnCanEditCell: TTIWCellAllowEvent;
    FOnPost: TNotifyEvent;
    FOnCancel: TNotifyEvent;
    FOnEdit: TNotifyEvent;
    FOnPostValidate: TTIWPostValidateEvent;
    FOnDirectEditUpdate: TTIWDirectEditUpdate;
    FPostData: TStringList;
    FDirectPost: Boolean;
    FUseFullHeight: Boolean;
    FUseFullWidth: Boolean;
    FFullHeight: Integer;
    FNameOfMonths: TStringList;
    FNameOfDays: TStringList;
    procedure SetRowCount(const Value: Integer);
    procedure SetColumns(const Value: TTIWWebGridColumns);
    procedure SetController(const Value: TTIWAdvWebGridController);
    procedure SetShowColumnHeader(const Value: Boolean);
    procedure SetColumnHeaderColor(const Value: TIWColor);
    procedure SetPage(const Value: Integer);
    function GetPage: Integer;
    procedure SetHoverColor(const Value: TIWColor);
    procedure SetHoverFontColor(const Value: TIWColor);
    procedure SetSelectColor(const Value: TIWColor);
    procedure SetSelectFontColor(const Value: TIWColor);
    procedure SetDefaultRowHeight(const Value: Integer);
    procedure SetColumnHeaderFont(const Value: TIWFont);
    procedure SetBands(const Value: TTIWAdvWebGridBands);
    function GetRowSelect(r: Integer): Boolean;
    procedure SetIndicators(const Value: TTIWRGIndicators);
    procedure SetBorders(const Value: TTIWRGBorders);
    procedure SetColumnSizing(const Value: Boolean);
    procedure SetSortSettings(const Value: TTIWRGSortSettings);
    procedure SetFooterColor(const Value: TIWColor);
    procedure SetFooterFont(const Value: TIWFont);
    procedure SetShowFooter(const Value: Boolean);
    procedure SetGlyphs(const Value: TTIWRGGlyphs);
    procedure SetRowSelect(r: Integer; const Value: Boolean);
    function GetDynEdits(col, row: Integer): string;
    procedure SetDynEdits(col, row: Integer; const Value: string);
    function HasSubTitles: Boolean;
    function HasDetail: Boolean;
    procedure SetID(const Value: Integer);
    procedure SetCheckFalsePicture(const Value: TIPicture);
    procedure SetCheckTruePicture(const Value: TIPicture);
    procedure SetNodes(const Value: TIWGridNode);
    procedure SetBackground(const Value: TIWGridBackground);
    procedure SetClientEvents(const Value: TIWGridClientEvents);
    procedure SetScroll(const Value: TTIWWebGridScroll);
    function GetDetailStates(Row: Integer): Boolean;
    procedure SetDetailStates(Row: Integer; const Value: Boolean);
    function FontToTag(Font: TIWFont; s: string): string;
    function FontInsert(Font: TIWFont): string;
    function FontUsed(Font: TIWFont): Boolean;
    function GetActiveDetailRow: Integer;
    procedure SetActiveDetailRow(const Value: Integer);
    procedure SetRadioSelection(const Value: Integer);
    function GradientStyle(Color1,Color2: TIWColor; Direction: TTIWGradientDirection):string;
    function CellColor(Color,Color1,Color2: TIWColor; Direction: TTIWGradientDirection):string;
    procedure SetNameOfDays(const Value: TStringList);
    procedure SetNameOfMonths(const Value: TStringList);
    procedure SetRowOffsetTemp(const Value: Integer);
    procedure InitMonths;
    procedure InitDays;
    {$IFDEF TMSIW7}
    function RaisedStyle(AContext: TIWBaseComponentContext): string;
    {$ELSE}
    function RaisedStyle: string;
    {$ENDIF}
  protected
    ic: TIWHTMLPictureCache;
    function ImageHTML(const ASrc: string; AWidth, AHeight: Integer; UseSize:
      Boolean; Hint: string): TIWHTMLTag;
    function OutputBMP(ACacheName: string; ABitmap: TBitmap; UseSize: Boolean;
      Hint: string): string;
    function OutputBMPEx(ACacheName: string; ABitmap: TBitmap; UseSize: Boolean;
      Hint: string; Height, Width: Integer): string;
    function OutputBMPFileName(ACacheName: string; ABitmap: TBitmap): string;
    function OutputPIC(ACacheName: string; APicture: TIPicture; UseSize:
      Boolean; Hint: string): string;
    procedure SetRowOffset(AValue: Integer);
    {$IFDEF TMSIW6}
    procedure IWPaint; override;
    {$ELSE}
    procedure Paint; override;
    {$ENDIF}
    procedure ClearCells; virtual;    
    procedure DeleteSelection(i: Integer);
    procedure DeleteRows(RowIndex,RowCount: Integer); virtual;
    procedure InsertRows(RowIndex,RowCount: Integer); virtual;
    procedure UpdateRowCount(const Value: Integer); virtual;
    procedure UpdateTotalRows(const Value: Integer); virtual;
    function GetCellData(ACol, ARow: Integer): string; virtual;
    procedure SetCellData(ACol, ARow: Integer; Value: string;postalways:boolean=false); virtual;
    function GetCellImage(ACol,ARow: Integer): TPicture; virtual;
    function GetURLText(ACol, ARow: Integer; AValue: string): string; virtual;
    function GetCellDetail(ACol, ARow: Integer): string; virtual;
    function GetDetailGrid(ARow: Integer): TTIWCustomWebGrid; virtual;
    function GetLookupValue(ACol: Integer; ACellValue: string): string; virtual;
    function GetLookupValues(ACol: Integer; ACellValue: string): string; virtual;
    function GetColumnTitle(ACol: Integer): string; virtual;
    function GetGridState: TTIWGridState; virtual;
    procedure GetRowInfo(var NumRows, RowOffset, PageOffset: Integer); virtual;
    function GetCurrentRecord: integer; virtual;
    procedure SaveBookmark; virtual;
    procedure RestoreBookmark; virtual;
    function IsValidRow(ARow: integer): boolean; virtual;
    procedure RenderPrepareDetail(AGrid: TTIWCustomWebGrid); virtual;
    function RenderPrepare: Boolean; virtual;
    procedure RenderDone; virtual;
    procedure DoEdit; virtual;
    procedure DoCancel; virtual;
    function DoPost(postalways:boolean=false): Boolean; virtual;
    procedure DoInsert; virtual;
    procedure DoNodeOpen(ARow: Integer); virtual;
    procedure DoNodeClose(ARow: Integer); virtual;
    procedure GotoRecord(RecordIndex: Integer); virtual;
    function NextRecord: boolean; virtual;
    function IsDBAware: boolean; virtual;
    function DirectEditUpdate(ACol,ARow: Integer;var Value: string): Boolean; virtual;
    procedure Submit(const AValue: string); override;
    procedure SetValue(const AValue: string); override;
    function HTMLClr(AColor: TIWColor): string;
    procedure GetCellProp(RowIndex, ColumnIndex: Integer; AValue: string;
      var AColor: TIWColor; var AAlignment: TAlignment; AFont: TIWFont); virtual;
    procedure Notification(AComponent: TComponent; AOperation: TOperation); override;
    function DateStrToDate(AValue: string): TDateTime;
    function DateToDateStr(AValue: TDateTime): string;
    function RenderCalendar(Name: string; Width: Integer; AFontName: string;
      AFontSize: Integer; blurevent, cellvalue: string; AColor: TIWColor): string;
    function RenderSpin(Name: string; MaxLength, Width: Integer; Alignment: TAlignment;
      AFontStyle: string; CellValue: string; AColor: TIWColor;
      MaxValue: Integer; MinValue: Integer; AutoSpin: Boolean;
      blurevent: string; isIE: bool): string;
    function SubmitCall(Param: string): string;
    function GetTableWidth(inner: Boolean): Integer;
    function GetVisibleCols: Integer;
    function GetController(isIe, isAsync, isTop: boolean): string;
    function GetScrollBarStyle(Scroll: TTIWWebGridScroll): string;
    function GetRowHeader(NumRows,GridHeight: Integer;HeaderRaisedStyle: string): string;
    procedure ControllerChanged(Sender: TObject);
    {$IFDEF TMSIW6}
    function RenderString(Master: Boolean; AContext: TIWBaseComponentContext): string;
    {$ELSE}
    function RenderString(Master: Boolean): string;
    {$ENDIF}
    property IDS: string read FIDS;
    property IsDetail: Boolean read FIsDetail write FIsDetail;
    property IDDetail: Integer read FEditID;
    property PostValues: TStringList read FPostData;
    function HasDynEdits: Boolean;
    function HasPercCols: Boolean;
    function HasColSpans: Boolean;
    property DirectPost: Boolean read FDirectPost write FDirectPost;
    property FullHeight: Integer read FFullHeight write FFullHeight;
    property NumDetails: Integer read FNumDetails write FNumDetails;
    {$IFDEF TMSIW72_NEW}
    function get_ShouldRenderTabOrder: Boolean; override;
    {$ENDIF}
    {$IFDEF TMSIW9}
    procedure DoAsyncCellClick(AParams: TStringList);
    procedure DoAsyncButtonClick(AParams: TStringList);
    procedure DoAsyncCheckClick(AParams: TStringList);
    procedure DoAsyncRowSelect(AParams: TStringList);
    procedure DoAsyncGotoRow(AParams: TStringList);    
    procedure DoAsyncImageClick(AParams: TStringList);
    procedure DoAsyncLinkClick(AParams: TStringList);
    procedure DoAsyncComboChange(AParams: TStringList);
    procedure DoAsyncEditDone(AParams: TStringList);
    procedure DoAsyncPost(AParams: TStringList);
    procedure DoAsyncEdit(AParams: TStringList);
    procedure DoAsyncCancel(AParams: TStringList);
    procedure DoAsyncNextPage(AParams: TStringList);
    procedure DoAsyncPrevPage(AParams: TStringList);
    procedure DoAsyncFirstPage(AParams: TStringList);
    procedure DoAsyncLastPage(AParams: TStringList);
    procedure DoAsyncGotoPage(AParams: TStringList);
    procedure DoAsyncColumnHeaderClick(AParams: TStringList);
    {$ENDIF}
  public
    {$IFDEF TMSIW72}
    function get_HasTabOrder: boolean; override;
    {$ENDIF}
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    {$IFDEF TMSIW6}
    function RenderHTML(AContext: TIWBaseComponentContext): TIWHTMLTag; override;
    {$ELSE}
    function RenderHTML: TIWHTMLTag; override;
    {$ENDIF}
    {$IFDEF TMSIW9}
    function RenderAsync(AContext: TIWBaseHTMLComponentContext): TIWXMLTag; override;
    procedure AsyncClearRowSelect;
    procedure AsyncSetCell(Col: Integer; Row: Integer; Value: string);
    procedure AsyncRowSelect(Row: Integer; Selected: Boolean);
    procedure AsyncSetEditMode(Row: Integer);
    function AsyncDoPost(): boolean;
    procedure AsyncDoCancel();
    procedure AsyncUpdateRowCheck();    
    {$ENDIF}
    function HTMLAdapt(Value: string): string; virtual;
    function HTMLAdaptInv(Value: string): string; virtual;
    procedure SetBounds(ALeft,ATop,AWidth,AHeight: Integer); override;
    procedure ClearRowSelect;
    procedure ClearImageCache;
    procedure ClearDynEdits;
    procedure ClearDetailStates;
    procedure Edit; virtual;
    procedure ColumnHeaderClick(AColumn: Integer); virtual;
    function CreateColumns: TTIWWebGridColumns; virtual;
    property RowSelect[r: Integer]: Boolean read GetRowSelect write SetRowSelect;
    property RowOffset: Integer read FRowOffset write SetRowOffsetTemp;
    property Row: Integer read FPageOffset;
    property RowTot: Integer read FNumRows;
    property RadioSelection: Integer read FRadioSelection write SetRadioSelection;
    property DynEdits[Col, Row: Integer]: string read GetDynEdits write SetDynEdits;
    property DetailStates[Row: Integer]: Boolean read GetDetailStates write SetDetailStates;
    property ActiveColumn: Integer read FActiveColumn write FActiveColumn;
    property ActiveDetailRow: Integer read GetActiveDetailRow write SetActiveDetailRow;
    function GetVersionNr: Integer; virtual;
    function GetVersionString: string; virtual;
    procedure Invalidate; override;
  published
    property ActiveRowColor: TIWColor read FActiveRowColor write FActiveRowColor;
    property ActiveRowFontColor: TIWColor read FActiveRowFontColor write
      FActiveRowFontColor;
    property AdvanceOnReturn: Boolean read FAdvanceOnReturn write FAdvanceOnReturn;
    property AutoEdit: Boolean read FAutoEdit write FAutoEdit;
    property AutoHTMLAdapt: Boolean read FAutoHTMLAdapt write FAutoHTMLAdapt;
    property Background: TIWGridBackground read FBackground write SetBackground;
    property Bands: TTIWAdvWebGridBands read FBands write SetBands;
    property Borders: TTIWRGBorders read FBorders write SetBorders;
    property CheckTruePicture: TIPicture read FCheckTruePicture write SetCheckTruePicture;
    property CheckTruePictureURL: string read FCheckTruePictureURL write FCheckTruePictureURL;
    property CheckFalsePicture: TIPicture read FCheckFalsePicture write SetCheckFalsePicture;
    property CheckFalsePictureURL: string read FCheckFalsePictureURL write FCheckFalsePictureURL;
    property ClientEvents: TIWGridClientEvents read FClientEvents write SetClientEvents;
    property Color;
    property Columns: TTIWWebGridColumns read FColumns write SetColumns;
    property ColumnHeaderColor: TIWColor read FColumnHeaderColor write SetColumnHeaderColor;
    property ColumnHeaderFont: TIWFont read FColumnHeaderFont write SetColumnHeaderFont;
    property ColumnHeaderBorders: TTIWRGBorders read FColumnHeaderBorders write FColumnHeaderBorders;  
    property ColumnSizing: Boolean read FColumnSizing write SetColumnSizing;
    property Controller: TTIWAdvWebGridController read FController write SetController;
    property DateSeparator: char read FDateSeparator write FDateSeparator;
    property DateFormat: TTIWGridDateFormat read FDateFormat write FDateFormat;
    property DecimalPoint: char read FDecimalPoint write FDecimalPoint;
    property DefaultRowHeight: Integer read FDefaultRowHeight write SetDefaultRowHeight;
    property DetailGrid: TTIWCustomWebGrid read FDetailGrid write FDetailGrid;
    property DetailRowHeight: Integer read FDetailHeight write FDetailHeight;
    property DetailRowShow: TTIWDetailRowShow read FDetailRowShow write
      FDetailRowShow;
    property EditColor: TIWColor read FEditColor write FEditColor;
    property EditSelectAll: Boolean read FEditSelectAll write FEditSelectAll;
    property FooterBorders: TTIWRGBorders read FFooterBorders write FFooterBorders;          
    property FooterColor: TIWColor read FFooterColor write SetFooterColor;
    property FooterFont: TIWFont read FFooterFont write SetFooterFont;
    property Font;
    property Glyphs: TTIWRGGlyphs read FGlyphs write SetGlyphs;
    property HoverColor: TIWColor read FHoverColor write SetHoverColor;
    property HoverFontColor: TIWColor read FHoverFontColor write
      SetHoverFontColor;
    property HeaderStyle: TTIWHeaderStyle read FHeaderStyle write FHeaderStyle;   
    property ID: Integer read FID write SetID;
    property Images: TImageList read FImages write FImages;
    property Indicators: TTIWRGIndicators read FIndicators write SetIndicators;
    property MouseSelect: TTIWMouseSelect read FMouseSelect write FMouseSelect;
    property Nodes: TIWGridNode read FNodes write SetNodes;
    property NameOfDays: TStringList read FNameOfDays write SetNameOfDays;
    property NameOfMonths: TStringList read FNameOfMonths write SetNameOfMonths;
    property OuterBorder: TTIWWebGridOuterBorder read FOuterBorder write FOuterBorder;
    property Page: Integer read GetPage write SetPage;
    property RowCount: Integer read FRowCount write SetRowCount;
    property RowHeader: TTIWWebGridRowHeader read FRowHeader write FRowHeader;
    property Scroll: TTIWWebGridScroll read FScroll write SetScroll;
    property SelectColor: TIWColor read FSelectColor write SetSelectColor;
    property SelectFontColor: TIWColor read FSelectFontColor write
      SetSelectFontColor;
    property SelectPersistent: Boolean read FSelectPersistent write FSelectPersistent default True;
    property ShowColumnHeader: Boolean read FShowColumnHeader write
      SetShowColumnHeader;
    property ShowFooter: Boolean read FShowFooter write SetShowFooter;
    property ShowSelect: Boolean read FShowSelect write FShowSelect;
    property SortSettings: TTIWRGSortSettings read FSortSettings write
      SetSortSettings;
    property StretchColumn: Integer read FStretchColumn write FStretchColumn;
    property TabOrder;
    property UseFullHeight: Boolean read FUseFullHeight write FUseFullHeight;
    property UseFullWidth: Boolean read FUseFullWidth write FUseFullWidth;
    property OnAfterGotoLink: TTIWAfterLinkEvent read FOnAfterGotoLink write
      FOnAfterGotoLink;
    property OnBeforeGotoLink: TTIWBeforeLinkEvent read FOnBeforeGotoLink write
      FOnBeforeGotoLink;
    property OnButtonClick: TIWRGButtonClick read FOnButtonClick write
      FOnButtonClick;
    property OnLinkClick: TIWRGButtonClick read FOnLinkClick write
      FOnLinkClick;
    property OnComboChange: TIWComboChangeEvent read FOnComboChange write
      FOnComboChange;
    property OnCanEditCell: TTIWCellAllowEvent read FOnCanEditCell write
      FOnCanEditCell;
    property OnCellClick: TIWRGButtonClick read FOnCellClick write FOnCellClick;
    property OnValueClick: TIWRGCellValueEvent read FOnValueClick write FOnValueClick;
    property OnCheckClick: TIWRGButtonClick read FOnCheckClick write
      FOnCheckClick;
    property OnColumnHeaderClick: TIWRGColumnHeaderClick read
      FOnColumnHeaderClick write FOnColumnHeaderClick;
    property OnFilterSelect: TTIWFilterEvent read FOnFilterSelect write
      FOnFilterSelect;
    property OnGetCellData: TIWRGCellDataEvent read FOnGetCellData write
      FOnGetCellData;
    property OnGetCellEditorEnabled: TIWRGCellEditorEnabled read FOnGetCellEditorEnabled  write
      FOnGetCellEditorEnabled;
    property OnGetCellType: TIWRGCellType read FOnGetCellType  write
      FOnGetCellType;
    property OnGetCellDetail: TIWRGCellDataEvent read FOnGetCellDetail write
      FOnGetCellDetail;
    property OnGetCellProp: TIWRGCellPropEvent read FOnGetCellProp write
      FOnGetCellProp;
    property OnGetCellHint: TIWRGCellDataEvent read FOnGetCellHint write
      FOnGetCellHint;
    property OnGetRowHeaderText: TIWRowHeaderTextEvent read FOnGetRowHeaderText write
      FOnGetRowHeaderText;
    property OnGetCellPopupText: TIWRGCellDataEvent read FOnGetCellPopupText
      write FOnGetCellPopupText;
    property OnGetDynText: TTIWGetDynText read FOnGetDynText write
      FOnGetDynText;
    property OnGetDetailGrid: TIWRGDetailGridEvent read FOnGetDetailGrid write
      FOnGetDetailGrid;
    property OnGetURLText: TIWRGCellDataEvent read FOnGetURLText write
      FOnGetURLText;
    property OnGetImageIdx: TTIWRGImageIndexEvent read FOnGetImageIdx write
      FOnGetImageIdx;
    property OnImageClick: TIWRGButtonClick read FOnImageClick write
      FOnImageClick;
    property OnSetCellData: TIWRGCellDataEvent read FOnSetCellData write
      FOnSetCellData;
    property OnNextPage: TNotifyEvent read FOnNextPage write FOnNextPage;
    property OnPrevPage: TNotifyEvent read FOnPrevPage write FOnPrevPage;
    property OnFirstPage: TNotifyEvent read FOnFirstPage write FOnFirstPage;
    property OnLastPage: TNotifyEvent read FOnLastPage write FOnLastPage;
    property OnGotoPage: TTIWPageEvent read FOnGotoPage write FOnGotoPage;
    property OnGotoRow: TTIWRowEvent read FOnGotoRow write FOnGotoRow;
    property OnRowCountChange: TIWRowCountEvent read FOnRowCountChange write FOnRowCountChange;
    property OnNodeOpen: TTIWRowEvent read FOnNodeOpen write FOnNodeOpen;
    property OnNodeClose: TTIWRowEvent read FOnNodeClose write FOnNodeClose;
    property OnNodeShow: TTIWNodeShowEvent read FOnNodeShow write FOnNodeShow;
    property OnEdit: TNotifyEvent read FOnEdit write FOnEdit;
    property OnCancel: TNotifyEvent read FOnCancel write FOnCancel;
    property OnPost: TNotifyEvent read FOnPost write FOnPost;
    property OnPostValidate: TTIWPostValidateEvent read FOnPostValidate write FOnPostValidate;
    property OnDirectEditUpdate: TTIWDirectEditUpdate read FOnDirectEditUpdate write FOnDirectEditUpdate;
    {$IFDEF TMSIW9}
    property AsyncActiveRowMove: Boolean read FAsyncActiveRowMove write FAsyncActiveRowMove;    
    property AsyncEdit: Boolean read FAsyncEdit write FAsyncEdit;
    property AsyncPaging: Boolean read FAsyncPaging write FAsyncPaging;
    property AsyncSorting: Boolean read FAsyncSorting write FAsyncSorting;
    property OnAsyncCellClick: TIWAsyncButtonEvent read FOnAsyncCellClick write FOnAsyncCellClick;
    property OnAsyncButtonClick: TIWAsyncButtonEvent read FOnAsyncButtonClick write FOnAsyncButtonClick;
    property OnAsyncCheckClick: TIWAsyncButtonEvent read FOnAsyncCheckClick write FOnAsyncCheckClick;
    property OnAsyncRowSelect: TIWAsyncRowSelectEvent read FOnAsyncRowSelect write FOnAsyncRowSelect;
    property OnAsyncGotoRow: TIWAsyncRowEvent read FOnAsyncGotoRow write FOnAsyncGotoRow;
    property OnAsyncImageClick: TIWAsyncButtonEvent read FOnAsyncImageClick write FOnAsyncImageClick;
    property OnAsyncLinkClick: TIWAsyncButtonEvent read FOnAsyncLinkClick write FOnAsyncLinkClick;
    property OnAsyncComboChange: TIWAsyncComboChangeEvent read FOnAsyncComboChange write FOnAsyncComboChange;
    property OnAsyncEditDone: TIWAsyncEditDoneEvent read FOnAsyncEditDone write FOnAsyncEditDone;
    property OnAsyncValidate: TIWAsyncValidateEvent read FOnAsyncValidate write FOnAsyncValidate;
    property OnAsyncPost: TIWAsyncEvent read FOnAsyncPost write FOnAsyncPost;
    property OnAsyncEdit: TIWAsyncEvent read FOnAsyncEdit write FOnAsyncEdit;
    property OnAsyncCancel: TIWAsyncEvent read FOnAsyncCancel write FOnAsyncCancel;
    property OnAsyncNextPage: TIWAsyncEvent read FOnAsyncNextPage write FOnAsyncNextPage;
    property OnAsyncPrevPage: TIWAsyncEvent read FOnAsyncPrevPage write FOnAsyncPrevPage;
    property OnAsyncFirstPage: TIWAsyncEvent read FOnAsyncFirstPage write FOnAsyncFirstPage;
    property OnAsyncLastPage: TIWAsyncEvent read FOnAsyncLastPage write FOnAsyncLastPage;
    property OnAsyncGotoPage: TIWAsyncPageEvent read FOnAsyncGotoPage write FOnAsyncGotoPage;
    property OnAsyncColumnHeaderClick: TIWAsyncColumnEvent read FOnAsyncColumnHeaderClick write FOnAsyncColumnHeaderClick;
    property OnAsyncPostValidate: TIWAsyncPostValidateEvent read FOnAsyncPostValidate write FOnAsyncPostValidate;
    procedure AsyncUpdateAllCells();
    procedure AsyncUpdateActiveRow(RenderAsync: boolean);
    {$ENDIF}
  end;


{$IFDEF LINUX}
function MakeLong(hi_, lo_: Integer): Integer;
function MakeWord(hi_, lo_: Byte): SmallInt;
function LoWord(t: Integer): word;
function HiWord(t: Integer): word;
{$ENDIF}

implementation

uses
  {$IFNDEF LINUX}
  ImgList, ShellAPI, CommCtrl,
  {$ENDIF}
  IWApplication, IWServerControllerBase,
  SWStrings, SWSystem, IWAppForm, Math, IWServer
  {$IFDEF TMSIW7}
  , IWBaseHTMLControl
  {$ENDIF}
  ;

{$DEFINE REMOVESTRIP}
{$DEFINE REMOVEDRAW}

{$IFDEF LINUX}
{$I QHTMLENG.PAS}
{$ELSE}
{$I iwhtmleng.pas}
{$ENDIF}

{$IFNDEF DELPHI7_LVL}
function BoolToStr(B: Boolean; UseBoolStrs: Boolean = False): string;
const
  cSimpleBoolStrs: array [boolean] of String = ('0', '-1');
begin
  Result := cSimpleBoolStrs[B];
end;
{$ENDIF}


{$IFDEF LINUX}

function MakeLong(hi_, lo_: Integer): Integer;
begin
  Result := ((hi_ shl 16) and $FFFF0000) or (Lo_ and $0000FFFF);
end;

function LoWord(t: Integer): word;
begin
  Result := t and $0000FFFF;
end;

function HiWord(t: Integer): word;
begin
  Result := (t and $FFFF0000) shr 16;
end;

function MakeWord(hi_, lo_: Byte): SmallInt;
begin
  Result := hi_;
  Result := (Result shl 8) + lo_;
end;

{$ENDIF}

{ TIntList }

constructor TIntList.Create;
begin
  inherited Create;
end;

procedure TIntList.SetInteger(Index: Integer; Value: Integer);
begin
  if Index < 0 then
    Exit;

  while Index >= Count do
  begin
    Add(0);
  end;

  inherited Items[Index] := Pointer(Value);
  if Assigned(OnChange) then
    OnChange(Self);
end;

function TIntList.GetInteger(Index: Integer): Integer;
begin
  Result := 0;
  if Index < 0 then
    Exit;

  while Index >= Count do
  begin
    Add(0);
  end;

  Result := Integer(inherited Items[Index]);
end;

procedure TIntList.Add(Value: Integer);
begin
  inherited Add(Pointer(Value));
  if Assigned(OnChange) then
    OnChange(Self);
end;

procedure TIntList.Delete(Index: Integer);
begin
  inherited Delete(Index);
  if Assigned(OnChange) then
    OnChange(Self);
end;

function TIntList.GetStrValue: string;
var
  i: integer;
begin
  for i := 1 to Count do
    if i = 1 then
      Result := IntToStr(Items[i - 1])
    else
      Result := Result + ',' + IntToStr(Items[i - 1]);
end;

procedure TIntList.SetStrValue(const Value: string);
var
  sl: TStringList;
  i: Integer;
begin
  sl := TStringList.Create;
  sl.CommaText := Value;
  Clear;
  for i := 1 to sl.Count do
    Add(StrToInt(sl.Strings[i - 1]));
  sl.Free;
end;

{ TTIWCustomWebGrid }
{$IFDEF TMSIW9}
procedure TTIWCustomWebGrid.DoAsyncColumnHeaderClick(AParams: TStringList);
begin  
  if GetGridState = gsBrowse then
  begin
    ColumnHeaderClick(SortSettings.Column);

    if Assigned(OnAsyncColumnHeaderClick) then
    begin
      OnAsyncColumnHeaderClick(Self, AParams, SortSettings.Column);
    end;

    AsyncUpdateAllCells;
  end;
end;

procedure TTIWCustomWebGrid.DoAsyncPost(AParams: TStringList);
var
  CellValue,  AlertMessage: string;
  i, j: integer;
  Allow, EditMode: boolean;
begin

  FEditRowIndicator := FEditRow;

  Allow := True;
  EditMode := False;
  AlertMessage := EmptyStr;
  if Assigned(OnAsyncPostValidate) then
    OnAsyncPostValidate(Self, FPostData, Allow, EditMode, AlertMessage);

  if Allow then
  begin
     for I := 0 to Columns.Count - 1 do
     begin
       if (Columns[I].ColumnType = ctRowIndicator) then
       begin
         for J := 0 to RowCount - 1 do
         begin
           if J = FEditRowIndicator then
           begin
             if Indicators.BrowseURL <> EmptyStr then
               CellValue := ImageHTML(Indicators.BrowseURL, 0, 0, False, '').Render()
             else
               CellValue := OutputBMP('BROWSE', FIndicators.Browse, False, '');
           end
           else
             CellValue := '&nbsp;';

           FAsyncSetCell := FAsyncSetCell + IntToStr(i) + '|' + IntToStr(j) + '|' + CellValue + '~';
          end;
        end
       end;

      if FAsyncSetCell <> EmptyStr then
      begin
        FAsyncSetCell := StringReplace(FAsyncSetCell, '"', '\"', [rfReplaceAll]);
        FAsyncSetCell := StringReplace(FAsyncSetCell, #13, ' ', [rfReplaceAll]);
        FAsyncSetCell := StringReplace(FAsyncSetCell, #10, ' ', [rfReplaceAll]);
        GGetWebApplicationThreadVar.CallBackResponse.AddJavaScriptToExecute('<![CDATA[GASetCell('
        + HTMLName + 'Obj, "' + FAsyncSetCell + '");]]>');
        FAsyncSetCell := EmptyStr;
      end;

      GGetWebApplicationThreadVar.CallBackResponse.AddJavaScriptToExecute('<![CDATA[GAPost(submval,'
        +HTMLName+'Obj,'+IntToStr(FEditRowIndicator)+');]]>');

      DoPost;
      
      if Assigned(OnAsyncPost) then
      begin
        OnAsyncPost(Self, AParams);

        if FAsyncSetCell <> EmptyStr then
        begin
          GGetWebApplicationThreadVar.CallBackResponse.AddJavaScriptToExecute('<![CDATA[GASetCell('
          + HTMLName + 'Obj, "' + FAsyncSetCell + '");]]>');
          FAsyncSetCell := EmptyStr;
        end;

      end;

      FEditRow := FEditRowIndicator;
  end
  else
  begin
    FPostData.Clear();

    if AlertMessage <> EmptyStr then
    begin
        GGetWebApplicationThreadVar.CallBackResponse.AddJavaScriptToExecute('<![CDATA[GAPostValidate('
          + HTMLName + 'Obj, "' + AlertMessage + '");]]>');
    end;

    if not EditMode then
    begin
       DoPost;

       for I := 0 to Columns.Count - 1 do
       begin
         if (Columns[I].ColumnType = ctRowIndicator) then
         begin
           for J := 0 to RowCount - 1 do
           begin
             if J = FEditRowIndicator then
             begin
               if Indicators.BrowseURL <> EmptyStr then
                 CellValue := ImageHTML(Indicators.BrowseURL, 0, 0, False, '').Render()
               else
                 CellValue := OutputBMP('BROWSE', FIndicators.Browse, False, '');
             end
             else
               CellValue := '&nbsp;';

             FAsyncSetCell := FAsyncSetCell + IntToStr(i) + '|' + IntToStr(j) + '|' + CellValue + '~';
            end;
          end
        end;

        if FAsyncSetCell <> EmptyStr then
        begin
          FAsyncSetCell := StringReplace(FAsyncSetCell, '"', '\"', [rfReplaceAll]);
          GGetWebApplicationThreadVar.CallBackResponse.AddJavaScriptToExecute('<![CDATA[GASetCell('
          + HTMLName + 'Obj, "' + FAsyncSetCell + '");]]>');
          FAsyncSetCell := EmptyStr;
        end;

        GGetWebApplicationThreadVar.CallBackResponse.AddJavaScriptToExecute('<![CDATA[GACancel('
          + HTMLName + 'Obj, ' + IntToStr(FEditRowIndicator) + ');]]>');
    end;
  end;
                                    
//  FEditRow := -1;
  GGetWebApplicationThreadVar.CallBackResponse.AddJavaScriptToExecute('<![CDATA[GASetEditRow(' + HTMLName + 'Obj);]]>');
end;

procedure TTIWCustomWebGrid.DoAsyncEdit(AParams: TStringList);
var
CellValue: string;
i, j: integer;
begin

  FEditRowIndicator := FEditRow - RowOffset;

  for I := 0 to Columns.Count - 1 do
   begin
     if (Columns[I].ColumnType = ctRowIndicator) then
     begin
      for J := 0 to RowCount - 1 do
      begin
        if J = FEditRowIndicator then
        begin
          if Indicators.EditURL <> EmptyStr then
            CellValue := ImageHTML(Indicators.EditURL, 0, 0, False, '').Render()
          else
            CellValue := OutputBMP('EDIT', FIndicators.Edit, False, '');
        end
        else
          CellValue := '&nbsp;';

        FAsyncSetCell := FAsyncSetCell + IntToStr(i) + '|' + IntToStr(j) + '|' + CellValue + '~';
      end
    end
  end;

  if FAsyncSetCell <> EmptyStr then
  begin
    FAsyncSetCell := StringReplace(FAsyncSetCell, '"', '\"', [rfReplaceAll]);
    FAsyncSetCell := StringReplace(FAsyncSetCell, #13, ' ', [rfReplaceAll]);
    FAsyncSetCell := StringReplace(FAsyncSetCell, #10, ' ', [rfReplaceAll]);    
    GGetWebApplicationThreadVar.CallBackResponse.AddJavaScriptToExecute('<![CDATA[GASetCell('
      + HTMLName + 'Obj, "' + FAsyncSetCell + '");]]>');
    FAsyncSetCell := EmptyStr;
  end;
                                                                                              
  //new FEditRow value is set in .setvalue
  //  FEditRow := FRowOffset + ival;
  GotoRecord(FEditRow);
  DoEdit;
  
  if Assigned(OnAsyncEdit) then
    OnAsyncEdit(Self, AParams);

  FEditRow := FEditRowIndicator;
end;

procedure TTIWCustomWebGrid.DoAsyncCancel(AParams: TStringList);
var
CellValue: string;
i, j: integer;
begin
  DoCancel;

  for I := 0 to Columns.Count - 1 do
  begin
    if (Columns[I].ColumnType = ctRowIndicator) then
    begin
     for J := 0 to RowCount - 1 do
     begin
       if J = FEditRowIndicator then
       begin
         if Indicators.BrowseURL <> EmptyStr then
           CellValue := ImageHTML(Indicators.BrowseURL, 0, 0, False, '').Render()
         else
           CellValue := OutputBMP('BROWSE', FIndicators.Browse, False, '');
       end
       else
         CellValue := '&nbsp;';

       FAsyncSetCell := FAsyncSetCell + IntToStr(i) + '|' + IntToStr(j) + '|' + CellValue + '~';
     end
   end
  end;

  if FAsyncSetCell <> EmptyStr then
  begin
    FAsyncSetCell := StringReplace(FAsyncSetCell, '"', '\"', [rfReplaceAll]);
    FAsyncSetCell := StringReplace(FAsyncSetCell, #13, ' ', [rfReplaceAll]);
    FAsyncSetCell := StringReplace(FAsyncSetCell, #10, ' ', [rfReplaceAll]);    
    GGetWebApplicationThreadVar.CallBackResponse.AddJavaScriptToExecute('<![CDATA[GASetCell('
    + HTMLName + 'Obj, "' + FAsyncSetCell + '");]]>');
    FAsyncSetCell := EmptyStr;
  end;

  if Assigned(OnAsyncCancel) then
    OnAsyncCancel(Self, AParams);

//  FEditRow := -1;
  GGetWebApplicationThreadVar.CallBackResponse.AddJavaScriptToExecute('<![CDATA[GASetEditRow('+HTMLName+'Obj);]]>');
end;

procedure TTIWCustomWebGrid.AsyncUpdateRowCheck();
var
  CellStates: string;
  i, j, c: integer;
begin
  CellStates := EmptyStr;

  for i := 0 to RowCount - 1 do
  begin
    CellStates := CellStates + IIF(RowSelect[RowOffset + i],'1','0');
  end;
                                                               
  c := -1;
  for j := 0 to Columns.Count - 1 do                             
  begin                                                           
    if (Columns[j].ColumnType = ctCheckBox) then
    begin
      c := j;
    end;
  end;

  if Length(CellStates) > 0 then
    GGetWebApplicationThreadVar.CallBackResponse.AddJavaScriptToExecute('<![CDATA[GASetCellState('
    + HTMLName + 'Obj,"' + CellStates + '",' + IIF(MouseSelect in [msSingleRowCheck], 'true', 'false') + ','+ IntToStr(c) +');]]>');
end;



procedure TTIWCustomWebGrid.AsyncUpdateActiveRow(RenderAsync: boolean);
var
  CellValue, chkrow: string;
  i, j, c, RowsOnPage, NewActiveRow: integer;
begin

  //Update NumRows in case the RowCount of the db-query has changed
  GetRowInfo(FNumRows, FRowOffset, FPageOffset);

  FEditRowIndicator := FEditRow;

  //Async RowOffset & CheckedRow Update
  chkrow := '-1';

  if RowCount = 0 then
    RowsOnPage := FNumRows
  else
  begin
    if (RowCount + RowOffset <= FNumRows) then
      RowsOnPage := RowCount
    else
      RowsOnPage := FNumRows - RowOffset;
  end;

  if MouseSelect in [msSingleRowCheck, msRowCheck] then
  begin
    for c := 1 to RowsOnPage do
      if RowSelect[c - 1 + RowOffset] then
        chkrow := inttostr(c);
  end;

  GGetWebApplicationThreadVar.CallBackResponse.AddJavaScriptToExecute('<![CDATA[GASetRowOffset('
    + HTMLName + 'Obj, "' + IntToStr(RowOffset) + '",' + chkrow + ');]]>');   

  GGetWebApplicationThreadVar.CallBackResponse.AddJavaScriptToExecute('<![CDATA[GASetRows('
    + HTMLName + 'Obj, "' + IntToStr(RowsOnPage) + '");]]>');

    if RenderAsync then    
      NewActiveRow := FPageOffset
    else
      NewActiveRow := FCellRow;

   //RowIndicator Update
   for I := 0 to Columns.Count - 1 do
    begin
      if (Columns[I].ColumnType = ctRowIndicator) then
      begin
       for J := 0 to RowCount - 1 do
       begin
         //set rowindicator on the new selected row
         if J = NewActiveRow then
         begin
           if Indicators.BrowseURL <> EmptyStr then
             CellValue := ImageHTML(Indicators.BrowseURL, 0, 0, False, '').Render()
           else
             CellValue := OutputBMP('BROWSE', FIndicators.Browse, False, '');

           FAsyncSetCell := FAsyncSetCell + IntToStr(i) + '|' + IntToStr(j) + '|' + CellValue + '~';
         end
         //remove rowindicator from the old selected row
         else //if J = FPageOffset then
         begin
           CellValue := '&nbsp;';

           FAsyncSetCell := FAsyncSetCell + IntToStr(i) + '|' + IntToStr(j) + '|' + CellValue + '~';
         end
       end
     end
    end;                       

    if FAsyncSetCell <> EmptyStr then
    begin
      FAsyncSetCell := StringReplace(FAsyncSetCell, '"', '\"', [rfReplaceAll]);
      GGetWebApplicationThreadVar.CallBackResponse.AddJavaScriptToExecute('<![CDATA[GASetCell('
        + HTMLName + 'Obj, "' + FAsyncSetCell + '");]]>');
      FAsyncSetCell := EmptyStr;
    end;                                                               

end;

procedure TTIWCustomWebGrid.AsyncUpdateAllCells();
var
  CellValue, CellStates, CellData, chkrow: string;
  i, j, c, RowsOnPage: integer;
  dseof: boolean;
begin
  SaveBookmark;

  //Update NumRows in case the RowCount of the db-query has changed
  GetRowInfo(FNumRows, FRowOffset, FPageOffset);

  FEditRowIndicator := FEditRow;

  //Async RowOffset & CheckedRow Update
  chkrow := '-1';

  if RowCount = 0 then
    RowsOnPage := FNumRows
  else
  begin
    if (RowCount + RowOffset <= FNumRows) then
      RowsOnPage := RowCount
    else
      RowsOnPage := FNumRows - RowOffset;
  end;

  if MouseSelect in [msSingleRowCheck, msRowCheck] then
  begin
    for c := 1 to RowsOnPage do
      if RowSelect[c - 1 + RowOffset] then
        chkrow := inttostr(c);
  end;

  GGetWebApplicationThreadVar.CallBackResponse.AddJavaScriptToExecute('<![CDATA[GASetRowOffset('
    + HTMLName + 'Obj, "' + IntToStr(RowOffset) + '",' + chkrow + ');]]>');

  dseof := false;
  CellStates := EmptyStr;
  for J := 0 to RowCount - 1 do
  begin
    CellStates := CellStates + IIF(RowSelect[RowOffset + J],'1','0');

    for I := 0 to Columns.Count - 1 do
    begin
      if not dseof then
      begin
        if IsValidRow(j) then
        begin

//  OutputDebugString(pchar('valid rowupdate ' + IntToStr(J) + ' (' + IntToStr(FRowOffset) + '): ' + BoolToStr(RowSelect[FRowOffset + J])));

          CellData := GetCellData(i,j);

          if (Columns[I].ColumnType = ctRowNumber) then
            //CellValue := FontToTag(Columns[I].Font,IntToStr(FRowOffset + J + 1))
              CellValue := IntToStr(RowOffset + J + 1)
          else
          if (Columns[I].ColumnType = ctLinkRowNumber) then
            CellValue := IntToStr(RowOffset + J + 1)
          else if (Columns[I].ColumnType = ctCheckBox) then
            CellValue := BoolToStr(RowSelect[RowOffset + J])
          else if (Columns[I].ColumnType = ctImage) or (Columns[I].ColumnType = ctDataImage) then
          begin
            if Assigned(FImages) then
              CellValue := '#cached#'
            else
            begin
              if not (CellData = '') then
              begin
                if (Pos('<img', CellData) < 1) then
                  CellValue := '<img src="' + CellData + '">'
              end
              else
                CellValue := '&nbsp;';
            end
          end
          else
            CellValue := GetCellData(i,j);

        end
        else
          CellValue := '';
      end
      else
        CellValue := '&nbsp;';

      FAsyncSetCell := FAsyncSetCell + IntToStr(i) + '|' + IntToStr(j) + '|' + CellValue + '~';
    end;

    dseof := NextRecord;
  end;

  if FAsyncSetCell <> EmptyStr then
  begin
    FAsyncSetCell := StringReplace(FAsyncSetCell, '"', '\"', [rfReplaceAll]);
    FAsyncSetCell := StringReplace(FAsyncSetCell, #13, ' ', [rfReplaceAll]);
    FAsyncSetCell := StringReplace(FAsyncSetCell, #10, ' ', [rfReplaceAll]);

    GGetWebApplicationThreadVar.CallBackResponse.AddJavaScriptToExecute('<![CDATA[GASetCell('
      + HTMLName + 'Obj, "' + FAsyncSetCell + '");]]>');

    FAsyncSetCell := EmptyStr;
  end;

  GGetWebApplicationThreadVar.CallBackResponse.AddJavaScriptToExecute('<![CDATA[GASetRows('
    + HTMLName + 'Obj, "' + IntToStr(RowsOnPage) + '");]]>');

   if Length(CellStates) > 0 then
   begin
    GGetWebApplicationThreadVar.CallBackResponse.AddJavaScriptToExecute('<![CDATA[GASetCellState('
      + HTMLName + 'Obj,"' + CellStates + '",' + IIF(MouseSelect in [msSingleRowCheck], 'true', 'false') + ');]]>');
   end;

  //Async Controller Update
  FAsyncSetCtrl := GetController(FisIE,true,true);
  FAsyncSetCtrl := StringReplace(FAsyncSetCtrl, '"', '\"', [rfReplaceAll]);
  if FAsyncSetCtrl <> EmptyStr then
  begin
    FAsyncSetCtrl := '<![CDATA[GASetCtrl(' + HTMLName + 'Obj, "' + FAsyncSetCtrl + '");]]>';
    GGetWebApplicationThreadVar.CallBackResponse.AddJavaScriptToExecute(FAsyncSetCtrl);
    FAsyncSetCtrl := EmptyStr;
  end;

   //RowIndicator Update
   for I := 0 to Columns.Count - 1 do
    begin
      if (Columns[I].ColumnType = ctRowIndicator) then
      begin
       for J := 0 to RowCount - 1 do
       begin
//         if J = FEditRowIndicator then
         if J = FPageOffset then
         begin
           if Indicators.BrowseURL <> EmptyStr then
             CellValue := ImageHTML(Indicators.BrowseURL, 0, 0, False, '').Render()
           else
             CellValue := OutputBMP('BROWSE', FIndicators.Browse, False, '');
         end
         else
           CellValue := '&nbsp;';

         FAsyncSetCell := FAsyncSetCell + IntToStr(i) + '|' + IntToStr(j) + '|' + CellValue + '~';
       end
     end
    end;

    if FAsyncSetCell <> EmptyStr then
    begin
      FAsyncSetCell := StringReplace(FAsyncSetCell, '"', '\"', [rfReplaceAll]);

      GGetWebApplicationThreadVar.CallBackResponse.AddJavaScriptToExecute('<![CDATA[GASetCell('
        + HTMLName + 'Obj, "' + FAsyncSetCell + '");]]>');

      FAsyncSetCell := EmptyStr;
    end;

//    FEditRow := FEditRowIndicator;
//    GotoRecord(FEditRow);

  RestoreBookmark;

end;

procedure TTIWCustomWebGrid.DoAsyncNextPage(AParams: TStringList);
begin

  if FEditRow >= 0 then
    GGetWebApplicationThreadVar.CallBackResponse.AddJavaScriptToExecute('<![CDATA[GACancel('
      + HTMLName + 'Obj, ' + IntToStr(FEditRow) + ');]]>');

  RowOffset := RowOffset + RowCount;

  if Assigned(OnAsyncNextPage) then
    OnAsyncNextPage(Self, AParams);

    //ro change
  GotoRecord(RowOffset);

  SaveBookmark;
  GGetWebApplicationThreadVar.CallBackResponse.AddJavaScriptToExecute('<![CDATA[GASetEditRow(' + HTMLName + 'Obj);]]>');
  AsyncUpdateAllCells;
  RestoreBookmark;
end;

procedure TTIWCustomWebGrid.DoAsyncPrevPage(AParams: TStringList);
begin
  if FEditRow >= 0 then
    GGetWebApplicationThreadVar.CallBackResponse.AddJavaScriptToExecute('<![CDATA[GACancel('
      + HTMLName + 'Obj, ' + IntToStr(FEditRow) + ');]]>');

  if RowOffset >= RowCount then
    RowOffset := RowOffset - RowCount
  else
    RowOffset := 0;

  if Assigned(OnAsyncPrevPage) then
    OnAsyncPrevPage(Self, AParams);

  GotoRecord(RowOffset);

  SaveBookmark;
  GGetWebApplicationThreadVar.CallBackResponse.AddJavaScriptToExecute('<![CDATA[GASetEditRow(' + HTMLName + 'Obj);]]>');
  AsyncUpdateAllCells;
  RestoreBookmark;
end;

procedure TTIWCustomWebGrid.DoAsyncFirstPage(AParams: TStringList);
begin
  if FEditRow >= 0 then
    GGetWebApplicationThreadVar.CallBackResponse.AddJavaScriptToExecute('<![CDATA[GACancel('
      + HTMLName + 'Obj, ' + IntToStr(FEditRow) + ');]]>');

  RowOffset := 0;

  if Assigned(OnAsyncFirstPage) then
    OnAsyncFirstPage(Self, AParams);

  GotoRecord(RowOffset);

  SaveBookmark;
  GGetWebApplicationThreadVar.CallBackResponse.AddJavaScriptToExecute('<![CDATA[GASetEditRow(' + HTMLName + 'Obj);]]>');
  AsyncUpdateAllCells;
  RestoreBookmark;
end;

procedure TTIWCustomWebGrid.DoAsyncLastPage(AParams: TStringList);
begin
  if FEditRow >= 0 then
    GGetWebApplicationThreadVar.CallBackResponse.AddJavaScriptToExecute('<![CDATA[GACancel('
      + HTMLName + 'Obj, ' + IntToStr(FEditRow) + ');]]>');

  RowOffset := ((FNumRows - 1) div RowCount) * RowCount;
  
  if Assigned(OnAsyncLastPage) then
    OnAsyncLastPage(Self, AParams);

  GotoRecord(RowOffset);

  SaveBookmark;
  GGetWebApplicationThreadVar.CallBackResponse.AddJavaScriptToExecute('<![CDATA[GASetEditRow(' + HTMLName + 'Obj);]]>');
  AsyncUpdateAllCells;
  RestoreBookmark;  
end;

procedure TTIWCustomWebGrid.DoAsyncGotoPage(AParams: TStringList);
begin

  if FEditRow >= 0 then
    GGetWebApplicationThreadVar.CallBackResponse.AddJavaScriptToExecute('<![CDATA[GACancel('
      + HTMLName + 'Obj, ' + IntToStr(FEditRow) + ');]]>');

    RowOffset := Page * RowCount;

  if Assigned(OnAsyncGotoPage) then
    OnAsyncGotoPage(Self, AParams, Page + 1);

  SaveBookmark;
  GotoRecord(RowOffset);
  RestoreBookmark;

  GGetWebApplicationThreadVar.CallBackResponse.AddJavaScriptToExecute('<![CDATA[GASetEditRow(' + HTMLName + 'Obj);]]>');
  AsyncUpdateAllCells;
end;

procedure TTIWCustomWebGrid.DoAsyncCellClick(AParams: TStringList);
begin
  if Assigned(OnAsyncCellClick) then
    OnAsyncCellClick(Self, AParams, FCellRow + RowOffset, FCellCol);
end;

procedure TTIWCustomWebGrid.DoAsyncButtonClick(AParams: TStringList);
begin
  if Assigned(OnAsyncButtonClick) then
    OnAsyncButtonClick(Self, AParams, FCellRow, FCellCol);
end;

procedure TTIWCustomWebGrid.DoAsyncCheckClick(AParams: TStringList);
begin
  if Assigned(OnAsyncCheckClick) then
    OnAsyncCheckClick(Self, AParams, FCellRow + RowOffset, FCellCol);
end;

procedure TTIWCustomWebGrid.DoAsyncRowSelect(AParams: TStringList);
begin
  if Assigned(OnAsyncRowSelect) then
    OnAsyncRowSelect(Self, AParams, FCellRow + RowOffset, FChecked);
end;
    
procedure TTIWCustomWebGrid.DoAsyncGotoRow(AParams: TStringList);
begin
  SaveBookmark;

  FPrevPageOffset := FPageOffset;
  FPageOffset := FCellRow;

  //  AsyncUpdateAllCells;
  AsyncUpdateActiveRow(false);

  if Assigned(OnAsyncGotoRow) then
    OnAsyncGotoRow(Self, AParams, FCellRow + RowOffset);

  GGetWebApplicationThreadVar.CallBackResponse.AddJavaScriptToExecute('<![CDATA[GARowChange('
    + HTMLName + 'Obj, '+ IntToStr(FCellRow) +');]]>');

  RestoreBookmark;

  GotoRecord(FCellRow + RowOffset);
end;

procedure TTIWCustomWebGrid.DoAsyncImageClick(AParams: TStringList);
begin
  if Assigned(OnAsyncImageClick) then
    OnAsyncImageClick(Self, AParams, FCellRow + RowOffset, FCellCol);
end;

procedure TTIWCustomWebGrid.DoAsyncLinkClick(AParams: TStringList);
begin
  if Assigned(OnAsyncLinkClick) then
    OnAsyncLinkClick(Self, AParams, FCellRow, FCellCol);
end;

procedure TTIWCustomWebGrid.DoAsyncComboChange(AParams: TStringList);                     
begin
  if Assigned(OnAsyncComboChange) then
    OnAsyncComboChange(Self, AParams, FCellRow + RowOffset, FCellCol, FCellValue);
end;

procedure TTIWCustomWebGrid.DoAsyncEditDone(AParams: TStringList);
var
 AValue, AMessage: string;
 Col, Row: integer;
begin
  AValue := FCellValue;
  AMessage := EmptyStr;

  Col := FCellCol;
  Row := FCellRow + RowOffset;

  if Assigned(OnAsyncValidate) then
  begin
    OnAsyncValidate(Self, AParams, Row, Col, AValue, AMessage);

    if (AValue <> FCellValue) or (AMessage <> EmptyStr) then
      GGetWebApplicationThreadVar.CallBackResponse.AddJavaScriptToExecute('<![CDATA[GAValidate('
      + HTMLName + 'Obj, '+ IntToStr(Col) +', '+ IntToStr(Row) +', "' + AValue
      + '", "' + AMessage + '");]]>');
  end;
                                                                       
  if Assigned(OnAsyncEditDone) then
    OnAsyncEditDone(Self, AParams, Row, Col, AValue);
end;                                                             

function TTIWCustomWebGrid.RenderAsync(
  AContext: TIWBaseHTMLComponentContext): TIWXMLTag;
  var
  I, J: integer;
  CellValue: string;
begin
  SaveBookmark;

  if FAsyncSetCell <> EmptyStr then
  begin
    FAsyncSetCell := StringReplace(FAsyncSetCell, '"', '\"', [rfReplaceAll]);
    FAsyncSetCell := StringReplace(FAsyncSetCell, #13, ' ', [rfReplaceAll]);
    FAsyncSetCell := StringReplace(FAsyncSetCell, #10, ' ', [rfReplaceAll]);    
    GGetWebApplicationThreadVar.CallBackResponse.AddJavaScriptToExecute('<![CDATA[GASetCell('
    + HTMLName + 'Obj, "' + FAsyncSetCell + '");]]>');
    FAsyncSetCell := EmptyStr;
  end;

  if FAsyncDoPostInvalid then
  begin
    FAsyncDoPostInvalid := false;
    //FPostData.Clear;

    if FAsyncInvalidPostMessage <> EmptyStr then
    begin
        GGetWebApplicationThreadVar.CallBackResponse.AddJavaScriptToExecute('<![CDATA[GAPostValidate('
          + HTMLName + 'Obj, "' + FAsyncInvalidPostMessage + '");]]>');

        FAsyncInvalidPostMessage := EmptyStr;
    end;

    if not FAsyncInvalidPostEditMode then
    begin
       DoPost;

       for I := 0 to Columns.Count - 1 do
       begin
         if (Columns[I].ColumnType = ctRowIndicator) then
         begin
           for J := 0 to RowCount - 1 do
           begin
             if J = FEditRow then
             begin
               if Indicators.BrowseURL <> EmptyStr then
                 CellValue := ImageHTML(Indicators.BrowseURL, 0, 0, False, '').Render()
               else
                 CellValue := OutputBMP('BROWSE', FIndicators.Browse, False, '');
             end
             else
               CellValue := '&nbsp;';

             FAsyncSetCell := FAsyncSetCell + IntToStr(i) + '|' + IntToStr(j) + '|' + CellValue + '~';
            end;
          end
        end;

        if FAsyncSetCell <> EmptyStr then
        begin
          FAsyncSetCell := StringReplace(FAsyncSetCell, '"', '\"', [rfReplaceAll]);
          FAsyncSetCell := StringReplace(FAsyncSetCell, #13, ' ', [rfReplaceAll]);
          FAsyncSetCell := StringReplace(FAsyncSetCell, #10, ' ', [rfReplaceAll]);
          GGetWebApplicationThreadVar.CallBackResponse.AddJavaScriptToExecute('<![CDATA[GASetCell('
          + HTMLName + 'Obj, "' + FAsyncSetCell + '");]]>');
          FAsyncSetCell := EmptyStr;
        end;

        GGetWebApplicationThreadVar.CallBackResponse.AddJavaScriptToExecute('<![CDATA[GACancel('
          + HTMLName + 'Obj, ' + IntToStr(FEditRowIndicator) + ');]]>');
    end;
  end;


  if FAsyncDoEdit then
  begin
    FEditRow := FAsyncSetEditMode;

     for I := 0 to Columns.Count - 1 do
     begin
       if (Columns[I].ColumnType = ctRowIndicator) then
       begin
         for J := 0 to RowCount - 1 do
         begin
           if J = FEditRow then
           begin
             if Indicators.EditURL <> EmptyStr then
               CellValue := ImageHTML(Indicators.EditURL, 0, 0, False, '').Render()
             else
               CellValue := OutputBMP('EDIT', FIndicators.Edit, False, '');
           end
           else
             CellValue := '&nbsp;';

           FAsyncSetCell := FAsyncSetCell + IntToStr(i) + '|' + IntToStr(j) + '|' + CellValue + '~';
         end;
       end
     end;

    if FAsyncSetCell <> EmptyStr then
    begin
      FAsyncSetCell := StringReplace(FAsyncSetCell, '"', '\"', [rfReplaceAll]);
      FAsyncSetCell := StringReplace(FAsyncSetCell, #13, ' ', [rfReplaceAll]);
      FAsyncSetCell := StringReplace(FAsyncSetCell, #10, ' ', [rfReplaceAll]);
      GGetWebApplicationThreadVar.CallBackResponse.AddJavaScriptToExecute('<![CDATA[GASetCell('
      + HTMLName + 'Obj, "' + FAsyncSetCell + '");]]>');
      FAsyncSetCell := EmptyStr;
    end;

    GotoRecord(FAsyncSetEditMode);
    DoEdit;

    GGetWebApplicationThreadVar.CallBackResponse.AddJavaScriptToExecute('<![CDATA[GAEdit('
    + HTMLName + 'Obj, ' + IntToStr(FAsyncSetEditMode) + ', ' + HTMLControlImplementation.IWCLName + ',false);]]>');

    FAsyncDoEdit := false;
    FAsyncSetEditMode := -1;
  end;

  if FAsyncDoPost then
  begin
     for I := 0 to Columns.Count - 1 do
     begin
       if (Columns[I].ColumnType = ctRowIndicator) then
       begin
         for J := 0 to RowCount - 1 do
         begin
           if J = FEditRow then
           begin
             if Indicators.BrowseURL <> EmptyStr then
               CellValue := ImageHTML(Indicators.BrowseURL, 0, 0, False, '').Render()
             else
               CellValue := OutputBMP('BROWSE', FIndicators.Browse, False, '');
           end
           else
             CellValue := '&nbsp;';

           FAsyncSetCell := FAsyncSetCell + IntToStr(i) + '|' + IntToStr(j) + '|' + CellValue + '~';
         end;
       end
     end;

    if FAsyncSetCell <> EmptyStr then
    begin
      FAsyncSetCell := StringReplace(FAsyncSetCell, '"', '\"', [rfReplaceAll]);
      FAsyncSetCell := StringReplace(FAsyncSetCell, #13, ' ', [rfReplaceAll]);
      FAsyncSetCell := StringReplace(FAsyncSetCell, #10, ' ', [rfReplaceAll]);
      GGetWebApplicationThreadVar.CallBackResponse.AddJavaScriptToExecute('<![CDATA[GASetCell('
      + HTMLName + 'Obj, "' + FAsyncSetCell + '");]]>');
      FAsyncSetCell := EmptyStr;
    end;

    DoPost;

    GGetWebApplicationThreadVar.CallBackResponse.AddJavaScriptToExecute('<![CDATA[GAPost('
    + 'FindElem(' + HTMLName + 'Obj.id).value,' + HTMLName + 'Obj, ' + IntToStr(FEditRow) + ');]]>');

    FAsyncDoPost := false;
  end;

  if FAsyncDoCancel then
  begin
     for I := 0 to Columns.Count - 1 do
     begin
       if (Columns[I].ColumnType = ctRowIndicator) then
       begin
         for J := 0 to RowCount - 1 do
         begin
           if J = FEditRow then
           begin
             if Indicators.BrowseURL <> EmptyStr then
               CellValue := ImageHTML(Indicators.BrowseURL, 0, 0, False, '').Render()
             else
               CellValue := OutputBMP('BROWSE', FIndicators.Browse, False, '');
           end
           else
             CellValue := '&nbsp;';

           FAsyncSetCell := FAsyncSetCell + IntToStr(i) + '|' + IntToStr(j) + '|' + CellValue + '~';
         end;
       end
     end;

    if FAsyncSetCell <> EmptyStr then
    begin
      FAsyncSetCell := StringReplace(FAsyncSetCell, '"', '\"', [rfReplaceAll]);
      GGetWebApplicationThreadVar.CallBackResponse.AddJavaScriptToExecute('<![CDATA[GASetCell('
      + HTMLName + 'Obj, "' + FAsyncSetCell + '");]]>');
      FAsyncSetCell := EmptyStr;
    end;

    DoCancel;

    GGetWebApplicationThreadVar.CallBackResponse.AddJavaScriptToExecute('<![CDATA[GACancel('
    + HTMLName + 'Obj, ' + IntToStr(FEditRow) + ');]]>');

    FAsyncDoCancel := false;
  end;

  if AsyncActiveRowMove then
  begin
    RestoreBookmark;                   
    SaveBookMark;
    //AsyncUpdateAllCells;
    AsyncUpdateActiveRow(true);

    if (ActiveRowColor <> clNone) or (ActiveRowFontColor <> clNone) then
    begin
      GGetWebApplicationThreadVar.CallBackResponse.AddJavaScriptToExecute('<![CDATA[GARowChange('
        + HTMLName + 'Obj, '+ IntToStr(FPageOffset) +');]]>');
    end
  end;
                                            
  RestoreBookmark;

  Result := TIWXMLTag.CreateTag('control');
  try
    Result.AddStringParam('id', HTMLName);
    Result.AddStringParam('type', 'TTIWCUSTOMWEBGRID');

    RenderAsyncCommonProperties( AContext, Result );

  except
    FreeAndNil(Result);
  end;
end;

procedure TTIWCustomWebGrid.AsyncSetEditMode(Row: Integer);
begin
  FAsyncDoEdit := true;
  FAsyncSetEditMode := Row;
  GotoRecord(FAsyncSetEditMode);
  DoEdit;
  Invalidate;
end;

function TTIWCustomWebGrid.AsyncDoPost(): boolean;
var
  Allow, EditMode: boolean;
  AlertMessage: string;
begin
  Allow := True;
  EditMode := False;
  AlertMessage := EmptyStr;
  if Assigned(OnAsyncPostValidate) then
    OnAsyncPostValidate(Self, FPostData, Allow, EditMode, AlertMessage);

  if Allow then
  begin
    DoPost;
    FAsyncDoPost := true;
    Invalidate;
    FAsyncDoPostInvalid := false;
    Result := true;
  end
  else
  begin
    FAsyncDoPostInvalid := true;
    FAsyncInvalidPostMessage := AlertMessage;
    FAsyncInvalidPostEditMode := EditMode;
    Invalidate;
    Result := false;
  end;
end;

procedure TTIWCustomWebGrid.AsyncDoCancel();
begin
  DoCancel;
  FAsyncDoCancel := true;
  Invalidate;
end;

procedure TTIWCustomWebGrid.AsyncSetCell(Col: Integer; Row: Integer; Value: string);
var
  TempEditRow: integer;
  TempCol: TTIWColumnEditor;
  HasTempCol: Boolean;

begin
  if (Col > Columns.Count) then
  begin
    if Col >= Columns.Count then
      raise Exception.Create('Col index out of bounds '#13+InttoStr(Col)+' is not in range 0..'+inttostr(Columns.Count-1));
  end
  else
  begin
    TempEditRow := FEditRow;
    TempCol := Columns[Col].Editor;
    if Columns[Col].Editor = edNone then
    begin
      Columns[Col].Editor := edEdit;
      HasTempCol := true;
    end
    else
      HasTempCol := false;

//    TempRowOffset := FRowOffset;

//    if (Row > RowCount) then
//    begin
//      FRowOffset := (Row div RowCount) * RowCount;
//      FEditRow := Row;                                                              
//    end
//    else
//    begin
      if Row >= RowOffset then
        FAsyncSetCell := FAsyncSetCell + IntToStr(Col) + '|' + IntToStr(Row - RowOffset) + '|' + Value + '~'
      else
        FAsyncSetCell := FAsyncSetCell + IntToStr(Col) + '|' + IntToStr(Row) + '|' + Value + '~';
      FEditRow := Row;
//      FEditRow := FRowOffset + Row;
//    end;

    GotoRecord(FEditRow);
    DoEdit;
    FPostData.Clear;
    SetCellData(Col, 0, Value);
    DoPost;

//    FRowOffset := TempRowOffset;

    if HasTempCol then
      Columns[Col].Editor := TempCol;
    FEditRow := TempEditRow;
    GotoRecord(FEditRow);
  end;

  Invalidate;

end;

procedure TTIWCustomWebGrid.AsyncRowSelect(Row: Integer; Selected: Boolean);
begin
  RowSelect[Row] := Selected;
//  AsyncUpdateAllCells;
  AsyncUpdateRowCheck;
end;

procedure TTIWCustomWebGrid.AsyncClearRowSelect;
begin
  ClearRowSelect;
//  AsyncUpdateAllCells;
  AsyncUpdateRowCheck;
end;

{$ENDIF}


constructor TTIWCustomWebGrid.Create(AOwner: TComponent);
var
  i,maxid: Integer;

begin
  inherited;
  // General IW control settings
  {$IFDEF TMSIW6}
  SetRenderSize(True);
  {TODO}
  {$ELSE}
  FRenderSize := True;
  FSupportsSubmit := True;
  FSupportsInput := True;
  {$ENDIF}
  Editable := true;

  ic := TIWHTMLPictureCache.Create;
  ic.DesignLive := True;
  Color := clNone;
  FColumns := CreateColumns;
  FRowCount := 10;
  FController := TTIWAdvWebGridController.Create;
  FController.OnChange := ControllerChanged;
  FController.FControllerBorders := TTIWRGBorders.Create(Self);
  FController.FControllerBorders.FCollapsed := true;
  FIndicators := TTIWRGIndicators.Create(Self);
  FBorders := TTIWRGBorders.Create(Self);
  FBorders.FCollapsed := true;
  FSortSettings := TTIWRGSortSettings.Create(Self);
  FStretchColumn := -1;
  FHeaderStyle := hsRaised;
  FSelectPersistent := True;

  FRowOffset := 0;
  FBands := TTIWAdvWebGridBands.Create(Self);
  FGlyphs := TTIWRGGlyphs.Create(Self);
  FColumnHeaderColor := clBtnFace;
  FShowColumnHeader := True;
  FHoverColor := clNone;
  FHoverFontColor := clNone;
  FSelectColor := clHighlight;
  FSelectFontColor := clHighlightText;
  FEditColor := clNone;
  FActiveRowColor := clNone;
  FActiveRowFontColor := clNone;
  FDecimalPoint := '.';
  FDateSeparator := '/';

  FColumnHeaderFont := TIWFont.Create;
  FFooterBorders := TTIWRGBorders.Create(Self);
  FFooterBorders.FCollapsed := true;
  FFooterFont := TIWFont.Create;
  FFooterColor := clBtnFace;
  Width := 384;
  Height := 260;
  FSelectList := TIntList.Create;
  FDynEdits := TStringList.Create;
  FDefaultRowHeight := 22;

  FCache := TStringList.Create;
  FPostData := TStringList.Create;

  FActiveColumn := -1;
  FRadioSelection := -1;

  FCheckTruePicture := TIPicture.Create;
  FCheckFalsePicture := TIPicture.Create;

  FShowSelect := True;
  FDirectPost := True;

  FNodes := TIWGridNode.Create(Self);
  FBackground := TIWGridBackground.Create;

  FClientEvents := TIWGridClientEvents.Create;

  FNameOfDays := TStringList.Create;
  FNameOfMonths := TStringList.Create;

  InitDays;
  InitMonths;

  {$IFDEF IW9}
  FAsyncSetEditMode := -1;
  FAsyncDoPost := false;
  FAsyncDoCancel := false;
  {$ENDIF}

  if (csDesigning in ComponentState) then
  begin
    maxid := 0;
    for i := 1 to Owner.ComponentCount do
      if (Owner.Components[i - 1] is TTIWCustomWebGrid) then
      begin
        if Owner.Components[i - 1] <> Self then
          if maxid <= (Owner.Components[i - 1] as TTIWCustomWebGrid).ID then
            maxid := (Owner.Components[i - 1] as TTIWCustomWebGrid).ID + 1;
      end;
    ID := maxid;
  end;

  FOuterBorder := TTIWWebGridOuterBorder.Create;
  FColumnHeaderBorders := TTIWRGBorders.Create(Self);
  FColumnHeaderBorders.Collapsed := true;
  FRowHeader := TTIWWebGridRowHeader.Create(Self);

  FScroll := TTIWWebGridScroll.Create;
  FSCroll.OnChange := ControllerChanged;
  FScroll.FStyle := scNever;

  FScroll.FScrollbar3DLightColor := clNone;
  FScroll.FScrollbarArrowColor := clNone;
  FScroll.FScrollbarBaseColor := clNone;
  FScroll.FScrollbarTrackColor := clNone;
  FScroll.FScrollbarDarkshadowColor := clNone;
  FScroll.FScrollbarFaceColor := clNone;
  FScroll.FScrollbarHighlightColor := clNone;
  FScroll.FScrollbarShadowColor := clNone;

  FScroll.FScrollIntoView := true;

  FDetailStates := TIntList.Create;

  if DesignMode then
  begin
    Columns.Add;
    Columns.Add;
    Columns.Add;
  end;

  if not (csDesigning in Componentstate) then
  begin
    {$IFDEF TMSIW51}
    TIWServer.AddInternalFile('IW_JS_TMSGRID','/js/TMSGRID.js');
    {$ELSE}
    GIWServer.AddInternalFile('IW_JS_TMSGRID');
    {$ENDIF}
  end;
  {$IFDEF TMSIW7}
  SupportsPartial := true;
  {$ENDIF}
end;

procedure TTIWCustomWebGrid.SetNameOfDays(const Value: TStringList);
begin
  FNameOfDays.Assign(Value);
end;

procedure TTIWCustomWebGrid.SetNameOfMonths(const Value: TStringList);
begin
  FNameOfMonths.Assign(Value);
end;

destructor TTIWCustomWebGrid.Destroy;
begin
  FNameOfDays.Free;
  FNameOfMonths.Free;
  ic.Free;
  FController.Free;
  FColumns.Free;
  FRowHeader.Free;
  FColumnHeaderFont.Free;
  FFooterFont.Free;
  FBands.Free;
  FBorders.Free;

  FOuterBorder.Free;
  FColumnHeaderBorders.Free;
  FFooterBorders.Free;
  
  FIndicators.Free;
  FSortSettings.Free;
  FGlyphs.Free;
  FSelectList.Free;
  FDynEdits.Free;
  FCache.Free;
  FPostData.Free;

  FCheckTruePicture.Free;
  FCheckFalsePicture.Free;

  FNodes.Free;
  FBackground.Free;
  FClientEvents.Free;
  FScroll.Free;
  FDetailStates.Free;
  inherited;
end;

function TTIWCustomWebGrid.ImageHTML(const ASrc: string; AWidth, AHeight:
  Integer; UseSize: Boolean; Hint: string): TIWHTMLTag;
begin
  Result := TIWHTMLTag.CreateTag('IMG');
  Result.AddStringParam('SRC', ASrc);
  Result.AddStringParam('NAME', HTMLName);
  Result.AddStringParam('ALIGN', 'MIDDLE');
  Result.AddIntegerParam('BORDER', 0 {iif(UseBorder, 1, 0)});

//hint is set on TD tag, so no need to set it again on IMG tag
//  if Hint <> '' then
//    Result.AddStringParam('TITLE', Hint);

  if (AWidth > 0) and UseSize then
    Result.AddIntegerParam('WIDTH', AWidth);

  if (DefaultRowHeight > 0) and (AHeight = 0) and UseSize then
    Result.AddIntegerParam('HEIGHT', DefaultRowHeight)
  else
  begin
    if (AHeight > 0) and UseSize then
      Result.AddIntegerParam('HEIGHT', AHeight);
  end;
end;

function TTIWCustomWebGrid.OutputBMPFileName(ACacheName: string; ABitmap: TBitmap): string;
var
  TempFilename: string;
  i: Integer;
begin
  if ABitmap.Empty then
    Result := '...'
  else
  begin
    for i := 1 to FCache.Count do
    begin
      if pos(ACacheName + ';', FCache.Strings[i - 1]) = 1 then
      begin
        TempFileName := FCache.Strings[i - 1];
        Delete(TempFileName, 1, Length(ACacheName) + 1);
        Result := TempFileName;
        Exit;
      end;
    end;

    {$IFDEF TMSIW71}
    TempFilename := TIWServerControllerBase.NewCacheFile('bmp',true);
    {$ELSE}
    TempFilename := TIWServerControllerBase.NewCacheFile('bmp');
    {$ENDIF}
    ABitmap.SaveToFile(TempFilename);
    TempFileName := GetCacheDir(Self) + ExtractFilename(TempFilename);

    Result := TempFilename;
    FCache.Add(ACacheName + ';' + Result);
  end;
end;

function TTIWCustomWebGrid.OutputBMP(ACacheName: string; ABitmap: TBitmap;
  UseSize: Boolean; Hint: string): string;
var
  TempFilename: string;
  IWHTMLTag: TIWHTMLTag;
  i: Integer;
begin
  if ABitmap.Empty then
    Result := '&gt;'
  else
  begin
    for i := 1 to FCache.Count do
    begin
      if pos(ACacheName + ';', FCache.Strings[i - 1]) = 1 then
      begin
        TempFileName := FCache.Strings[i - 1];
        Delete(TempFileName, 1, Length(ACacheName) + 1);
        Result := TempFileName;
        Exit;
      end;
    end;

    {$IFDEF TMSIW71}
    TempFilename := TIWServerControllerBase.NewCacheFile('bmp',true);
    {$ELSE}
    TempFilename := TIWServerControllerBase.NewCacheFile('bmp');
    {$ENDIF}
    ABitmap.SaveToFile(TempFilename);
    TempFileName := GetCacheDir(Self) + ExtractFilename(TempFilename);

    IWHTMLTag := ImageHTML(TempFilename, ABitmap.Width, ABitmap.Height, UseSize, Hint);

    Result := IWHTMLTag.Render;
    IWHTMLTag.Free;
    FCache.Add(ACacheName + ';' + Result);
  end;
end;

function TTIWCustomWebGrid.OutputBMPEx(ACacheName: string; ABitmap: TBitmap;
  UseSize: Boolean; Hint: string; Height, Width: Integer): string;
var
  TempFilename: string;
  IWHTMLTag: TIWHTMLTag;
  i: Integer;
begin
  if ABitmap.Empty then
    Result := '&gt;'
  else
  begin
    for i := 1 to FCache.Count do
    begin
      if pos(ACacheName + ';', FCache.Strings[i - 1]) = 1 then
      begin
        TempFileName := FCache.Strings[i - 1];
        Delete(TempFileName, 1, Length(ACacheName) + 1);
        Result := TempFileName;
        Exit;
      end;
    end;

    {$IFDEF TMSIW71}
    TempFilename := TIWServerControllerBase.NewCacheFile('bmp',true);
    {$ELSE}
    TempFilename := TIWServerControllerBase.NewCacheFile('bmp');
    {$ENDIF}
    ABitmap.SaveToFile(TempFilename);
    TempFileName := GetCacheDir(Self) + ExtractFilename(TempFilename);

    if (Width = 0) or (Height = 0) then
      IWHTMLTag := ImageHTML(TempFilename, ABitmap.Width, ABitmap.Height, False, Hint)
    else
      IWHTMLTag := ImageHTML(TempFilename, Width, Height, UseSize, Hint);

    Result := IWHTMLTag.Render;
    IWHTMLTag.Free;
    FCache.Add(ACacheName + ';' + Result);
  end;
end;

function TTIWCustomWebGrid.GradientStyle(Color1,Color2: TIWColor; Direction: TTIWGradientDirection):string;
begin
  if (Color1 <> clNone) and (Color2 <> clNone) then
    Result := ' style="FILTER: progid:DXImageTransform.Microsoft.Gradient(GradientType=' +
        IntToStr(1 - Integer(Direction)) + ', StartColorStr='#39 + HTMLClr(Color1) + #39', EndColorStr='#39 + HTMLClr(Color2) + #39');'
  else
    Result := ' style="';
end;

function TTIWCustomWebGrid.CellColor(Color,Color1,Color2: TIWColor; Direction: TTIWGradientDirection):string;
begin
  if (Color1 <> clNone) and (Color2 <> clNone) then
    Result := ' style="FILTER: progid:DXImageTransform.Microsoft.Gradient(GradientType=' +
        IntToStr(1 - Integer(Direction)) + ', StartColorStr='#39 + HTMLClr(Color1) + #39', EndColorStr='#39 + HTMLClr(Color2) + #39');'
  else
    Result := ' style="background-color:' + HTMLClr(Color)+';';

end;

{$IFDEF TMSIW7}
function TTIWCustomWebGrid.RaisedStyle(AContext: TIWBaseComponentContext): string;
begin
  if (AContext.WebApplication.Browser = brIE) then
    Result := ' border:1px solid;border-color:ButtonHighlight ButtonShadow ButtonShadow ButtonHighlight;'
  else
    Result := '';
end;
{$ELSE}
function TTIWCustomWebGrid.RaisedStyle: string;
begin
  if (WebApplication.Browser = brIE) then
    Result := ' border:1px solid;border-color:ButtonHighlight ButtonShadow ButtonShadow ButtonHighlight;'
  else
    Result := '';
end;
{$ENDIF}

function TTIWCustomWebGrid.OutputPic(ACacheName: string; APicture: TIPicture;
  UseSize: Boolean; Hint: string): string;
var
  TempFilename: string;
  IWHTMLTag: TIWHTMLTag;
  i: Integer;
begin
  if APicture.Empty then
    Result := '&gt;'
  else
  begin
    for i := 1 to FCache.Count do
    begin
      if Pos(ACacheName + ';', FCache.Strings[i - 1]) = 1 then
      begin
        TempFileName := FCache.Strings[i - 1];
        Delete(TempFileName, 1, Length(ACacheName) + 1);
        Result := TempFileName;
        Exit;
      end;
    end;

    if APicture.IsGIF then
    {$IFDEF TMSIW71}
      TempFilename := TIWServerControllerBase.NewCacheFile('gif',true)
    {$ELSE}
      TempFilename := TIWServerControllerBase.NewCacheFile('gif')
    {$ENDIF}
    else
    {$IFDEF TMSIW71}
      TempFilename := TIWServerControllerBase.NewCacheFile('jpg',true);
    {$ELSE}
      TempFilename := TIWServerControllerBase.NewCacheFile('jpg');
    {$ENDIF}

    APicture.SaveToFile(TempFilename);

    TempFileName := GetCacheDir(Self) + ExtractFilename(TempFilename);

    IWHTMLTag := ImageHTML(TempFilename, 0, 0, UseSize, Hint);
    Result := IWHTMLTag.Render;
    IWHTMLTag.Free;

    FCache.Add(ACacheName + ';' + Result);
  end;
end;

function TTIWCustomWebGrid.GetCellImage(ACol,ARow: Integer): TPicture;
begin
  Result := nil;
  // implemented in descendent grids
end;

function TTIWCustomWebGrid.GetCellData(ACol, ARow: integer): string;
begin
  // implemented in descendent grids
end;

function HTMLStrip(s: string): string;
var
  TagPos: integer;
begin
  Result := '';
  // replace line breaks by linefeeds
  while (pos('<BR>', uppercase(s)) > 0) do
    s := StringReplace(s, '<BR>', chr(13) + chr(10), [rfIgnoreCase]);
  while (pos('<HR>', uppercase(s)) > 0) do
    s := StringReplace(s, '<HR>', chr(13) + chr(10), [rfIgnoreCase]);

  // remove all other tags
  while (VarPos('<', s, TagPos) > 0) do
  begin
    Result := Result + Copy(s, 1, TagPos - 1);
    if (VarPos('>', s, TagPos) > 0) then
      Delete(s, 1, TagPos)
    else
      Break;
  end;

  while (pos('"', s) > 0) do
    s := StringReplace(s, '"', #39, [rfIgnoreCase]);


  Result := Result + s;
end;

function StripThousandSep(s: string): string;
var
  i: Integer;
begin
  Result := '';
  for i := 1 to Length(s) do
  begin
    if s[i] = DecimalSeparator then
      Result := Result + '.'
    else if s[i] <> ThousandSeparator then
      Result := Result + s[i];
  end;
end;

function TTIWCustomWebGrid.SubmitCall(Param: string): string;
begin
  Result := '"SubmitClick('#39 + HTMLName + #39','#39 + Param + #39',false);return false;"';
  Invalidate;
end;

function TTIWCustomWebGrid.GetRowHeader(NumRows,GridHeight: Integer;HeaderRaisedStyle: string): string;
var
  s, AValue: string;
  i: Integer;
begin
  s := '<TD valign="top" width="'+IntToStr(RowHeader.FRowHeaderWidth)
    +'px" style="background:'+ HTMLClr(RowHeader.FRowHeaderColor) +';overflow:hidden;">';

  if (Scroll.Style <> scNever) then
    s := s + '<DIV id="'+ HTMLName +'div2" style="height:'
      + IntToStr(GridHeight)+';width:' + IntToStr(RowHeader.FRowHeaderWidth) + 'px;overflow:hidden;">';

  s := s + '<TABLE id="' + HTMLName + 'rh" border="' +  IntToStr(RowHeader.Borders.Width) +
    '" cellpadding="' + IntToStr(RowHeader.Borders.Padding) +
    '" cellspacing="' + IntToStr(RowHeader.Borders.Spacing) + '"';

  case FRowHeader.FRowHeaderBorders.FInner of
  ibColumns: s := s + ' RULES="cols"';
  ibRows: s := s + ' RULES="rows"';
  ibNone: s := s + ' RULES="none"';
  end;

  case FRowHeader.FRowHeaderBorders.FOuter of
  obVertical: s := s + ' FRAME="vsides"';
  obHorizontal: s := s + ' FRAME="hsides"';
  obNone: s := s + ' FRAME="void"';
  end;

  if FRowHeader.FRowHeaderBorders.FColor <> clNone then
    s := s + ' bordercolor="' + HTMLClr(FRowHeader.FRowHeaderBorders.FColor) + '"';

  if FRowHeader.FRowHeaderBorders.FColorLight <> clNone then
    s := s + ' bordercolorlight="' + HTMLClr(FRowHeader.FRowHeaderBorders.FColorLight) + '"';

  if FRowHeader.FRowHeaderBorders.FColorDark <> clNone then
    s := s + ' bordercolordark="' + HTMLClr(FRowHeader.FRowHeaderBorders.FColorDark) + '"';

  s := s + ' style="';

  if FRowHeader.FRowHeaderBorders.Collapsed then
    s := s + 'border-collapse:collapse;';

  s := s + ' font-size:'+IntToStr(Font.Size)+';width:100%;overflow:hidden;';

      //changed
  if Scroll.Style = scNever then
    s := s + 'position:relative;top:'+IntToStr(DefaultRowHeight-1)+'px;';

  s := s + '">';

  for i := 1 to NumRows do
  begin
    if (i - 1 + RowOffset < FNumRows) then
    begin
      s := s + '<TR height="'+IntToStr(DefaultRowHeight)+'"><TD align="center"';

      s := s + CellColor(RowHeader.Color,RowHeader.Gradient1,RowHeader.Gradient2,RowHeader.GradientDirection);

      if (HeaderStyle = hsRaised) then
        s := s + HeaderRaisedStyle;

      avalue := IntToStr(RowOffset + i);

      if assigned(OnGetRowHeaderText) then
        OnGetRowHeaderText(self, RowOffset + i, AValue);

      s := s + '" NOWRAP>' + avalue +'</TD></TR>';
    end;
  end;

  s := s + '</TABLE>';

  if (Scroll.Style <> scNever) then
    s := s + '</DIV>';

  s := s + '</TD>';

  Result := s;

end;

function TTIWCustomWebGrid.GetScrollBarStyle(Scroll: TTIWWebGridScroll): string;
begin
  Result := '';
  if Scroll.ScrollbarBaseColor <> clNone then
    Result := Result + 'scrollbar-base-color:' + HTMLClr(Scroll.ScrollbarBaseColor) + ';';
  if Scroll.Scrollbar3DLightColor <> clNone then
    Result := Result + 'scrollbar-3dlight-color:' + HTMLClr(Scroll.Scrollbar3DLightColor) + ';';
  if Scroll.ScrollbarArrowColor <> clNone then
    Result := Result + 'scrollbar-arrow-color:' + HTMLClr(Scroll.ScrollbarArrowColor) + ';';
  if Scroll.ScrollbarTrackColor <> clNone then
    Result := Result + 'scrollbar-track-color:' + HTMLClr(Scroll.ScrollbarTrackColor) + ';';
  if Scroll.ScrollbarDarkshadowColor <> clNone then
    Result := Result + 'scrollbar-darkshadow-color:' + HTMLClr(Scroll.ScrollbarDarkshadowColor) + ';';
  if Scroll.ScrollbarFaceColor <> clNone then
    Result := Result + 'scrollbar-face-color:' + HTMLClr(Scroll.ScrollbarFaceColor) + ';';
  if Scroll.ScrollbarHighlightColor <> clNone then
    Result := Result + 'scrollbar-highlight-color:' + HTMLClr(Scroll.ScrollbarHighlightColor) + ';';
  if Scroll.ScrollbarShadowColor <> clNone then
    Result := Result + 'scrollbar-shadow-color:' + HTMLClr(Scroll.ScrollbarShadowColor) + ';';
end;

function TTIWCustomWebGrid.HasDynEdits: Boolean;
var
  i: Integer;                                               
begin
  Result := False;

  for i := 1 to Columns.Count do
  begin
    if (Columns[i - 1].ColumnType in [ctDynEdit,ctDynCheckBox,ctDynCombo,ctDynText,ctDynMemo]) then
    begin
      Result := True;
      break;
    end;  
  end;
end;

function TTIWCustomWebGrid.HasPercCols: Boolean;
var
  i: Integer;
begin
  Result := False;

  for i := 1 to Columns.Count do
  begin
    if (Columns[i - 1].WidthType = wtPercent) then
    begin
      Result := True;
      break;
    end;
  end;
end;

function TTIWCustomWebGrid.HasColSpans: Boolean;
var
  i: Integer;
begin
  Result := False;

  for i := 1 to Columns.Count do
  begin
    if (Columns[i - 1].TitleSpan > 1) or (Columns[i - 1].SubTitleSpan > 1) then
    begin
      Result := True;
      break;
    end;
  end;
end;

function TTIWCustomWebGrid.GetVisibleCols: Integer;
var
  i: integer;
begin
  Result := 0;

  for i := 1 to Columns.Count do
  begin
    if Columns[i - 1].Visible then
      Result := Result + 1;
  end;
end;

function TTIWCustomWebGrid.GetTableWidth(inner: boolean): integer;
var
  i: integer;
begin
  Result := 0;

  if (Scroll.Style <> scNever) and not inner then
  begin
    Result := Width;
    Exit;
  end;

  for i := 1 to Columns.Count do
  begin
    if Columns[i - 1].Visible then
      Result := Result + Columns[i - 1].Width;
  end;

  Result := Result + (Columns.Count * ColumnHeaderBorders.Width);

  if not FFooterBorders.Collapsed then
    Result := Result + (Columns.Count * ColumnHeaderBorders.Width);

  if (ShowColumnHeader) then
  begin
    Result := Result + (Columns.Count * ColumnHeaderBorders.Padding);
    Result := Result + (Columns.Count * ColumnHeaderBorders.Padding);
    Result := Result + (Columns.Count * ColumnHeaderBorders.Spacing);
  end;

  Result := Result + (Columns.Count * Borders.Padding);
  Result := Result + (Columns.Count * Borders.Padding);

end;


{$WARNINGS OFF}
function TTIWCustomWebGrid.GetController(isIE, isAsync, isTop: boolean): string;
var
  i, k: Integer;
  ctrltext: string;
//  IWHTMLTag: TIWHTMLTag;
  selected: string;
  rcselbef, rcselaft: string;
  sclicknext, sclickprev, sclickfirst, sclicklast: string;

begin
  if not isAsync then
  begin
    Result := '<TR><TD colspan="2">';

    Result := Result + '<TABLE id="' + HTMLName + '_" border="' +
      IntToStr(FController.FControllerBorders.Width) +
      '" cellpadding="' + IntToStr(FController.FControllerBorders.Padding) +
      '" cellspacing="' + IntToStr(FController.FControllerBorders.Spacing) + '"';

    case FController.FControllerBorders.FInner of
    ibColumns: Result := Result + ' RULES="cols"';
    ibRows: Result := Result + ' RULES="rows"';
    ibNone: Result := Result + ' RULES="none"';
    end;

    case FController.FControllerBorders.FOuter of
    obVertical: Result := Result + ' FRAME="vsides"';
    obHorizontal: Result := Result + ' FRAME="hsides"';
    obNone: Result := Result + ' FRAME="void"';
    end;

    if FController.FControllerBorders.FColor <> clNone then
      Result := Result + ' bordercolor="' + HTMLClr(FController.FControllerBorders.FColor) + '"';

    if FController.FControllerBorders.FColorLight <> clNone then
      Result := Result + ' bordercolorlight="' + HTMLClr(FController.FControllerBorders.FColorLight) + '"';

    if FController.FControllerBorders.FColorDark <> clNone then
      Result := Result + ' bordercolordark="' + HTMLClr(FController.FControllerBorders.FColorDark) + '"';
                   
    if FController.FControllerBorders.Collapsed then
      Result := Result + ' style="border-collapse:collapse;"';

    if HasPercCols {or (Scroll.Style = scNever)} then
    begin
      Result := Result + ' width="100%">';
    end
    else
    begin
      if UseFullWidth and (StretchColumn <> -1) then
        Result := Result + ' width="' + IntToStr(Width)+'px">'
      else
      begin
        if (RowHeader.Show) and (Scroll.Style = scNever) then
          Result := Result + ' width="' + IntToStr(GetTableWidth(false) + Borders.Width + RowHeader.Width )+'px">'
        else
          Result := Result + ' width="' + IntToStr(GetTableWidth(false) + Borders.Width)+'px">';
      end;    
    end;

    if Controller.Height > 0 then
      Result := Result + '<TR height="' + IntToStr(Controller.Height) + '">'
    else
      Result := Result + '<TR>';

      if not isTop then      
        Result := Result + '<TD id="'+HTMLName+'CTRLB" colspan = "' + inttostr(Columns.Count) + '"'
      else
        Result := Result + '<TD id="'+HTMLName+'CTRLT" colspan = "' + inttostr(Columns.Count) + '"';              

    if (Controller.Gradient1 <> clNone) and (Controller.Gradient2 <> clNone) then
    begin
      if isIE then
        Result := Result + GradientStyle(Controller.Gradient1, Controller.Gradient2, Controller.GradientDirection) + '"'
      else
        Result := Result + ' bgcolor="' + HTMLClr(Controller.Gradient1) + '"';    
    end
    else if Controller.Color <> clNone then
      Result := Result + ' bgcolor="' + HTMLClr(Controller.Color) + '"';

    Result := Result + '>';
  end;

  case Controller.Alignment of
    taCenter: Result := Result + '<p align="center">';
    taRightJustify: Result := Result + '<p align="right">';
  end;

  ctrltext := Controller.Caption;

  if ((FNumRows - 1) div RowCount) > 0 then
  begin
    if Controller.FControllerPager = cpDropDownList then
    begin
        ctrltext := ctrltext + '<select' + ' onChange="SelectPage('+HTMLName+'Obj, this, ';
        {$IFDEF TMSIW9}
        if AsyncPaging then        
          ctrltext := ctrltext + HTMLControlImplementation.IWCLName + ', true);'
        else
          ctrltext := ctrltext + ''''', false);';        
        {$ELSE}
          ctrltext := ctrltext + ''''', false);';
        {$ENDIF}

        ctrltext := ctrltext + '">';

       for i := 1 to (FNumRows - 1) div RowCount + 1 do
       begin
        selected := '';
        if i = (RowOffset div RowCount) + 1 then
        selected := 'selected';
         ctrltext := ctrltext + '<option value="'+ IntToStr(i) +'" '+selected+'>' + IntToStr(i) + '</option>';
       end;
         ctrltext := ctrltext + '</select>';
    end
    else

      sclicknext := SubmitCall('Next');
      sclickprev := SubmitCall('Prev');
      sclickfirst := SubmitCall('First');
      sclicklast := SubmitCall('Last');

      {$IFDEF TMSIW9}
      if (AsyncPaging) then
      begin
        sclicknext := '"processAjaxEvent(''onNextPage'', '
          + HTMLControlImplementation.IWCLName
          + ',''' + HTMLName + '.' + 'DoAsyncNextPage' + ''','
          + 'true' + ', null, '
          + 'true' + ');"';

      end;

      if (AsyncPaging) then
      begin
        sclickprev := '"processAjaxEvent(''onPrevPage'', '
          + HTMLControlImplementation.IWCLName
          + ',''' + HTMLName + '.' + 'DoAsyncPrevPage' + ''','
          + 'true' + ', null, '
          + 'true' + ');"';

      end;

      if (AsyncPaging) then
      begin
        sclickfirst := '"processAjaxEvent(''onFirstPage'', '
          + HTMLControlImplementation.IWCLName
          + ',''' + HTMLName + '.' + 'DoAsyncFirstPage' + ''','
          + 'true' + ', null, '
          + 'true' + ');"';

      end;

      if (AsyncPaging) then
      begin
        sclicklast := '"processAjaxEvent(''onLastPage'', '
          + HTMLControlImplementation.IWCLName
          + ',''' + HTMLName + '.' + 'DoAsyncLastPage' + ''','
          + 'true' + ', null, '
          + 'true' + ');"';

      end;
      {$ENDIF}

      case Controller.PagerType of
        cptLink:
          begin

            if Controller.FControllerPager = cpPrevNext then
            begin
              if RowOffset > 0 then
                ctrltext := ctrltext + '<a href="#" onclick=' + sclickprev
                  + '>' + Controller.TextPrev + '</a>&nbsp;'
              else
                if Controller.ShowPagersAlways then
                  ctrltext := ctrltext + Controller.TextPrev+'&nbsp;';

              if RowOffset + RowCount < FNumRows then
                ctrltext := ctrltext + '<a href="#" onclick=' + sclicknext
                  + '>' + Controller.TextNext + '</a>'
              else
                if Controller.ShowPagersAlways then
                  ctrltext := ctrltext + Controller.TextNext;
            end;

            if Controller.FControllerPager = cpPrevNextFirstLast then
            begin
              if RowOffset > 0 then
                ctrltext := ctrltext + '<a href="#" onclick=' + sclickfirst
                  + '>' + Controller.TextFirst + '</a>&nbsp;'
              else
                if Controller.ShowPagersAlways then
                  ctrltext := ctrltext + Controller.TextFirst + '&nbsp;';

              if RowOffset > 0 then
                ctrltext := ctrltext + '<a href="#" onclick=' + sclickprev
                  + '>' + Controller.TextPrev + '</a>&nbsp;'
              else
                if Controller.ShowPagersAlways then
                  ctrltext := ctrltext + Controller.TextPrev+'&nbsp;';

              if RowOffset + RowCount < FNumRows then
                ctrltext := ctrltext + '<a href="#" onclick=' + sclicknext
                  + '>' + Controller.TextNext + '</a>&nbsp;'
              else
                if Controller.ShowPagersAlways then
                  ctrltext := ctrltext + Controller.TextNext + '&nbsp;';

              if RowOffset + RowCount < FNumRows then
                ctrltext := ctrltext + '<a href="#" onclick=' + sclicklast
                  + '>' + Controller.TextLast + '</a>&nbsp;'
              else
                if Controller.ShowPagersAlways then
                  ctrltext := ctrltext + Controller.TextLast + '&nbsp;';
            end;

          if Controller.FControllerPager = cpPageList then
          begin

            k := RowOffset div RowCount;

            k := ((k) div Controller.MaxPages) * Controller.MaxPages;

            if ((FNumRows - 1) div RowCount) >= Controller.MaxPages then
            begin
              if k > 0 then
                ctrltext := ctrltext
                  + '<a href="#" onclick="GASGoto(' + HTMLName+'Obj, ' + IntToStr(k - 1) + ', '
                  {$IFDEF TMSIW9}
                  + HTMLControlImplementation.IWCLName + ', '
                  + IIF((AsyncPaging or Assigned(OnAsyncGotoPage)),'true','false') + ');'
                  {$ELSE}
                  + ''''', false);'
                  {$ENDIF}
                  + '">&lt;</a>&nbsp;';

              for i := 0 to Controller.MaxPages - 1 do
              begin
                // first page = FRowOffset div RowCount
                if ((FNumRows - 1) div RowCount) >= i + k then

                  if (i + k) = Page then
                    ctrltext := ctrltext + IntToStr(i + 1 + k) + '&nbsp;'
                  else
                  begin
                    ctrltext := ctrltext + '<a href="#" onclick="GASGoto(' + HTMLName+'Obj, ' + IntToStr(i + k) + ', '
                    {$IFDEF TMSIW9}
                    + HTMLControlImplementation.IWCLName + ', '
                    + IIF((AsyncPaging or Assigned(OnAsyncGotoPage)),'true','false') + ');'
                    {$ELSE}
                    + ''''', false);'
                    {$ENDIF}
                    + '">' + IntToStr(i + 1 + k) + '</a>&nbsp;';
                  end;

              end;

              if ((FNumRows - 1) div RowCount) >= Controller.MaxPages + k then
                ctrltext := ctrltext + '<a href="#" onclick="GASGoto(' + HTMLName+'Obj, ' + IntToStr(k + Controller.MaxPages) + ', '
                  {$IFDEF TMSIW9}
                  + HTMLControlImplementation.IWCLName + ', '
                  + IIF((AsyncPaging or Assigned(OnAsyncGotoPage)),'true','false') + ');'
                  {$ELSE}
                  + ''''', false);'
                  {$ENDIF}
                  + '">&gt;</a>&nbsp;';
            end
            else
              for i := 0 to ((FNumRows - 1) div RowCount) do
              begin
                  if i = Page then
                    ctrltext := ctrltext + IntToStr(i + 1 + k) + '&nbsp;'
                  else
                  begin
                  ctrltext := ctrltext + '<a href="#" onclick="GASGoto(' + HTMLName+'Obj, ' + IntToStr(i) + ', '
                    {$IFDEF TMSIW9}
                    + HTMLControlImplementation.IWCLName + ', '
                    + IIF((AsyncPaging or Assigned(OnAsyncGotoPage)),'true','false') + ');'
                    {$ELSE}
                    + ''''', false);'
                    {$ENDIF}
                    + '">' + IntToStr(i + 1) + '</a>&nbsp;';
                  end;
              end;
          end;
        end;
      cptButton:
        begin
          if Controller.FControllerPager = cpPrevNext then
          begin
            if RowOffset > 0 then
              ctrltext := ctrltext + '<INPUT type="BUTTON" onclick=' +
                sclickprev + ' value="' + Controller.TextPrev +
                  '">&nbsp';

            if RowOffset + RowCount < FNumRows then
              ctrltext := ctrltext + '<INPUT type="BUTTON" onclick=' +
                sclicknext + ' value="' + Controller.TextNext + '">';
          end;

          if Controller.FControllerPager = cpPrevNextFirstLast then
          begin
            if (RowOffset > 0) or Controller.ShowPagersAlways then
              ctrltext := ctrltext + '<INPUT type="BUTTON" onclick=' +
                sclickfirst + IIF(RowOffset = 0,'DISABLED','') + ' value="' + Controller.TextFirst +
                '">&nbsp;';

            if (RowOffset > 0) or Controller.ShowPagersAlways then
              ctrltext := ctrltext + '<INPUT type="BUTTON" onclick=' +
                sclickprev + IIF(RowOffset = 0,'DISABLED','') + ' value="' + Controller.TextPrev +
                  '">&nbsp;';

            if (RowOffset + RowCount < FNumRows) or Controller.ShowPagersAlways then
              ctrltext := ctrltext + '<INPUT type="BUTTON" onclick=' +
                sclicknext + IIF(RowOffset + RowCount >= FNumRows,'DISABLED','') + ' value="' + Controller.TextNext +
                  '">&nbsp;';

            if (RowOffset + RowCount < FNumRows) or Controller.ShowPagersAlways then
              ctrltext := ctrltext + '<INPUT type="BUTTON" onclick=' +
                sclicklast + IIF(RowOffset + RowCount >= FNumRows,'DISABLED','') + ' value="' + Controller.TextLast +
                  '">&nbsp;';
          end;

          if Controller.FControllerPager = cpPageList then
          begin

            k := RowOffset div RowCount;

            k := ((k) div Controller.MaxPages) * Controller.MaxPages;

            if ((FNumRows - 1) div RowCount) > Controller.MaxPages then
            begin
              if k > 0 then

                ctrltext := ctrltext + '<INPUT type="BUTTON" onclick="GASGoto(' + HTMLName+'Obj, ' + IntToStr(k - 1) + ', '
                  {$IFDEF TMSIW9}
                  + HTMLControlImplementation.IWCLName + ', '
                  + IIF((AsyncPaging or Assigned(OnAsyncGotoPage)),'true','false') + ');'
                  {$ELSE}
                  + ''''', false);'
                  {$ENDIF}
                  + '" value="&lt;">&nbsp;';

              for i := 0 to Controller.MaxPages - 1 do
              begin
                // first page = FRowOffset div RowCount
                if ((FNumRows - 1) div RowCount) >= i + k then
                  //  ctrltext := ctrltext + '<a href="#" onclick='+SubmitCall('Goto'+IntToStr(i+k))+'>'+IntToStr(i+1+k)+'</a>&nbsp';

                  if (i + k) = Page then
                  ctrltext := ctrltext + '<INPUT TYPE="BUTTON" value="' + IntToStr(i + 1 + k) + '" disabled>&nbsp;'
                  else
                  begin
                    ctrltext := ctrltext + '<INPUT type="BUTTON" onclick="GASGoto(' + HTMLName+'Obj, ' + IntToStr(i + k) + ', '
                      {$IFDEF TMSIW9}
                      + HTMLControlImplementation.IWCLName + ', '
                      + IIF((AsyncPaging or Assigned(OnAsyncGotoPage)),'true','false') + ');'
                      {$ELSE}
                      + ''''', false);'
                      {$ENDIF}
                      + '" value="' + IntToStr(i + 1 + k) + '">&nbsp;';
                  end;
              end;

              if ((FNumRows - 1) div RowCount) >= Controller.MaxPages + k then
                //ctrltext := ctrltext + '<a href="#" onclick='+SubmitCall('Goto'+IntToStr(k+Controller.MaxPages))+'>&gt;</a>&nbsp';
                ctrltext := ctrltext + '<INPUT type="BUTTON" onclick="GASGoto(' + HTMLName+'Obj, ' + IntToStr(k + Controller.MaxPages) + ', '
                  {$IFDEF TMSIW9}
                  + HTMLControlImplementation.IWCLName + ', '
                  + IIF((AsyncPaging or Assigned(OnAsyncGotoPage)),'true','false') + ');'
                  {$ELSE}
                  + ''''', false);'
                  {$ENDIF}
                  + '" value="&gt;">&nbsp;';
            end
            else
              for i := 0 to ((FNumRows - 1) div RowCount) do
              begin
                if (i) = Page then
                  ctrltext := ctrltext + '<INPUT TYPE="BUTTON" value="' + IntToStr(i + 1) + '" disabled>&nbsp;'
                else
                begin
                  ctrltext := ctrltext + '<INPUT type="BUTTON" onclick="GASGoto(' + HTMLName+'Obj, ' + IntToStr(i) + ', '
                    {$IFDEF TMSIW9}
                    + HTMLControlImplementation.IWCLName + ', '
                    + IIF((AsyncPaging or Assigned(OnAsyncGotoPage)),'true','false') + ');'
                    {$ELSE}
                    + ''''', false);'
                    {$ENDIF}
                    + '" value="' + inttostr(i + 1)
                    + '">&nbsp;';
                  end;
              end;
          end;

        end;
      cptImageButton:
        begin
          if Controller.FControllerPager = cpPrevNext then
          begin
            if (RowOffset > 0) or Controller.ShowPagersAlways then
              ctrltext := ctrltext + '<BUTTON onclick=' +
                sclickprev + IIF(RowOffset = 0,'DISABLED','') + ' style="font-family:webdings" '+ IIF(Controller.HintPrev = '','title="' + Controller.TextPrev + '"', 'title="' + Controller.HintPrev + '"')+'><font face="webdings"> ' + chr($33) +
                  '</font></BUTTON>&nbsp;';

            if (RowOffset + RowCount < FNumRows) or Controller.ShowPagersAlways then
              ctrltext := ctrltext + '<BUTTON onclick=' +
                sclicknext + IIF(RowOffset + RowCount >= FNumRows,'DISABLED','') + ' style="font-family:webdings" '+ IIF(Controller.HintNext = '', 'title="' + Controller.TextNext + '"', 'title="' + Controller.HintNext + '"')+'><font face="webdings">' + chr($34) + '</font></BUTTON>';
          end;

          if Controller.FControllerPager = cpPrevNextFirstLast then
          begin
            if (RowOffset > 0) or Controller.ShowPagersAlways then
              ctrltext := ctrltext + '<BUTTON onclick=' +
                sclickfirst + IIF(RowOffset = 0,'DISABLED','') + ' style="font-family:webdings" '+ IIF(Controller.HintFirst = '', 'title="' + Controller.TextFirst + '"', 'title="' + Controller.HintFirst + '"')+'><font face="webdings">' + chr($39) +
                '</font></BUTTON>&nbsp;';

            if (RowOffset > 0) or Controller.ShowPagersAlways then
              ctrltext := ctrltext + '<BUTTON onclick=' +
                sclickprev + IIF(RowOffset = 0,'DISABLED','') + ' style="font-family:webdings" '+ IIF(Controller.HintPrev = '', 'title="' + Controller.TextPrev + '"', 'title="' + Controller.HintPrev + '"')+'><font face="webdings"> ' + chr($33) +
                  '</font></BUTTON>&nbsp;';

            if (RowOffset + RowCount < FNumRows) or Controller.ShowPagersAlways then
              ctrltext := ctrltext + '<BUTTON onclick=' +
                sclicknext + IIF(RowOffset + RowCount >= FNumRows,'DISABLED','') + ' style="font-family:webdings" '+ IIF(Controller.HintNext = '', 'title="' + Controller.TextNext + '"', 'title="' + Controller.HintNext + '"')+'><font face="webdings"> ' + chr($34) +
                  '</font></BUTTON>&nbsp;';

            if (RowOffset + RowCount < FNumRows) or Controller.ShowPagersAlways then
              ctrltext := ctrltext + '<BUTTON onclick=' +
                sclicklast + IIF(RowOffset + RowCount >= FNumRows,'DISABLED','') + ' style="font-family:webdings" '+ IIF(Controller.HintLast = '', 'title="' + Controller.TextLast + '"', 'title="' + Controller.HintLast + '"')+'><font face="webdings">' + chr($3A) +
                  '</font></BUTTON>&nbsp;';
          end;

          if Controller.FControllerPager = cpPageList then
          begin
            k := RowOffset div RowCount;

            k := ((k) div Controller.MaxPages) * Controller.MaxPages;

            if ((FNumRows - 1) div RowCount) > Controller.MaxPages then
            begin
              if k > 0 then
                ctrltext := ctrltext + '<INPUT type="BUTTON" onclick="GASGoto(' + HTMLName+'Obj, ' + IntToStr(k - 1) + ', '
                  {$IFDEF TMSIW9}
                  + HTMLControlImplementation.IWCLName + ', '
                  + IIF((AsyncPaging or Assigned(OnAsyncGotoPage)),'true','false') + ');'
                  {$ELSE}
                  + ''''', false);'
                  {$ENDIF}
                  + '" value="&lt;">&nbsp;';

              for i := 0 to Controller.MaxPages - 1 do
              begin
                // first page = FRowOffset div RowCount
                if ((FNumRows - 1) div RowCount) >= i + k then
                  //  ctrltext := ctrltext + '<a href="#" onclick='+SubmitCall('Goto'+IntToStr(i+k))+'>'+IntToStr(i+1+k)+'</a>&nbsp';

                  ctrltext := ctrltext + '<INPUT type="BUTTON" onclick="GASGoto(' + HTMLName+'Obj, ' + IntToStr(i + k) + ', '
                  {$IFDEF TMSIW9}
                  + HTMLControlImplementation.IWCLName + ', '
                  + IIF((AsyncPaging or Assigned(OnAsyncGotoPage)),'true','false') + ');'
                  {$ELSE}
                  + ''''', false);'
                  {$ENDIF}
                  + '" value="' +
                  inttostr(i + 1 + k) + '">&nbsp;';
              end;

              if ((FNumRows - 1) div RowCount) >= Controller.MaxPages + k then
                //ctrltext := ctrltext + '<a href="#" onclick='+SubmitCall('Goto'+IntToStr(k+Controller.MaxPages))+'>&gt;</a>&nbsp';
                ctrltext := ctrltext + '<INPUT type="BUTTON" onclick="GASGoto(' + HTMLName+'Obj, ' + IntToStr(k + Controller.MaxPages) + ', '
                  {$IFDEF TMSIW9}
                  + HTMLControlImplementation.IWCLName + ', '
                  + IIF((AsyncPaging or Assigned(OnAsyncGotoPage)),'true','false') + ');'
                  {$ELSE}
                  + ''''', false);'
                  {$ENDIF}
                  + '" value="&gt;">&nbsp;';

            end
            else
              for i := 0 to ((FNumRows - 1) div RowCount) do
              begin
                ctrltext := ctrltext + '<INPUT type="BUTTON" onclick="GASGoto(' + HTMLName+'Obj, ' + IntToStr(i) + ', '
                  {$IFDEF TMSIW9}
                  + HTMLControlImplementation.IWCLName + ', '
                  + IIF((AsyncPaging or Assigned(OnAsyncGotoPage)),'true','false') + ');'
                  {$ELSE}
                  + ''''', false);'
                  {$ENDIF}
                  + '" value="' + inttostr(i + 1)
                  + '">&nbsp;';
              end;
          end;

        end;

      cptImage:
        begin
          if Controller.FControllerPager = cpPrevNext then
          begin
            if RowOffset > 0 then
            begin
              ctrltext := ctrltext + '<span onclick=' + sclickprev
                + ' '+ IIF(Controller.TextPrev = '', '', 'title="' + Controller.TextPrev + '"')+'>';
                if Controller.ImgPrevURL <> EmptyStr then
                  ctrltext := ctrltext + ImageHTML(Controller.ImgPrevURL, 0, 0, False, '').Render()
                else
                  ctrltext := ctrltext + OutputPic('GRPREV', Controller.ImgPrev, False, Controller.HintPrev);
                ctrltext := ctrltext + '</span>';
            end;


            if RowOffset + RowCount < FNumRows then
            begin
              ctrltext := ctrltext + '<span onclick=' + sclicknext
                + ' '+ IIF(Controller.TextNext = '', '', 'title="' + Controller.TextNext + '"')+'>';
                if Controller.ImgNextURL <> EmptyStr then
                  ctrltext := ctrltext + ImageHTML(Controller.ImgNextURL, 0, 0, False, '').Render()
                else
                  ctrltext := ctrltext + OutputPic('GRNEXT', Controller.ImgNext, False, Controller.HintNext);
                ctrltext := ctrltext + '</span>';
            end;
          end;

          if Controller.FControllerPager = cpPrevNextFirstLast then
          begin
            if RowOffset > 0 then
            begin
              ctrltext := ctrltext + '<span onclick=' + sclickfirst
                + ' '+ IIF(Controller.HintFirst = '', 'title="' + Controller.TextFirst + '"', 'title="' + Controller.HintFirst + '"')+'>';
                if Controller.ImgFirstURL <> EmptyStr then
                  ctrltext := ctrltext + ImageHTML(Controller.ImgFirstURL, 0, 0, False, '').Render()
                else
                  ctrltext := ctrltext + OutputPic('GRFIRST', Controller.ImgFirst, False, Controller.HintFirst);
                ctrltext := ctrltext + '</span>';
            end;

            if RowOffset > 0 then
            begin
              ctrltext := ctrltext + '<span onclick=' + sclickprev
                + ' '+ IIF(Controller.HintPrev = '', 'title="' + Controller.TextPrev + '"', 'title="' + Controller.HintPrev + '"')+'>';
                if Controller.ImgPrevURL <> EmptyStr then
                  ctrltext := ctrltext + ImageHTML(Controller.ImgPrevURL, 0, 0, False, '').Render()
                else
                  ctrltext := ctrltext + OutputPic('GRPREV', Controller.ImgPrev, False, Controller.HintPrev);
                ctrltext := ctrltext + '</span>';
            end;

            if RowOffset + RowCount < FNumRows then
            begin
              ctrltext := ctrltext + '<span onclick=' + sclicknext
                + ' '+ IIF(Controller.HintNext = '', 'title="' + Controller.TextNext + '"', 'title="' + Controller.HintNext + '"')+'>';
                if Controller.ImgNextURL <> EmptyStr then
                  ctrltext := ctrltext + ImageHTML(Controller.ImgNextURL, 0, 0, False, '').Render()
                else
                  ctrltext := ctrltext + OutputPic('GRNEXT', Controller.ImgNext, False, Controller.HintNext);
                ctrltext := ctrltext + '</span>';
            end;

            if RowOffset + RowCount < FNumRows then
            begin
              ctrltext := ctrltext + '<span onclick=' + sclicklast
                + ' '+ IIF(Controller.HintLast = '', 'title="' + Controller.TextLast + '"', 'title="' + Controller.HintLast + '"')+'>';
                if Controller.ImgLastURL <> EmptyStr then
                  ctrltext := ctrltext + ImageHTML(Controller.ImgLastURL, 0, 0, False, '').Render()
                else
                  ctrltext := ctrltext + OutputPic('GRLAST', Controller.ImgLast, False, Controller.HintLast);
                ctrltext := ctrltext + '</span>';
            end;
          end;

          if Controller.FControllerPager = cpPageList then
          begin
            for i := 0 to ((FNumRows - 1) div RowCount) do
            begin
              ctrltext := ctrltext + '<INPUT type="BUTTON" onclick="GASGoto(' + HTMLName+'Obj, ' + IntToStr(i) + ', '
                  {$IFDEF TMSIW9}
                  + HTMLControlImplementation.IWCLName + ', '
                  + IIF((AsyncPaging or Assigned(OnAsyncGotoPage)),'true','false') + ');'
                  {$ELSE}
                  + ''''', false);'
                  {$ENDIF}
                  + '" value="' + inttostr(i + 1) + '">&nbsp;';
            end;
          end;
        end;
    end;

    if Controller.ShowFind then
    ctrltext := ctrltext + '<BUTTON onclick="find('+HTMLName+'Obj)"' +
      ' style="font-family:webdings;" '+ IIF(Controller.HintFind = '', '', 'title="' + Controller.HintFind + '"')+'><font face="webdings">' + chr($7E) + '</font></BUTTON>&nbsp;';

    if (Controller.IndicatorType = itRecordNr) then
    begin
      ctrltext := ctrltext + '&nbsp;' + Format(Controller.IndicatorFormat,[RowOffset + 1, FNumRows]);
    end;

    if (Controller.IndicatorType = itRecordFromTo) then
    begin
      if ((RowOffset + FRowCount) < FNumRows) then
        ctrltext := ctrltext + '&nbsp;' + Format(Controller.IndicatorFormat,[RowOffset + 1,RowOffset+FRowCount, FNumRows])
      else
        ctrltext := ctrltext + '&nbsp;' + Format(Controller.IndicatorFormat,[RowOffset + 1,FNumRows, FNumRows])
    end;

    if (Controller.IndicatorType = itPageNr) then
    begin
      ctrltext := ctrltext + '&nbsp;' + Format(Controller.IndicatorFormat,
        [(RowOffset div RowCount) + 1, ((FNumRows - 1) div RowCount) + 1]);
    end;
  end;

  if ctrltext = '' then
    ctrltext := '&nbsp;';

  Result := Result + FontToTag(Controller.Font,ctrltext);

  case Controller.Alignment of
    taCenter: Result := Result + '</p>';
    taRightJustify: Result := Result + '</p>';
  end;

  if Controller.RowCountSelect then
  begin
    if Controller.RowCountSelectLabelBefore <> '' then
      rcselbef := FontToTag(Controller.Font,'&nbsp;' + Controller.RowCountSelectLabelBefore + '&nbsp;')
    else
      rcselbef := '&nbsp;&nbsp;';

    if Controller.RowCountSelectLabelAfter <> '' then
      rcselaft := FontToTag(Controller.Font,'&nbsp;' + Controller.RowCountSelectLabelAfter)
    else
      rcselaft := '';

    Result := Result + rcselbef +'<SELECT' + ' id="'+HTMLName+'rcs" onChange=RowCountChange('+HTMLName+'Obj,this)>';
    for i := 1 to Controller.RowCountValues.Count do
    begin
      Result := Result + '<OPTION VALUE="'+Controller.RowCountValues.Strings[i - 1]+'"';

      try
        if StrToInt(Controller.RowCountValues.Strings[i - 1]) = RowCount then
          Result := Result + ' SELECTED';
      except
      end;

      Result := Result + '>' + Controller.RowCountValues.Strings[i - 1];
    end;
    Result := Result + '</SELECT>' + rcselaft;
  end;

  if not isAsync then
  begin
    Result := Result + '</TD></TR>';

    Result := Result + '</TABLE></TD></TR>';
  end;

end;

function TTIWCustomWebGrid.GetCurrentRecord: integer;
begin
  Result := 0;
end;

procedure TTIWCustomWebGrid.Invalidate;
begin
  inherited;
end;

{$WARNINGS ON}

{$IFDEF TMSIW6}
function TTIWCustomWebGrid.RenderString(Master: Boolean; AContext: TIWBaseComponentContext): string;
{$ELSE}
function TTIWCustomWebGrid.RenderString(Master: Boolean): string;
{$ENDIF}
var
  s, he, colprop, hover, colhdr, colsortcolor, coltitle, temp: string;
  ACellValue, ACellURL, ACellHint, subm, psubm, tmp: string;
  DivE,DivPC, submitclick, idBE, idBP, idBC, dispE, dispPC: string;
  InplaceEdits, ch, chkrow, ridx,cidx,ridxj,cidxj: string;
  newcell, newrow, TabIndex, coldisplay, pwd: string;
  WidthStyle, HeightStyle, EditHeightStyle, EditWidthStyle, CellStyle: string;
  EditID, FirstEdit, DetailRow, DetailValue, img1, CRPar: string;
  i, j, k, l, m: Integer;
  AImageIdx, WidthCell, WidthTable: Integer;
  Err, RowsOnPage, MaxID, RowsToDo: Integer;
  TotColWidth, GridWidth, GridHeight: Integer;
//ticks: integer;
  ACellFont,  ACellDetailFont: TIWFont;
  ACellColor, ABorderColor: TIWColor;
  ACellAlign: TAlignment;
  Tempval: double;
  bmp: TBitmap;
  EditableCell, EnabledCell, ShowNode: Boolean;
  OldAdapt, isIE, displaysort, found: boolean;
  IWHTMLTag: TIWHTMLTag;
  DG: TTIWCustomWebGrid;
  coltype: TTIWColumnType;
  coleditor: TTIWColumnEditor;
  coldynedit: TTIWDynEditType;
  //ParentComponent: TComponent;

  function VAlignStyle(VAlign: TTIWVAlign): string;
  begin
    Result := '';
    case VAlign of
      vaTop: Result := ' vertical-align:top;';
      vaBottom: Result := 'vertical-align:bottom;';
      vaMiddle: Result := 'vertical-align:middle;';
    end;
  end;

  function MakeFormulas(DoDyn: Boolean): string;
  var
    c: Integer;
    s: string;
    funcsel: string;
  begin
//    s := '<SCRIPT Language="JavaScript">'#13;
    s := '';

    if DoDyn then
    s := s
    + 'function ' + FIDS + 'DynInit() {'
      + 'for(di=0;di<' + IntToStr(RowsOnPage) + ';di++) {'#13
      + '' + FIDS + 'DynaEditUpdate(null,0,di,-1); }'#13
      + '}'#13;

    // partial update issue
    //outputdebugstring(pchar('rows on page = ' + inttostr(rowsonpage)));

    s := s
    + 'function ' + FIDS + 'PartialDynInit() {'
      + 'for(di=0;di<' + IntToStr(RowsOnPage) + ';di++) {'#13
      + ' + IWTop().'+FIDS + 'DynaEditPartialUpdate(null,0,di,-1); }'#13
      + '}'#13;

    s := s
   + 'function ' + FIDS + 'ScrollInit() {'
      + IIF(Scroll.Persistent and (Scroll.Style <> scNever),'document.getElementById("'
        +HTMLNAME+'div1").scrollTop = ' + IntToStr(FScrollPos)+';'#13,'')
      + IIF(Scroll.Persistent and (Scroll.Style <> scNever),'document.getElementById("'
        +HTMLNAME+'div1").scrollLeft = ' + IntToStr(FScrollLeft)+';'#13,'')
      + '}'#13

    + 'function ' + FIDS + 'FocusInit(ctrl) {'#13
      //temp async change
//      + ' el =  document.getElementById(ctrl);'#13
//      + ' if (el != null) {'#13
//      + ' el.focus();'#13
//      + IIF(FEditSelectAll, ' el.select();'#13, '')
//      + ' }'#13
      + '}'#13;

    if DoDyn then
    begin
    s := s
    + 'function ' + FIDS + 'DynaEditDone(ctrl,c,r,event) {'#13
      + ClientEvents.DynEditDone.Text + #13
      + FIDS + 'DynaEditUpdate(ctrl,c,r,-1);'#13
      + '}'#13

      + 'function ' + FIDS + 'DynaEditUpdate(ctrl,c,r,sel,event) {'#13

      + '  if ( (! isIE) && (ctrl) )'#13
      + '  {'#13
      + '    if (ctrl.value.lastIndexOf("-") > 0)'#13
      + '    {'#13
      + '      ctrl.value = WGtempval;'#13
      + '    }'#13
      + '  }'#13

      //+ 'if (sel == 0) {'#13
      //+ ClientEvents.DynEditChange.Text + #13
      //+' }'#13
      + 'if (sel == 1) {'#13
      + ClientEvents.DynComboChange.Text + #13
      +' }'#13
      + 'if (sel == 2) {'#13
      + ClientEvents.DynCheckClick.Text + #13
      +' }'#13

      + ' if (event){'#13
      {$IFDEF TMSIW6}
      + IIF((AContext.WebApplication.Browser = brIE),'if (event.keyCode == 40) NextEdit('+HTMLName+'Obj,c,r);'#13,'')
      + IIF((AContext.WebApplication.Browser = brIE),'if (event.keyCode == 38) PrevEdit('+HTMLName+'Obj,c,r);'#13,'')
      + IIF((AContext.WebApplication.Browser = brIE),'if ((event.keyCode == 13) && '+ IIF(AdvanceOnReturn,'(1>0)','(1<0)')+')' + FIDS + 'NextEdit(c,r);'#13,'')
      {$ELSE}
      + IIF((WebApplication.Browser = brIE),'if (event.keyCode == 40) NextEdit('+HTMLName+'Obj,c,r);'#13,'')
      + IIF((WebApplication.Browser = brIE),'if (event.keyCode == 38) PrevEdit('+HTMLName+'Obj,c,r);'#13,'')
      + IIF((WebApplication.Browser = brIE),'if ((event.keyCode == 13) && '+ IIF(AdvanceOnReturn,'(1>0)','(1<0)')+')' + FIDS + 'NextEdit(c,r);'#13,'')
      {$ENDIF}
      + '}'#13;

    for c := 1 to Columns.Count do
    begin
      if Columns[c - 1].ColumnType in [ctDynEdit, ctNormal, ctNoWrap, ctDynText,
        ctDynCombo, ctDynCheckBox, ctDynMemo] then
      begin
        case Columns[c - 1].ColumnType of
          ctDynEdit, ctDynCombo:
            s := s + 'CS' + IntToStr(c - 1) + ' = document.getElementById("' +
              FIDS + 'D"+r+"C' + IntToStr(c - 1) + '").value.replace("' + DecimalPoint + '", ".");'#13;
          ctNormal, ctNoWrap, ctDynText, ctDynMemo:
            s := s + 'CS' + IntToStr(c - 1) + ' = document.getElementById("' +
              FIDS + 'D"+r+"C' + IntToStr(c - 1) + '").innerHTML.replace("' + DecimalPoint + '", ".");'#13;
          ctDynCheckBox:
            begin
              s := s + 'if (document.getElementById("' + FIDS + 'D"+r+"C' +
                IntToStr(c - 1) + '").checked == true)'#13;
              s := s + 'C' + IntToStr(c - 1) + ' = 1;'#13;
              s := s + 'else C' + IntToStr(c - 1) + ' = 0;'#13;
            end;
        end;
        if (Columns[c - 1].ColumnType in [ctDynEdit, ctDynCombo, ctNormal, ctNoWrap, ctDynText, ctDynMemo]) then
        begin
          s := s + 'if ((CS' + IntToStr(c - 1)+' == "-") || (CS' + IntToStr(c - 1)+' == "")) C' + IntToStr(c - 1) + ' = 0; else C'+ IntToStr(c - 1) + ' = 1*CS'+IntToStr(c - 1)+'; '#13;
        end;
      end;
    end;
    for c := 1 to Columns.Count do                          
    begin
      if (Columns[c - 1].ColumnType in [ctDynText]) then
      begin
        if Columns[c - 1].Formula <> '' then
        begin
          s := s + 'var tempres = ' + Columns[c - 1].Formula + ';'#13;
          s := s + 'var fmtres = FormatNum('+ HTMLName + 'Obj, tempres,' + IntToStr(Columns[c - 1].DynPrecision)+',"' + DecimalPoint + '");'#13;
          s := s + 'SetElText('+HTMLName+'Obj, "' + FIDS + 'D"+r+"C' + IntToStr(c - 1) + '",fmtres);'#13
        end;
      end;
    end;                                                          

    if ShowFooter then
    begin
      s := s + ' if ((ctrl != null) | (r == ' + IntToStr(RowsOnPage - 1) +
        ')) {'#13;
      for c := 1 to Columns.Count do
      begin
        if (Columns[c - 1].ColumnType in [ctDynEdit, ctDynCombo, ctDynCheckBox, ctDynMemo])
          then
          funcsel := 'E'
        else
          funcsel := '';

        case Columns[c - 1].FooterType of
          ftDynSum: s := s + 'tempres = ColumnSum' + FuncSel + '('+HTMLName+'Obj,' +
            IntToStr(c - 1) + ');'#13;
          ftDynAvg: s := s + 'tempres = ColumnAvg' + FuncSel + '('+HTMLName+'Obj,' +
            IntToStr(c - 1) + ');'#13;
          ftDynMin: s := s + 'tempres = ColumnMin' + FuncSel + '('+HTMLName+'Obj,' +
            IntToStr(c - 1) + ');'#13;
          ftDynMax: s := s + 'tempres = ColumnMax' + FuncSel + '('+HTMLName+'Obj,' +
            IntToStr(c - 1) + ');'#13;
        end;

        if (Columns[c - 1].FooterType in [ftDynSum, ftDynAvg, ftDynMin,
          ftDynMax]) then
          s := s + 'SetElText('+HTMLName+'Obj,"' + FIDS + 'F' + IntToStr(c - 1) + '","' + Columns[c - 1].FooterText + '" + FormatNum('+ HTMLName + 'Obj, tempres,' +
            IntToStr(Columns[c - 1].DynPrecision) + ',"' + DecimalPoint + '"));'#13

        end;
      s := s + '}'#13;
    end;

    s := s + 'if (ctrl != null) {'#13;
    s := s + '  if (sel == 2) DynaCheck('+HTMLName+'Obj,ctrl,r,c);'#13;
    s := s + '  else DynaEdit('+HTMLName+'Obj,ctrl,r,c); }'#13;
    s := s + '}'#13;
    end;

    s := s + 'function ' + FIDS + 'DynaEditPartialUpdate(ctrl,c,r,sel) {'#13;

    for c := 1 to Columns.Count do
    begin
      if Columns[c - 1].ColumnType in [ctDynEdit, ctNormal, ctNoWrap, ctDynText,
        ctDynCombo, ctDynCheckBox, ctDynMemo] then
      begin
        case Columns[c - 1].ColumnType of
          ctDynEdit, ctDynCombo:
            s := s + 'C' + IntToStr(c - 1) + ' = 1*IWTop().document.getElementById("' +
              FIDS + 'D"+r+"C' + IntToStr(c - 1) + '").value;'#13;
          ctNormal, ctNoWrap, ctDynText, ctDynMemo:
            s := s + 'C' + IntToStr(c - 1) + ' = 1*IWTop().document.getElementById("' +
              FIDS + 'D"+r+"C' + IntToStr(c - 1) + '").innerHTML;'#13;

          ctDynCheckBox:
            begin
              s := s + 'if (IWTop().document.getElementById("' + FIDS + 'D"+r+"C' +
                IntToStr(c - 1) + '").checked == true)'#13;
              s := s + 'C' + IntToStr(c - 1) + ' = 1;'#13;
              s := s + 'else C' + IntToStr(c - 1) + ' = 0;'#13;
            end;

        end;
      end;
    end;

    for c := 1 to Columns.Count do
    begin
      if (Columns[c - 1].ColumnType in [ctDynText]) then
      begin
        if Columns[c - 1].Formula <> '' then
        begin
          s := s + 'var tempres = ' + Columns[c - 1].Formula + ';'#13;
          s := s + 'var fmtres = IWTop().FormatNum('+ HTMLName + 'Obj, tempres,' + IntToStr(Columns[c - 1].DynPrecision)+',"' + DecimalPoint + '");'#13;
          s := s + 'IWTop().SetElText('+HTMLName+'Obj, "' + FIDS + 'D"+r+"C' + IntToStr(c - 1) + '",fmtres);'#13
        end;
      end;
    end;

    if ShowFooter then
    begin
      s := s + ' if ((ctrl != null) | (r == ' + IntToStr(RowsOnPage - 1) +
        ')) {'#13;
      for c := 1 to Columns.Count do
      begin
        if (Columns[c - 1].ColumnType in [ctDynEdit, ctDynCombo, ctDynCheckBox, ctDynMemo])
          then
          funcsel := 'E'
        else
          funcsel := '';

        case Columns[c - 1].FooterType of
          ftDynSum: s := s + 'tempres = IWTop().ColumnSum' + FuncSel + '('+HTMLName+'Obj,' +
            IntToStr(c - 1) + ');'#13;
          ftDynAvg: s := s + 'tempres = IWTop().ColumnAvg' + FuncSel + '('+HTMLName+'Obj,' +
            IntToStr(c - 1) + ');'#13;
          ftDynMin: s := s + 'tempres = IWTop().ColumnMin' + FuncSel + '('+HTMLName+'Obj,' +
            IntToStr(c - 1) + ');'#13;
          ftDynMax: s := s + 'tempres = IWTop().ColumnMax' + FuncSel + '('+HTMLName+'Obj,' +
            IntToStr(c - 1) + ');'#13;
        end;

        if (Columns[c - 1].FooterType in [ftDynSum, ftDynAvg, ftDynMin,
          ftDynMax]) then
          begin
          s := s + 'IWTop().SetElText('+HTMLName+'Obj,"' + FIDS + 'F' + IntToStr(c - 1) + '","' + Columns[c - 1].FooterText + '" + FormatNum('+ HTMLName + 'Obj, tempres,' +
            IntToStr(Columns[c - 1].DynPrecision) + ', "' + DecimalPoint + '"));'#13
          end;
        end;
      s := s + '}'#13;
    end;
    s := s + 'if (ctrl != null) {'#13;
    s := s + '  if (sel == 2) IWTop().DynaCheck('+HTMLName+'Obj,ctrl,r,c);'#13;
    s := s + '  else IWTop().DynaEdit('+HTMLName+'Obj,ctrl,r,c); }'#13;
    s := s + '}'#13;



    //Result := s + '</SCRIPT>';
    Result := s;
  end;

  function GetNode(row: integer; proc: string): string;
  var
    img1, img2: string;
  begin
    if Nodes.NodeOpenURL <> EmptyStr then
      img1 := ImageHTML(Nodes.NodeOpenURL, 0, 0, False, Nodes.HintOpen).Render()
    else
      img1 := OutputPic('RGEXP', FNodes.FNodeOpen, False, FNodes.HintOpen);

    if Nodes.NodeClosedURL <> EmptyStr then
      img2 := ImageHTML(Nodes.NodeClosedURL, 0, 0, False, Nodes.HintClosed).Render()
    else
      img2 := OutputPic('RGCOL', FNodes.FNodeClosed, False, FNodes.HintClosed);

    Result := '';
    Result := Result + '<span onclick="' + Proc + '('+HTMLName+'Obj,' + IntToStr(row) +
      ')" style="cursor:pointer;cursor:hand">';

    if (DetailRowShow = dsAllOpen) or (DetailStates[RowOffset + Row - 1]) then
      Result := Result + '<div id="' + FIDS + 'NOE' + IntToStr(row) +
        '" style="display:none">' + img1 + '</div><div id="' + FIDS + 'NOC' +
        IntToStr(row) + '" style="display:">' + img2 + '</div>'
    else
      Result := Result + '<div id="' + FIDS + 'NOE' + IntToStr(row) +
        '" style="display:">' + img1 + '</div><div id="' + FIDS + 'NOC' +
        IntToStr(row) + '" style="display:none">' + img2 + '</div>';

    Result := Result + '</span>';                             
  end;

  function GetCheck(row, col: integer; proc: string; checked: Boolean): string;
  var
    img1, img2: string;                                                     
  begin
    if CheckFalsePictureURL <> EmptyStr then
      img1 := ImageHTML(CheckFalsePictureURL, 0, 0, false, '').Render()
    else
      img1 := OutputPIC('GRCKOFF', FCheckFalsePicture, False, '');

    if CheckTruePictureURL <> EmptyStr then
      img2 := ImageHTML(CheckTruePictureURL, 0, 0, false, '').Render()
    else
      img2 := OutputPIC('GRCKON', FCheckTruePicture, False, '');

    Result := '';
    Result := Result + '<span onclick="' + Proc + '('+HTMLName+'Obj,' + IntToStr(row) +
    {$IFDEF TMSIW9}
      ',' + IntToStr(col) + ','+HTMLControlImplementation.IWCLName+')" style="cursor:pointer;cursor:hand">';
    {$ELSE}
      ',' + IntToStr(col) + ','''')" style="cursor:pointer;cursor:hand">';
    {$ENDIF}
    Result := Result + '<div id="' + FIDS + 'CKT' + IntToStr(row) +
      '" style="display:' + IIF(checked, '', 'none') + '">' + img1 +
      '</div>';
    Result := Result + '<div id="' + FIDS + 'CKF' + IntToStr(row) +
      '" style="display:' + IIF(checked, 'none', '') + '">' + img2 +
      '</div>';
    Result := Result + '</span>';
  end;

  function GetImageCheck(row, col: integer; checked: Boolean): string;
  var
    img: string;
  begin
    if checked then
    begin
      if CheckTruePictureURL <> EmptyStr then
        img := ImageHTML(CheckTruePictureURL, 0, 0, false, '').Render()
      else
        img := OutputPIC('GRCKON', FCheckTruePicture, False, '');
      end
    else
    begin
      if CheckFalsePictureURL <> EmptyStr then
        img := ImageHTML(CheckFalsePictureURL, 0, 0, false, '').Render()
      else
        img := OutputPIC('GRCKOFF', FCheckFalsePicture, False, '');
    end;

    Result := img;
  end;

  function EditorToString(editor: TTIWColumnEditor): string;
  begin
    case editor of
      edNone: result :='None';
      edEdit: result := 'Edit';
      edPassword: result := 'Password';
      edCombo: result := 'Combo';
      edMemo: result := 'Memo';
      edCheckbox: result := 'CheckBox';
      edEditNumeric: result := 'Numeric';
      edEditFloat: result := 'Float';
      edEditLower: result := 'Lower';
      edEditUpper: result := 'Upper';
      edEditHex: result := 'Hex';
      edDatePicker: result := 'DatePicker';
      edSpinEdit: result := 'Spin';
      edPopupEdit: result := 'Popup';
    end;
  end;

  function ColumnTypeToString(columntype: TTIWColumnType): string;
  begin
    case columntype of
      ctNormal: result := 'Normal';
      ctCheckbox: result := 'CheckBox';
      ctButton: result := 'Button';
      ctRowIndicator: result := 'RowIndicator';
      ctRowNumber: result := 'RowNumber';
      ctScroll: result := 'Scroll';
      ctPopup: result := 'Popup';
      ctLink: result := 'Link';
      ctLinkField: result := 'LinkField';
      ctLinkRowNumber: result := 'LinkRowNumber';
      ctDataCheckbox: result := 'DataCheckBox';
      ctImage: result := 'Image';
      ctDataImage: result := 'DataImage';
      ctURL: result := 'URL';
      ctEmail: result := 'Email';
      ctDataButton: result := 'DataButton';
      ctRadioButton: result := 'RadioButton';
      ctDynEdit: result := 'DynEdit';
      ctDynText: result := 'DynText';
      ctDynMemo: result := 'DynMemo';
      ctDynCombo: result := 'DynCombo';
      ctDynCheckBox: result := 'DynCheckBox';              
      ctNode: result := 'Node';
      ctPassword: result := 'Password';
      ctProgress: result := 'Progress';
      ctPopupImage: result := 'PopupImage';
      ctImageCheckBox: result := 'ImageCheckBox';
      ctDataImageCheckBox: result := 'DataImageCheckBox';
      ctNoWrap: result := 'NoWrap';
    end;
  end;


  function MakeScript: string;
  var
    c: Integer;
    ColSpec, CellSpec, ColType, ColEdit, ColCheck, ColWidth: string;
    ColColor: TIWColor;
    ColFontColor: TIWColor;
    colsizemove: string;

  begin

    ColSpec := '';
    ColType := '';
    ColEdit := '';
    CellSpec := '';
    ColWidth := '';

    for c := 1 to Columns.Count do
    begin

      ColType := ColType + 'this.coltype[' + IntToStr(c - 1) + '] = "' + ColumnTypeToString(Columns[c - 1].ColumnType) + '"'#13;
      ColEdit := ColEdit + 'this.coledit[' + IntToStr(c - 1) + '] = "' + EditorToString(Columns[c - 1].Editor) + '"'#13;
      ColCheck := ColCheck + 'this.colchecktrue[' + IntToStr(c - 1) + '] = "' + Columns[c - 1].CheckTrue + '"'#13;
      ColCheck := ColCheck + 'this.colcheckfalse[' + IntToStr(c - 1) + '] = "' + Columns[c - 1].CheckFalse + '"'#13;
      ColWidth := ColWidth + 'this.colwidth[' + IntToStr(c - 1) + '] = "' + IntToStr(Columns[c - 1].Width) + '"'#13;

      if Columns[c - 1].Color = clNone then
      begin
        if Color = clNone then
          ColSpec := ColSpec + 'this.columncolors[' + inttostr(c - 1) + '] = "#ffffff"'#13
        else
          ColSpec := ColSpec + 'this.columncolors[' + inttostr(c - 1) + '] = "'+HTMLClr(Color)+'"'#13
      end
      else
      begin
        ColColor := Columns[c - 1].Color;
        ColSpec := ColSpec + 'this.columncolors[' + inttostr(c - 1) + '] = "' + HTMLClr(ColColor) + '"'#13;
      end;
                
      if Columns[c - 1].Font.Color = clNone then           
      begin                                                  
        if Font.Color = clNone then                
          ColFontColor := clBlack
        else
          ColFontColor := Font.Color;            
      end
      else
        ColFontColor := Columns[c - 1].Font.Color;
                                                                 
      ColSpec := ColSpec + 'this.coltextcolors[' + inttostr(c - 1) + '] = "' + HTMLClr(ColFontColor) + '"'#13;

    end;

    for c := 1 to RowsOnPage do
    begin
      if RowSelect[c - 1 + RowOffset] then
        CellSpec := CellSpec + 'this.cellstate[' + inttostr(c - 1) + '] = "1"'#13
      else
        CellSpec := CellSpec + 'this.cellstate[' + inttostr(c - 1) + '] = "0"'#13;

      if DetailStates[c - 1 + RowOffset] then
        CellSpec := CellSpec + 'this.detailstate[' + inttostr(c - 1) + '] = "1"'#13
      else
        CellSpec := CellSpec + 'this.detailstate[' + inttostr(c - 1) + '] = "0"'#13;

    end;

//    Result := '<SCRIPT Language="JavaScript">'#13;
    Result := '';

    //start colsizemove
    colsizemove :=
      ' obj = ' + HTMLName + 'Obj'#13
      + ' if (ie)'#13
    	+ '  nval = obj.event.x - obj.szw'#13
      + ' else'#13
    	+ '  nval = e.pageX - obj.szw'#13
      + '  newval = obj.origval + parseInt(nval);'#13
      + '  if (newval <= 0)'#13
      + '    newval = obj.origval;'#13

      + 'if (ie)'#13
      + '  document.selection.empty();'#13
      + 'if (navigator.appName == "Netscape")'#13
      + '  window.getSelection().removeAllRanges();'#13
      ;

    if (RowCount = 0) and (RowsOnPage > 0) then
    begin
      colsizemove := colsizemove + ' obj.rcount = 1;'#13;
    end;

    colsizemove := colsizemove
      + '    if (!document.styleSheets) return;'#13
      + '   var i;'#13
      + '   for (i = 0; i <= document.styleSheets.length ; i++)'#13
      + '   {'#13
      + '    if (document.styleSheets[i].title == "' + HTMLName + 'nowrapcol")'#13
      + '      break;'#13
      + '   }'#13
      + '    var mycss = new Array();'#13
      + '    if (document.styleSheets[i].cssRules)  // Mozilla'#13
      + '       mycss = document.styleSheets[i].cssRules;'#13
      + '    else'#13
      + '       mycss = document.styleSheets[i].rules;  // IE'#13

      + '    if (newval > 5)'#13
      + '      mycss[obj.mvc - 1].style.width = newval - 5;'#13
      + '    else'#13
      + '      mycss[obj.mvc - 1].style.width = 1;'#13

//      + '  for(i=1;i <= obj.rcount;i++) {'#13
      + '    s = obj.fids + "c" + obj.mvc + "r" + 1;'#13
      + '    document.getElementById(s).width = newval;'#13
//      + '  }'#13

      + '    sh = obj.fids + "CH" + obj.mvc;'#13
      + '    document.getElementById(sh).style.width = newval;'#13
      + '    document.getElementById(sh).firstChild.style.width = newval;'#13

      + '    var mg = document.getElementById(obj.fids + "mg");'#13
//      + '    if ((obj.origwidth + parseInt(nval)) <= 0){'#13
      + '      mg.width = obj.origwidth + parseInt(nval);'#13
      + '      mg.firstChild.width = mg.width;'#13
      + '      mg.firstChild.firstChild.width = obj.origfullwidth + parseInt(nval);'#13
//      + '    } else {'#13
//      + '      mg.width = 1;'#13
//      + '      mg.width = parseInt(obj.origwidth) - sbw;'#13
//      + '      mg.firstChild.width = mg.width;'#13
//      + '      mg.firstChild.firstChild.width = mg.width;'#13
//      + '    }'#13

      + '    var div3 = document.getElementById(obj.id + "div3");'#13
      + '    if (div3)'#13
      + '      div3.firstChild.width = mg.width;'#13
      ;
    //end colsizemove

    chkrow := '-1';
    if MouseSelect in [msSingleRowCheck, msRowCheck] then
    begin
      for c := 1 to RowsOnPage do
        if RowSelect[c - 1 + RowOffset] then
          chkrow := inttostr(c);
    end;

    //cached javascript object
    Result := Result
      + 'function '+HTMLName+'Obj(){'#13
      + '  this.id = "'+HTMLName+'";'#13
      + '  this.fids = "'+FIDS+'";'#13
      + '  this.hasdynedits = '+ IIF(HasDynEdits, 'true', 'false')+';'#13
      + '  this.pcol = "' + IIF(FBands.Active, HTMLClr(FBands.PrimaryColor), HTMLClr(Color)) + '"'#13
      + '  this.stcol = "' + IIF(Font.Color = clNone, HTMLClr(clBlack), HTMLClr(Font.Color)) + '"'#13
      + '  this.scol = "' + IIF(FBands.Active, HTMLClr(FBands.SecondaryColor), HTMLClr(Color)) + '"'#13
      + '  this.bands = ' + IIF(FBands.Active, 'true', 'false') + #13;

    if (ActiveRowColor = clNone) then    
      Result := Result
        + '  this.activerowcolor = ""'#13
    else
      Result := Result
        + '  this.activerowcolor = "' + HTMLClr(ActiveRowColor) + '"'#13;

    Result := Result
      + '  this.activerowfontcolor = "' + HTMLClr(ActiveRowFontColor) + '"'#13
      + '  this.myEl = ""'#13                                                                  
      + '  this.colchecktrue = new Array(' + inttostr(Columns.Count) + ')'#13
      + '  this.colcheckfalse = new Array(' + inttostr(Columns.Count) + ')'#13
      + '  this.coltype = new Array(' + inttostr(Columns.Count) + ')'#13
      + '  this.coledit = new Array(' + inttostr(Columns.Count) + ')'#13
      + '  this.columncolors = new Array(' + inttostr(Columns.Count) + ')'#13
      + '  this.colwidth = new Array(' + inttostr(Columns.Count) + ')'#13      
      + '  this.coltextcolors = new Array(' + inttostr(Columns.Count) + ')'#13
//      + '  this.holdcolumncolors = new Array(' + inttostr(Columns.Count) + ')'#13
//      + '  this.holdcoltextcolors = new Array(' + inttostr(Columns.Count) + ')'#13
      + '  this.cellstate = new Array(' + inttostr(RowsOnPage) + ')'#13
      + '  this.detailstate = new Array(' + inttostr(RowsOnPage) + ')'#13
      + '  this.szw = 0;'#13
      + '  this.event = null;'#13
      + '  this.mvc = 0;'#13
      + '  this.newval = 0;'#13
      + '  this.origval = 0;'#13
      + '  this.origwidth = -1;'#13
      + '  this.origfullwidth = -1'#13
      + '  this.rcount = ' + inttostr(rowcount) + ';'#13               
      + '  this.selcol = -1;'#13
      + '  this.selrow = -1;'#13
      + '  this.seledit = ""'#13
      + '  this.editcol = -1'#13
      + '  this.editrow = -1'#13
      + '  this.checkrow = '+chkrow+#13
      + '  this.origval = ""'#13
      + '  this.focusel = null;'#13
      + '  this.ccount = ' + IntToStr(columns.Count) + ';'#13
      + '  this.scrollpos = ' + IntToStr(FScrollPos) + ';'#13
      + '  this.scrollleft = ' + IntToStr(FScrollLeft) + ';'#13
      + '  this.scrollintoview = ' + IIF(Scroll.ScrollIntoView, 'true', 'false') + ';'#13
      + '  this.pageoffset = ' + IntToStr(FPageOffset) + ';'#13
      + '  this.rowoffset = ' + IntToStr(RowOffset) + ';'#13
      + '  this.rowsonpage = ' + IntToStr(RowsOnPage) + ';'#13
      + '  this.decimalpoint = ' + IntToStr(Ord(FDecimalPoint)) + ';'#13
      + '  this.showselect = ' + IIF(ShowSelect, 'true', 'false') + ';'#13
      + '  this.curpage = '+IntToStr(FPage)+';'#13
      + '  this.selectcolor = "' + HTMLClr(SelectColor) + '";'#13
      + '  this.selectfontcolor = "' + HTMLClr(SelectFontColor) + '";'#13
      + '  this.hovercolor = "' + HTMLClr(HoverColor) + '";'#13
      + '  this.hoverfontcolor = "' + HTMLClr(HoverFontColor) + '";'#13
      + '  this.fontcolor = "' + HTMLClr(Font.Color) + '";'#13
      + '  this.oncheckclick = ' + IIF(Assigned(OnCheckClick), 'true', 'false') + ';'#13
      + '  this.onimageclick = ' + IIF(Assigned(OnImageClick), 'true', 'false') + ';'#13      
      + '  this.onbuttonclick = ' + IIF(Assigned(OnButtonClick), 'true', 'false') + ';'#13
      + '  this.onlinkclick = ' + IIF(Assigned(OnLinkClick), 'true', 'false') + ';'#13
      + '  this.oncombochange = ' + IIF(Assigned(OnComboChange), 'true', 'false') + ';'#13
      + '  this.onnodeclose = ' + IIF(Assigned(OnNodeClose), 'true', 'false') + ';'#13
      + '  this.onnodeopen = ' + IIF(Assigned(OnNodeOpen), 'true', 'false') + ';'#13
      + '  this.onvalueclick = ' + IIF(Assigned(OnValueClick), 'true', 'false') + ';'#13
      + '  this.oncellclick = ' + IIF(Assigned(OnCellClick), 'true', 'false') + ';'#13
      {$IFDEF TMSIW9}
      + '  this.onasynccellclick = ' + IIF(Assigned(OnAsyncCellClick), 'true', 'false') + ';'#13
      + '  this.onasyncbuttonclick = ' + IIF(Assigned(OnAsyncButtonClick), 'true', 'false') + ';'#13
      + '  this.onasynccheckclick = ' + IIF(Assigned(OnAsyncCheckClick), 'true', 'false') + ';'#13
      + '  this.onasyncrowselect = ' + IIF(Assigned(OnAsyncRowSelect), 'true', 'false') + ';'#13
      + '  this.onasyncactiverowmove = ' + IIF(AsyncActiveRowMove, 'true', 'false') + ';'#13
      + '  this.onasyncimageclick = ' + IIF(Assigned(OnAsyncImageClick), 'true', 'false') + ';'#13
      + '  this.onasynclinkclick = ' + IIF(Assigned(OnAsyncLinkClick), 'true', 'false') + ';'#13
      + '  this.onasynccombochange = ' + IIF(Assigned(OnAsyncComboChange), 'true', 'false') + ';'#13
      + '  this.onasyncedit = ' + IIF( (Assigned(OnAsyncEdit)), 'true', 'false') + ';'#13
      + '  this.onasynceditdone = ' + IIF( (Assigned(OnAsyncEditDone) or Assigned(FOnAsyncValidate)), 'true', 'false') + ';'#13
      {$ENDIF}
      + '  this.showrowheader = ' + IIF(RowHeader.FShowRowHeader, 'true', 'false') + ';'#13
      + '  this.showcolheader = ' + IIF(FShowColumnHeader, 'true', 'false') + ';'#13
      + '  this.showfooter = ' + IIF(FShowFooter, 'true', 'false') + ';'#13
      + '  this.autoedit = ' + IIF(AutoEdit, 'true', 'false') + ';'#13
      + '  this.advanceonreturn = ' + IIF(AdvanceOnReturn, 'true', 'false') + ';'#13
      + '  this.scrollpersistent = ' + IIF(Scroll.Persistent, 'true', 'false') + ';'#13
      + '  this.editselectall = ' + IIF(EditSelectAll, 'true', 'false') + ';'#13
      + HTMLName + 'Obj.prototype.colsizemove = function(e) {'+#13+colsizemove+#13'}'#13
      + HTMLName + 'Obj.prototype.clientgridkeydown = function(obj,c,r,event) {'+#13+ClientEvents.GridKeyDown.Text+#13'}'#13
      + HTMLName + 'Obj.prototype.clientcheckclick = function(obj,c,r) {'+#13+ClientEvents.CheckClick.Text+#13'}'#13
      + HTMLName + 'Obj.prototype.clientimageclick = function(obj,c,r,s) {'+#13+ClientEvents.ImageClick.Text+#13'}'#13
      + HTMLName + 'Obj.prototype.clientbuttonclick = function(obj,c,r,s) {'+#13+ClientEvents.ButtonClick.Text+#13'}'#13
      + HTMLName + 'Obj.prototype.clienteditchange = function(obj,ctrl,c,r) {'+#13+ClientEvents.EditChange.Text+#13'}'#13
      + HTMLName + 'Obj.prototype.clientdyneditchange = function(obj,ctrl,c,r) {'+#13+ClientEvents.DynEditChange.Text+#13'}'#13
      + HTMLName + 'Obj.prototype.clienteditdone = function(obj,ctrl,c,r) {'+#13+ClientEvents.EditDone.Text+#13'}'#13
      + HTMLName + 'Obj.prototype.clientcombochange = function(obj,ctrl,c,r) {'+#13+ClientEvents.ComboChange.Text+#13'}'#13
      + HTMLName + 'Obj.prototype.clientnodeclick = function(obj,r) {'+#13+ClientEvents.NodeClick.Text+#13'}'#13
      + HTMLName + 'Obj.prototype.clienthoverrow = function(obj,r) {'+#13+ClientEvents.HoverRow.Text+#13'}'#13
      + HTMLName + 'Obj.prototype.clientcellclick = function(obj,c,r) {'+#13+ClientEvents.CellClick.Text+#13'}'#13
      + HTMLName + 'Obj.prototype.clientpopupeditok = function(obj,ctrl, cellid, c, r) {'+#13+ClientEvents.PopupEditOk.Text+#13'}'#13
      + HTMLName + 'Obj.prototype.clientpopupeditcancel = function(obj,ctrl,c,r) {'+#13+ClientEvents.PopupEditCancel.Text+#13'}'#13
      + '';

    if RowCount > 0 then
      Result := Result + '  this.maxpages = '+IntToStr((FNumRows - 1) div RowCount + 1)+';'#13
    else
      Result := Result + '  this.maxpages = 1;'#13;

    Result := Result + ColSpec + CellSpec + ColType + ColEdit + ColCheck + ColWidth;

    if MouseSelect = msEdit then
      Result := Result + '  this.mouseselect = "msEdit";'#13;
    if DetailRowShow = dsOneOpen then
      Result := Result + '  this.detailrowshow = "dsOneOpen";'#13
    else if DetailRowShow = dsServerOneOpen then
      Result := Result + '  this.detailrowshow = "dsServerOneOpen";'#13
    else if DetailRowShow = dsServerOpen then
      Result := Result + '  this.detailrowshow = "dsServerOpen";'#13;

    if Scroll.Style = scNever then
      Result := Result + '  this.scrollstyle = "scNever"'#13
    else if Scroll.Style = scAlways then
      Result := Result + '  this.scrollstyle = "scAlways"'#13
    else
      Result := Result + '  this.scrollstyle = "scAuto"'#13;

    if dState = gsEdit then
      Result := Result + '  this.dstate = "gsEdit"'#13
    else if dState = gsInsert then
      Result := Result + '  this.dstate = "gsInsert"'#13;

 //cached javascript object end
    Result := Result
      + '}'#13
      + HTMLName + 'Obj = new '+HTMLName+'Obj();'#13;

    Result := Result
     +  'function '+ HTMLname +'sbwidth(){ '#13

     // only calculate wgw1 & wgw2 once per rendering
     // to avoid problem with Scroll.Persistent in FF with more than 1 grid on the form
     // see ScrollInit
     // vars declared in advwebgrid.js file
     {
     + ' if ((!wgw1) || (!wgw2)){'#13
     + '	document.body.className = "without";'#13
     + '	wgw1 = document.body.clientWidth;'#13
     + ' 	document.body.className = "with";'#13
     + ' 	wgw2 = document.body.clientWidth;'#13
     + ' }
     //'#13
     //+ ''#13

//     + '	var sbw = wgw1 - wgw2;'#13
     + '  if (sbw == -1)'#13
     + '	  sbw = getScrollBarWidth();'#13
     + ''#13
     + ''#13

     + '  var div3 = document.getElementById("'+ HTMLName +'div3");'#13#13

     + IIF ((Scroll.Style <> scNever) and FShowColumnHeader and not HasPercCols,
        '	var divw = parseInt(div3.style.width) - sbw;'#13,'')

     + IIF ((Scroll.Style <> scNever) and FShowColumnHeader and not HasPercCols, '	div3.style.width = divw;'#13,'')
     + ''#13

//     + IIF ((Scroll.Style <> scNever) and RowHeader.FShowRowHeader and not HasPercCols,
//        '	div3.style.width = parseInt(div3.style.width) - ' + IntToStr(RowHeader.FRowHeaderWidth) + ';'#13,'')
//     + ''#13

     + IIF ((Scroll.Style <> scNever) and FShowColumnHeader and not HasPercCols,
        '	document.getElementById("'+ HTMLName +'div0").width = divw;'#13,'')
     + ''#13

     + IIF ((Scroll.Style <> scNever) and FShowFooter and not HasPercCols, '	var divw = document.getElementById("'
        + HTMLName +'div4").style.width.substr(0,document.getElementById("'
        + HTMLName +'div4").style.width.length-2) - sbw;'#13,'')

     + IIF ((Scroll.Style <> scNever) and FShowFooter and not HasPercCols, '	document.getElementById("'+ HTMLName +'div4").style.width = divw;'#13,'')
     + ''#13

     + IIF ((Scroll.Style <> scNever) and RowHeader.FShowRowHeader and not HasPercCols, '	var divw = document.getElementById("'
        + HTMLName +'div2").style.height.substr(0,document.getElementById("'
        + HTMLName +'div2").style.height.length-2) - sbw;'#13,'')
     + IIF ((Scroll.Style <> scNever) and RowHeader.FShowRowHeader and not HasPercCols, '	document.getElementById("'+ HTMLName +'div2").style.height = divw;'#13,'')

     + '}'#13;

//    Result := Result
//      + '</SCRIPT>';
  end;

  function MakeValidates: string;
  var
    c: Integer;
    tmp: string;
    ajaxcall, submitcall: string;
  begin
//    tmp := '<SCRIPT>'#13
    tmp := #13
      + 'function ' + FIDS + 'PostValidate(sel) {'#13
      + 'submval = FindElem('#39 + HTMLName + #39').value;'#13
      + 's_ar= submval.split("|");'#13;

    for c := 1 to Columns.Count do
    begin
      if Columns[c - 1].RequiredMsg <> '' then
      begin
        tmp := tmp + 'if ((s_ar[' + IntToStr(c + 1) + '] == "") | (s_ar[' +
          IntToStr(c + 1) + '] == "&nbsp;")) {'#13
          + 'alert("' + Columns[c - 1].RequiredMsg + '");'#13
          + 'return(0);}'#13
      end;
    end;

    ajaxcall := '';
    submitcall := 'return SubmitClick('#39 + HTMLName + #39','#39 +
      'PostRow'#39'+sel);'#13;

    {$IFDEF TMSIW9}
    if (AsyncEdit) then
    begin
      ajaxcall := 'processAjaxEvent(''onPost'', '
        + HTMLControlImplementation.IWCLName
        + ',''' + HTMLName + '.' + 'DoAsyncPost' + ''','
        + 'true' + ', null, '
        + 'true' + ');';

      submitcall := '';

      Acontext.WebApplication.RegisterCallBack(HTMLName+'.DoAsyncPost', DoAsyncPost);

//      tmp := tmp + 'GAPost(submval,'+HTMLName+'Obj,'+IntToStr(FEditRow)+');'#13;

    end;
    {$ENDIF}

    tmp := tmp + ajaxcall + submitcall

    + '}'#13;
//      + '</SCRIPT>';
    Result := tmp;
  end;

  function EncodeLF(s: string): string;
  begin
    s := StringReplace(s, #13, '\n', [rfReplaceAll]);
    s := StringReplace(s, #10, '', [rfReplaceAll]);
    s := StringReplace(s, '"', '&#034;', [rfReplaceAll]);
    Result := s;
  end;

  function MakeAlign(AAlignment: TAlignment): string;
  begin
    Result := '';
    case AAlignment of
      taRightJustify: Result := ' style="text-align:right;"';
      taCenter: Result := ' style="text-align:center;"';
    end;
  end;

  function GetColWidths(StartCol, NumCol: Integer): string;
  var
    k, res: Integer;
  begin
    res := 0;
    for k := StartCol to StartCol + NumCol do
    begin
      if k < Columns.Count then
        res := res + Columns[k].Width; // + Borders.Width;
    end;

    case Columns[StartCol].WidthType of
      wtAbsolute: Result := IntToStr(res) + 'px';
      wtPercent: Result := IntToStr(res) + '%';
    end;
  end;

begin
  MaxID := ID;
  NumDetails := 0;

  Result := '';
  InplaceEdits := '';

//ticks := gettickcount;

  {$IFDEF TMSIW6}
  isIE := AContext.WebApplication.Browser = brIE;
  {$ELSE}
  isIE := WebApplication.Browser = brIE;
  {$ENDIF}

  FisIE := isIE;

  if not FSelectPersistent then
    ClearRowSelect;

  // Calculation of different sizes in the grid

  TotCoLWidth := 0;

  // Count total width of columns
  for i := 1 to Columns.Count do
  begin
    if Columns[i - 1].Visible then
      TotColWidth := TotColWidth + Columns[i - 1].Width;
  end;

  //if (Scroll.Style = scNever) and not HasPercCols then
  // Width of the control
  // GridWidth := TotColWidth;

  if UseFullWidth then
  begin
    GridWidth := Width;
    if StretchColumn = -1 then
      TotColWidth := Width;
  end
  else
  begin
    if not HasPercCols then
      Width := TotColWidth;

    if (Scroll.Style = scNever) then
      GridWidth := GetTableWidth(true)
    else
      GridWidth := GetTableWidth(true) + 18;

    TotColWidth := GridWidth;

    Width := GridWidth;
  end;

  if RowHeader.Show then
    GridWidth := Width - RowHeader.Width;

  GridHeight := Height;
  if (Controller.Position <> cpNone) then
     GridHeight := GridHeight - Controller.Height - Controller.Borders.Width;
  if (Controller.Position = cpBoth) then
     GridHeight := GridHeight - Controller.Height - Controller.Borders.Width;
  if ShowColumnHeader then
     GridHeight := GridHeight - 22 - ColumnHeaderBorders.Width;
  if ShowFooter then
     GridHeight := GridHeight - 22 - FooterBorders.Width;
  if OuterBorder.Show then
     GridHeight := GridHeight - 1;

  s := '';
  he := '';

  FirstEdit := '';

  // prepare selected rows return
  for i := 0 to Columns.Count do
    s := s + '0';

  // prepare edit return
  for i := 0 to Columns.Count + 2 do
    s := s + '|';

  // init. static column calc
  for i := 1 to Columns.Count do
    Columns[i - 1].CalcValue := 0;

  // proc to get hidden submit input
  subm := 'FindElem(''' + HTMLName + ''').value="' + s + '";' + EOL;

  psubm := 'IWTop().FindElem(''' + HTMLName + ''').value="' + s + '";' + EOL;

  if RenderPrepare then
  begin
    dState := GetGridState;

    ACellFont := TIWFont.Create;
    ACellDetailFont := TIWFont.Create;    

    GetRowInfo(FNumRows, FRowOffset, FPageOffset);

    while (RowOffset > FNumRows) do
    begin
      if RowOffset >= RowCount then
        RowOffset := RowOffset - RowCount;
    end;

    if RowCount > 0 then
      FPage := (self.RowOffset div RowCount)
    else
      FPage := 0;

    if RowCount = 0 then
      RowsOnPage := FNumRows
    else
    begin
      if (RowCount + RowOffset <= FNumRows) then
        RowsOnPage := RowCount
      else
        RowsOnPage := FNumRows - RowOffset;
    end;

    {$IFDEF TMSDEBUG}
    outputdebugstring(pchar('ROWS ON PAGE = ' + inttostr(RowsOnPage)));
    {$ENDIF}

    //    s := MakeFormulas(HasDynEdits) + MakeScript + MakeValidates;
    s := '';

    // start grid outer table
    //nowrap columntype width in css
    s := s + #13'<STYLE type="text/css" title="'+HTMLName+'nowrapcol">'#13;

    for i := 1 to Columns.Count do                             
    begin
      s := s + '.' + HTMLName + 'nowrapc' + IntToStr(i - 1) + ' { overflow:hidden;width:'
      + IntToStr(Columns[i - 1].Width-4-1) + 'px;height:'
      + IntToStr(DefaultRowHeight-4-1) + 'px; }'#13;
    end;

    s := s + '.without { overflow:hidden; } .with { }'#13'</STYLE>';

    {$IFDEF TMSIW7}
    if (AContext.WebApplication.Browser <> brIE) and (MouseSelect = msEdit) then
    {$ELSE}
    if (WebApplication.Browser <> brIE) and (MouseSelect = msEdit) then
    {$ENDIF}
    begin

      j := 0;

      for i := 1 to Columns.Count do
      begin
        if Columns[i - 1].Editor <> edNone then
        begin
          j := i - 1;
          break;
        end;
      end;

      {$IFDEF TMSIW9}
      //hidden link
      s := s + '<a href="#" onfocus="return editclick('+HTMLName+'Obj,'+IntToStr(j)+',0,-1,'
        + HTMLControlImplementation.IWCLName + ')" autocomplete="off" tabindex="0" style="width:0;height:0;"></a>';
      s := s + '<INPUT type="INPUT" autocomplete="off" style="width:10;height:10;visibility:hidden;" id="'
        +HTMLName+'hi" onkeydown="return tablekey('+HTMLName+'Obj,event,'+HTMLControlImplementation.IWCLName+');">';
      {$ELSE}
      //hidden link
      s := s + '<a href="#" onfocus="return editclick('+HTMLName+'Obj,'+IntToStr(j)
         +',0,-1)" autocomplete="off" tabindex="0" style="width:0;height:0;"></a>';
      s := s + '<INPUT type="INPUT" autocomplete="off" style="width:10;height:10;visibility:hidden;" id="'
        +HTMLName+'hi" onkeydown="return tablekey('+HTMLName+'Obj,event,'''');">';
      {$ENDIF}
    end;

    // main grid outer table                                                                         
    if HasPercCols then
      s :=  s + '<TABLE id="'+HTMLName+'div0" cellpadding="0" cellspacing="0" border="0" width="100%">'
    else
      s :=  s + '<TABLE id="'+HTMLName+'div0" cellpadding="0" cellspacing="0" border="0">';

    // controller in top row span
    if (Controller.Position in [cpTop,cpBoth]) and not (RowCount = 0) then
      s := s + GetController(isIE,false,true);

    ch := '';

    // column header row
    if FShowColumnHeader then
    begin
       ch := ch + '<TR>';

      // rowheader top empty cell
      if (RowHeader.FShowRowHeader) and (Scroll.Style <> scNever) then
      begin
        ch := ch + '<TD width="' + IntToStr(RowHeader.FRowHeaderWidth)+'"';

        ch := ch + CellColor(RowHeader.Color,RowHeader.Gradient1,RowHeader.Gradient2,RowHeader.GradientDirection);

        if (HeaderStyle = hsRaised) then
        {$IFDEF TMSIW7}
          ch := ch + RaisedStyle(AContext);
        {$ELSE}
          ch := ch + RaisedStyle;
        {$ENDIF}
        ch := ch + '">&nbsp;</TD>';
      end;

      // column header cells
      if Scroll.Style <> scNever then
      begin
        ch := ch + '<TD style="background:'+ HTMLClr(ColumnHeaderColor) +';">';
//        ch := ch + '<DIV id="'+HTMLName+'div3" style="height:';
        ch := ch + '<DIV id="'+HTMLName+'div3" style="';

        {// let header always autosize
        if HasSubTitles then
          ch := ch + IntToStr(DefaultRowHeight*2)
        else
          ch := ch + IntToStr(DefaultRowHeight);
         }

        ch := ch + 'width:';                          

        if HasPercCols then
        begin
          ch := ch + '100%';
        end
        else
        begin
          if (RowHeader.FShowRowHeader) then
//            ch := ch +IntToStr(GridWidth - RowHeader.FRowHeaderWidth)+'px'
            ch := ch +IntToStr(Width - RowHeader.FRowHeaderWidth)+'px'
          else
//            ch := ch +IntToStr(GridWidth)+'px';
            ch := ch +IntToStr(Width)+'px';
        end;

        ch := ch + ';overflow:hidden;">';

        ch := ch + '<TABLE id="' + HTMLName + '_" border="' + IntToStr(FColumnHeaderBorders.Width) +
          '" cellpadding="' + IntToStr(FColumnHeaderBorders.Padding) +
          '" cellspacing="' + IntToStr(FColumnHeaderBorders.Spacing) + '"';

        case FColumnHeaderBorders.FInner of
        ibColumns: ch := ch + ' RULES="cols"';
        ibRows: ch := ch + ' RULES="rows"';
        ibNone: ch := ch + ' RULES="none"';
        end;

        case FColumnHeaderBorders.FOuter of
        obVertical: ch := ch + ' FRAME="vsides"';
        obHorizontal: ch := ch + ' FRAME="hsides"';
        obNone: ch := ch + ' FRAME="void"';
        end;

        if FColumnHeaderBorders.FColor <> clNone then
          ch := ch + ' bordercolor="' + HTMLClr(FColumnHeaderBorders.FColor) + '"';

        if FColumnHeaderBorders.FColorLight <> clNone then
          ch := ch + ' bordercolorlight="' + HTMLClr(FColumnHeaderBorders.FColorLight) + '"';

        if FColumnHeaderBorders.FColorDark <> clNone then
          ch := ch + ' bordercolordark="' + HTMLClr(FColumnHeaderBorders.FColorDark) + '"';

        if FColumnHeaderBorders.FCollapsed then
          ch := ch + ' style="border-collapse:collapse;"';

        if HasPercCols or (StretchColumn <> -1) then
          WidthTable := Width
        else
          WidthTable := GetTableWidth(true);

        if ((StretchColumn <> -1 ) and (GridWidth > TotColWidth )) or HasPercCols then
          ch := ch + ' width="100%"'
        else
          ch := ch + ' width="'+IntToStr(WidthTable)+'px"';

        {//let header always autosize
        ch := ch + ' height="';

        if HasSubTitles then
          ch := ch + IntToStr(DefaultRowHeight*2)
        else
          ch := ch + IntToStr(DefaultRowHeight);
         }
        ch := ch + '">';

//        ch := ch + '<TR style="height:'+IntToStr(DefaultRowHeight)+'px">';
//autosize
        ch := ch + '<TR>';

      end;

      j := 1;

      while j <= Columns.Count do
      begin
        ch := ch + '<TD id="'+FIDS+'CH'+inttostr(j)+'" valign="top" ' + HTMLColor(ColumnHeaderColor, 'bgcolor');

        CellStyle :=  VAlignStyle(Columns[j - 1].TitleVAlign);

        if (Columns[j - 1].TitleSpan > 1) then
          ch := ch + ' COLSPAN="' + IntToStr(Columns[j - 1].TitleSpan) + '"';

        if (Columns[j - 1].TitleRowSpan) and HasSubTitles then
          ch := ch + ' ROWSPAN="2"';

        if isIE then
        begin
          if (Columns[j - 1].ColumnHeaderGradient1 <> clNone) and
            (Columns[j - 1].ColumnHeaderGradient2 <> clNone) then
          begin
            ch := ch + GradientStyle(Columns[j - 1].ColumnHeaderGradient1,Columns[j - 1].ColumnHeaderGradient2,Columns[j - 1].ColumnHeaderGradientDirection);
          end
          else
          begin
            ch := ch + ' style="';
          end;
        end
        else
        begin
          ch := ch + ' style="';
        end;

        if Columns[j - 1].ColumnHeaderGradient1 <> clNone then
          ch := ch + 'background-color:' + HTMLClr(Columns[j - 1].ColumnHeaderGradient1)
        else
          ch := ch + 'background-color:' + HTMLClr(ColumnHeaderColor);

        WidthStyle := '';

        WidthCell := Columns[j - 1].Width;

        if Columns[j - 1].TitleSpan > 1 then
        begin
          for i := 2 to Columns[j - 1].TitleSpan do
          begin
            if (j - 1 + i - 1 < Columns.Count) then
            begin
              WidthCell := WidthCell + Columns[j - 1 + i - 1].Width;
              WidthCell := WidthCell + ColumnHeaderBorders.Padding;
              WidthCell := WidthCell + ColumnHeaderBorders.Padding;
              WidthCell := WidthCell + ColumnHeaderBorders.Spacing;
              WidthCell := WidthCell + ColumnHeaderBorders.Width;
              if not ColumnHeaderBorders.Collapsed then
                WidthCell := WidthCell + ColumnHeaderBorders.Width;
            end;
          end;
        end;

        if ((j - 1) = StretchColumn) and (GridWidth > TotColWidth) then
	   WidthStyle := 'width:' + IntToStr(GridWidth - TotColWidth + WidthCell) + 'px;'
        else
        begin
          if (Columns[j - 1].Width <> 0) then
          begin
            case Columns[j - 1].WidthType of
              wtAbsolute: WidthStyle := 'width:' + IntToStr(WidthCell) + 'px;';
              wtPercent: WidthStyle := 'width:' + IntToStr(WidthCell) + '%;';
            end;
          end;
        end;

        if (HeaderStyle = hsRaised) then
        {$IFDEF TMSIW7}
          CellStyle := Cellstyle + RaisedStyle(AContext);
        {$ELSE}
          CellStyle := Cellstyle + RaisedStyle;
        {$ENDIF}

        if not Columns[j - 1].Visible then
          CellStyle := CellStyle + ';display:none;';

        if CellStyle <> '' then
          ch := ch + CellStyle + WidthStyle;

       	ch := ch + '"';

        if ((j - 1) = StretchColumn) and (GridWidth > TotColWidth) then
           WidthStyle := ' style="width:' + IntToStr(GridWidth - TotColWidth) + 'px;'
        else
        begin
          if (Columns[j - 1].Width <> 0) then
          begin
            case Columns[j - 1].WidthType of
            wtAbsolute: WidthStyle := ' style="width:' + IntToStr(WidthCell) + 'px;';
            //wtPercent: WidthStyle := ' style="width:' + IntToStr(WidthCell) + '%;';
            wtPercent: WidthStyle := ' style="width:100%"';
            end;
          end;
        end;

        ch := ch + '><div '+WidthStyle+'overflow:hidden;"><TABLE border="0" cellpadding="0" cellspacing="0" width="100%" style="';

        case Columns[j - 1].ColumnHeaderAlignment of
          taRightJustify: ch := ch + 'text-align:right;';
          taCenter: ch := ch + 'text-align:center;';
        end;

        ch := ch + '"><TR><TD>';

        // s := s + IntToStr(WidthCell);

        // ' style="width:'+inttostr(Columns[j - 1].Width)+'px"

        colhdr := '';
        coltitle := GetColumnTitle(j - 1);
        colsortcolor := HTMLClr(Columns[j - 1].Font.Color);
        if (colsortcolor = '') then
          colsortcolor := HTMLClr(Font.Color);
        if ( ((Columns[j - 1].ColumnHeaderClick) or (SortSettings.Show and Columns[j - 1].CanSort)) ) and (coltitle <> '') and not HasSubTitles then
        begin
           coltitle := '<a href="#" style="color:'+HTMLClr(Columns[j - 1].Font.Color)+';" onclick="GAColClick('
                  + HTMLName+'Obj, ' + IntToStr(j - 1) + ', '
                  {$IFDEF TMSIW9}
                  + HTMLControlImplementation.IWCLName + ', '
                  + IIF((AsyncSorting or Assigned(OnAsyncColumnHeaderClick)),'true','false') + ');'
                  {$ELSE}
                  + ''''', false);'
                  {$ENDIF}
                  + '">'
                 + coltitle + '</a>';
        end;

        if (coltitle = '') then
          coltitle := '&nbsp;';

        if (Columns[j - 1].Filter) and not HasSubTitles then
        begin
          coltitle := '<SELECT' + WidthStyle + '" onChange=FilterChange('+HTMLName+'Obj,this,' + InttoStr(j - 1) + ')>';
          for k := 1 to Columns[j - 1].FilterList.Count do
          begin
            coltitle := coltitle + '<OPTION VALUE="' + Columns[j - 1].FilterList.Strings[k - 1] + '"';

            if k - 1 = Columns[j - 1].FilterIndex then
              coltitle := coltitle + ' SELECTED';
            coltitle := coltitle + '>' + Columns[j - 1].FilterList.Strings[k - 1];
          end;
          coltitle := coltitle + '</SELECT>';
        end;

        if (Columns[j - 1].ColumnHeaderCheckBox) and not HasSubTitles then
        begin
          if RowCount = 0 then
            RowsToDo := FNumRows
          else
            RowsToDo := RowCount;

          found := true;
          for i := 1 to RowsToDo do                                                           
          begin
            if not RowSelect[i - 1 + RowOffset] then
              found := false;
          end;

          coltitle := '<INPUT TYPE="CHECKBOX" onclick="CheckAll('+HTMLName+'Obj,this,'
            + IntToStr(j - 1) + ','
            {$IFDEF TMSIW9}
                + HTMLControlImplementation.IWCLName
            {$ELSE}
                + ''''
            {$ENDIF}
            + ')"' + IIF(found, 'checked ', '') + ' id="' + HTMLName + 'CHALL'
            + IntToStr(j - 1) + '">';
        end;

        if (Columns[j - 1].ColumnHeaderNode) and not HasSubTitles then
        begin
          coltitle := GetNode(0, 'ToggleAll');
        end;       

        colhdr := colhdr + coltitle;

        if SortSettings.Show and (SortSettings.Column = j - 1) and not
          HasSubTitles then
          displaysort := true
        else
          displaysort := false;

          if (SortSettings.Ascending.Empty or SortSettings.Descending.Empty)
          and ((SortSettings.AscendingURL = EmptyStr) or (SortSettings.DescendingURL = EmptyStr)) then
          begin
            if SortSettings.Direction = sdAscending then
              colhdr := colhdr + '<font face="webdings" id="' + HTMLName
              + 'SIND' + IntToStr(j - 1) + '" '
              + IIF(displaysort, '', 'style="display:none;"') + '>'+chr($35)+'</font>'
            else
              colhdr := colhdr + '<font face="webdings" id="' + HTMLName
              + 'SIND' + IntToStr(j - 1) + '" '
              + IIF(displaysort, '', 'style="display:none;"') + '>'+chr($36)+'</font>';
          end
          else
          begin

             if displaysort then
             begin
               colhdr := colhdr + '<span id="' + HTMLName +'SINDASC" style="display:none;">';

               if SortSettings.AscendingURL <> EmptyStr then
                colhdr := colhdr + ImageHTML(SortSettings.AscendingURL, 0, 0, False, '').Render()
               else
                colhdr := colhdr + OutputBmp('ASC', SortSettings.Ascending, False, '');

               colhdr := colhdr + '</span>'
               + '<span id="' + HTMLName +'SINDDESC" style="display:none;">';

               if SortSettings.DescendingURL <> EmptyStr then
                colhdr := colhdr + ImageHTML(SortSettings.DescendingURL, 0, 0, False, '').Render()
               else
                colhdr := colhdr + OutputBmp('DES', SortSettings.Descending, False, '');

               colhdr := colhdr + '</span>';
             end;
                                                                  
            if SortSettings.Direction = sdAscending then
            begin
              if SortSettings.AscendingURL <> EmptyStr then
                colhdr := colhdr + ' <span id="' + HTMLName
                + 'SIND' + IntToStr(j - 1) + '" '
                + IIF(displaysort, '', 'style="display:none;"') + '>'
                + ImageHTML(SortSettings.AscendingURL, 0, 0, False, '').Render()
                + '</span>'
              else
                colhdr := colhdr + ' <span id="' + HTMLName
                + 'SIND' + IntToStr(j - 1) + '" '
                + IIF(displaysort, '', 'style="display:none;"') + ' >'
                + OutputBmp('ASC', SortSettings.Ascending, False, '')
                + '</span>';
            end
            else
            begin
              if SortSettings.DescendingURL <> EmptyStr then
                colhdr := colhdr + ' <span id="' + HTMLName
                + 'SIND' + IntToStr(j - 1) + '" '
                + IIF(displaysort, '', 'style="display:none;"') + '>'
                + ImageHTML(SortSettings.DescendingURL, 0, 0, False, '').Render()
                + '</span>'
              else
                colhdr := colhdr + ' <span id="' + HTMLName
                + 'SIND' + IntToStr(j - 1) + '" '
                + IIF(displaysort, '', 'style="display:none;"') + '>'
                + OutputBmp('DES', SortSettings.Descending, False, '')
                + '</span>';
            end;
          end;
//        end;

	      if FontUsed(Columns[j - 1].ColumnHeaderFont) then
          ch := ch + FontToTag(Columns[j - 1].ColumnHeaderFont,colhdr)
        else if FontUsed(ColumnHeaderFont) then
          ch := ch + FontToTag(ColumnHeaderFont,colhdr)
        else
          ch := ch + FontToTag(Font,colhdr);

        ch := ch + '</TD>';

        if Columns[j - 1].AllowSizing and ColumnSizing and (Columns[j - 1].WidthType = wtAbsolute) and not HasSubTitles then
          ch := ch + '<TD style="cursor:e-resize;width:2px" onmousedown="'
             + 'colsizedwn('+HTMLName+'Obj,' + inttostr(j) + ',event)"></TD>';

        ch := ch + '</TR></TABLE></div>';
        ch := ch + '</TD>';

        if (Columns[j - 1].TitleSpan > 1) then
          j := j + Columns[j - 1].TitleSpan
        else
          inc(j);
                                       
      end;                     
                                   
      ch := ch + '</TR>';                                                                                                         
    end;                                     

    {$IFDEF TMSIW7}
    if (AContext.WebApplication.Browser = brIE) and (MouseSelect = msEdit) then
    {$ELSE}
    if (WebApplication.Browser = brIE) and (MouseSelect = msEdit) then
    {$ENDIF}
    begin

    j := 0;

    for i := 1 to Columns.Count do
    begin
      if Columns[i - 1].Editor <> edNone then
      begin
        j := i - 1;
        break;
      end;
    end;

    {$IFDEF TMSIW9}
    //hidden link
    s := s + '<a href="#" id="'+FIDS+'hl" onfocus="return editclick('+HTMLName+'Obj,'+IntToStr(j)
      +',0,-1,' + HTMLControlImplementation.IWCLName + ')" autocomplete="off" tabindex="0" style="width:0;height:0;"></a>';
    {$ELSE}
    //hidden link
    s := s + '<a href="#" id="'+FIDS+'hl" onfocus="return editclick('+HTMLName+'Obj,'+IntToStr(j)
      +',0,-1)" autocomplete="off" tabindex="0" style="width:0;height:0;"></a>';
    {$ENDIF}
    end;

    // column header with subtitles
    if FShowColumnHeader and HasSubTitles then
    begin
      ch := ch + '<TR style="height:22px">';

      j := 1;
                                                                                                                                  
      while (j <= Columns.Count) do
      begin
        //s := s + '<TD'+HTMLColor(ColumnHeaderColor,'bgcolor')+'><TABLE border="0" cellpadding="0" cellspacing="0" width="100%"><TR><TD>';

        if (Columns[j - 1].TitleRowSpan) then
        begin
          inc(j);
          Continue;
        end;

        ch := ch + '<TD ' + HTMLColor(ColumnHeaderColor, 'bgcolor');

        CellStyle := VAlignStyle(Columns[j - 1].SubTitleVAlign);

        if (Columns[j - 1].SubTitleSpan > 1) then
          ch := ch + ' COLSPAN="' + IntToStr(Columns[j - 1].SubTitleSpan) + '"';

        with Columns[j - 1] do
        if (ColumnHeaderGradient1 <> clNone) and
           (ColumnHeaderGradient2 <> clNone) then
          ch := ch + GradientStyle(ColumnHeaderGradient1,ColumnHeaderGradient2,ColumnHeaderGradientDirection)
        else
          ch := ch + ' style="';

        if (HeaderStyle = hsRaised) then
        {$IFDEF TMSIW7}
          ch := ch + RaisedStyle(AContext);
        {$ELSE}
          ch := ch + RaisedStyle;
        {$ENDIF}

        // s := s+ ' style="FILTER: alpha(opacity=255,style=0);"';

        WidthStyle := '';

        WidthCell := Columns[j - 1].Width;

        if Columns[j - 1].SubTitleSpan > 1 then
        begin
          for i := 2 to Columns[j - 1].SubTitleSpan do
          begin
            if (j - 1 + i - 1 < Columns.Count) then
            begin
              WidthCell := WidthCell + Columns[j - 1 + i - 1].Width;
              WidthCell := WidthCell + ColumnHeaderBorders.Padding;
              WidthCell := WidthCell + ColumnHeaderBorders.Padding;
              WidthCell := WidthCell + ColumnHeaderBorders.Spacing;
              WidthCell := WidthCell + ColumnHeaderBorders.Width;
              if not ColumnHeaderBorders.Collapsed then
                WidthCell := WidthCell + ColumnHeaderBorders.Width;
            end;
          end;
        end;

        if (Columns[j - 1].Width <> 0) then
        begin
          case Columns[j - 1].WidthType of
            wtAbsolute:
              WidthStyle := ' width:' + inttostr(WidthCell) + 'px';
            wtPercent:
              WidthStyle := ' width:' + inttostr(WidthCell) + '%';
          end;
        end;

        if not Columns[j - 1].Visible then           
        begin
          if CellStyle <> '' then
            CellStyle := CellStyle + ';';
          CellStyle := CellStyle + 'display:none;';
        end;

        ch := ch + CellStyle + '' + WidthStyle + ';"';

        ch := ch + '><TABLE border="0" cellpadding="0" cellspacing="0" width="100%" ';

        case Columns[j - 1].ColumnHeaderAlignment of
          taRightJustify: ch :=  ch + 'style="text-align:right"';
          taCenter: ch :=  ch + 'style="text-align:center"';
        end;

        ch := ch + '><TR><TD>';

        // ' style="width:'+inttostr(Columns[j - 1].Width)+'px"

        colhdr := '';
        {
        case Columns[j - 1].ColumnHeaderAlignment of
          taRightJustify: colhdr := '<p align="right">';
          taCenter: colhdr := '<p align="center">';
        end;
        }

        coltitle := Columns[j - 1].SubTitle;

        if (Columns[j - 1].ColumnHeaderClick) and (coltitle <> '') then
        begin
          coltitle := '<a href="#" onclick="GAColClick('
                  + HTMLName+'Obj, ' + IntToStr(j - 1) + ', '
                  {$IFDEF TMSIW9}
                  + HTMLControlImplementation.IWCLName + ', '
                  + IIF((AsyncSorting or Assigned(OnAsyncColumnHeaderClick)),'true','false') + ');'
                  {$ELSE}
                  + ''''', false);'
                  {$ENDIF}
                  + '">' + coltitle + '</a>';
        end;

        if (coltitle = '') then
          coltitle := '&nbsp;';

        if (Columns[j - 1].ColumnHeaderCheckBox) then
        begin
          coltitle := '<INPUT TYPE="CHECKBOX" onclick=CheckAll('+HTMLName+'Obj,this,'
            + IntToStr(j - 1) + ')>';
        end;

        if (Columns[j - 1].ColumnHeaderNode) then
        begin
          coltitle := GetNode(0, 'ToggleAll');
        end;

        if Columns[j - 1].Filter then
        begin
          coltitle := '<SELECT style="' + WidthStyle + '" onChange=FilterChange('+HTMLName+'Obj,this,' + InttoStr(j - 1) + ')>';
          for k := 1 to Columns[j - 1].FilterList.Count do
          begin
            coltitle := coltitle + '<OPTION VALUE="' + Columns[j - 1].FilterList.Strings[k - 1] + '"';

            if k - 1 = Columns[j - 1].FilterIndex then
              coltitle := coltitle + ' SELECTED';
            coltitle := coltitle + '>' + Columns[j - 1].FilterList.Strings[k -
              1];
          end;
          coltitle := coltitle + '</SELECT>';
        end;

        colhdr := colhdr + coltitle;

        if SortSettings.Show and (SortSettings.Column = j - 1) then
        begin  
          if SortSettings.Direction = sdAscending then
          begin
            if SortSettings.AscendingURL <> EmptyStr then
              colhdr := colhdr + ImageHTML(SortSettings.AscendingURL, 0, 0, False, '').Render()
            else
              colhdr := colhdr + OutputBmp('ASC', SortSettings.Ascending, False, '')
          end
          else
          begin
            if SortSettings.DescendingURL <> EmptyStr then
              colhdr := colhdr + ImageHTML(SortSettings.DescendingURL, 0, 0, False, '').Render()
            else
            colhdr := colhdr + OutputBmp('DES', SortSettings.Descending, False, '');
          end;
        end;

        {
        if (Columns[j - 1].ColumnHeaderAlignment <> taLeftJustify) then
          colhdr := colhdr + '</P>';
          }

        if FontUsed(ColumnHeaderFont) then
          ch := ch + FontToTag(ColumnHeaderFont,colhdr)
        else
          ch := ch + FontToTag(Font,colhdr);

        ch := ch + '</TD>';

        if Columns[j - 1].AllowSizing and ColumnSizing and (Columns[j -
          1].WidthType = wtAbsolute) then
          ch := ch + '<TD style="cursor:e-resize;width:2px" onmousedown="'
            + 'colsizedwn('+HTMLName+'Obj,' + inttostr(j) + ',event)"></TD>';

        ch := ch + '</TR></TABLE></TD>';

        if (Columns[j - 1].SubTitleSpan > 1) then
          j := j + Columns[j - 1].SubTitleSpan
        else
          inc(j);

      end;
      ch := ch + '</TR>';

      // fix up col widths when col spans are used
      if HasColSpans then
      begin
        ch := ch + '<TR style="height:0px">';
        j := 1;

        while j <= Columns.Count do
        begin
          WidthStyle := '';
          if (Columns[j - 1].Width <> 0) then
          begin
            case Columns[j - 1].WidthType of
              wtAbsolute:
                WidthStyle := ' style="width:' + inttostr(Columns[j - 1].Width) + 'px"';
              wtPercent:
                WidthStyle := ' style="width:' + inttostr(Columns[j - 1].Width) + '%"';
            end;
          end;

          ch := ch + '<TD '+WidthStyle+'></TD>';
          inc(j);
        end;

        ch := ch + '</TR>';
      end;
    end;

    if Scroll.Style <> scNever then
    begin
      s := s + ch;

      if ShowColumnHeader then
      begin
        s := s + '</TABLE>';

        if (Scroll.Style <> scNever) then
          s := s + '</DIV>';

        s := s + '</TD></TR>';
      end;
    end;

    if UseFullHeight or (DefaultRowHeight = 0) then
    begin
      s := s  + '<TR height="' + IntToStr(GridHeight) +'px">'
    end
    else
    begin
      if (DefaultRowHeight <> 0) and (RowCount <> 0) and UseFullHeight then
        s := s + '<TR height="' + IntToStr(RowCount * DefaultRowHeight)+'px">'
      else
        s := s + '<TR>';
    end;

    // row header body
    if (RowHeader.FShowRowHeader) then
    begin
      // row header content
      if RowCount = 0 then
        RowsToDo := FNumRows
      else
        RowsToDo := RowCount;

      {$IFDEF TMSIW7}
      s := s + GetRowHeader(RowsTodo,GridHeight,RaisedStyle(AContext));
      {$ELSE}
      s := s + GetRowHeader(RowsTodo,GridHeight,RaisedStyle);
      {$ENDIF}
    end;                                     
                                          
    // grid body
//    s := s + '<TD tabindex="0" onfocus="return editclick('+HTMLName+'Obj,0,0,-1)" onkeydown="return tablekey('+HTMLName+'Obj, event);" id="'+FIDS+'mg" valign="top"';
    {$IFDEF TMSIW9}
    s := s + '<TD onkeydown="return tablekey('+HTMLName+'Obj, event,'+HTMLControlImplementation.IWCLName+');" id="'+FIDS+'mg" valign="top"';
    {$ELSE}
    s := s + '<TD onkeydown="return tablekey('+HTMLName+'Obj, event,'''');" id="'+FIDS+'mg" valign="top"';
    {$ENDIF}

    if not HasPercCols then                            
    begin                                                     
      s := s + ' width="';

      if (RowHeader.FShowRowHeader) then
        s := s + IntToStr(Width - RowHeader.FRowHeaderWidth) + '"'
      else
        s := s + IntToStr(Width) +'"';
    end;

    s := s + '>';

    if (Scroll.Style <> scNever) then
    begin
      s := s + '<DIV id="'+HTMLName+'div1" onScroll="SyncScroll('+HTMLName+'Obj,this)" style="';

      if UseFullHeight then
         s := s +'height:' + IntToStr(GridHeight)+'px;';

      s := s + 'width:';

      if HasPercCols then
      begin
        s := s + '100%;overflow:';
      end
      else
      begin
//        if (RowHeader.FShowRowHeader) then
//          s := s +IntToStr(GridWidth - RowHeader.FRowHeaderWidth)
//        else
          s := s +IntToStr(GridWidth);

        s := s + 'px;overflow:';
      end;

      if (Scroll.Style = scAlways) then
        s := s + 'scroll;'
      else
        if (Scroll.Style = scAuto) then
          s := s + 'auto;';

      s := s + GetScrollBarStyle(Scroll) + '">';
    end;

    s := s + '<TABLE id="' + HTMLName + '_" border="' +
      IntToStr(FBorders.Width) + '" cellpadding="' + IntToStr(FBorders.Padding) + '" cellspacing="' +
      IntToStr(FBorders.Spacing) + '"';




    if (Background.Gradient1 <> clNone) then
    begin

      if (Background.Gradient2 <> clNone) then
        s := s + GradientStyle(Background.Gradient1,Background.Gradient2,Background.GradientDirection)
      else
        s := s + 'style="';

      s := s + 'background-color:' + ColorToRGBString(Background.Gradient1) + ';';

      //RenderInvisibleControls fix
      if Visible and FBorders.Collapsed then
      //if FBorders.Collapsed then
        s := s + 'border-collapse:collapse;';

      s := s + '"';

    end
    else
    begin

      if Background.PictureURL <> EmptyStr then
         img1 := background.PictureURL
      else if not Background.Picture.Empty then
      begin
        img1 := OutputPic('GRBKG', Background.Picture, False, '');
        delete(img1, 1, 10);

        delete(img1, pos('"', img1), length(img1));
      end;

      if img1 <> EmptyStr then
        s := s + ' background="' + img1 + '" ';

    end;

    case FBorders.FInner of
    ibColumns: s := s + ' RULES="cols"';
    ibRows: s := s + ' RULES="rows"';
    ibNone: s := s + ' RULES="none"';
    end;

    case FBorders.FOuter of
    obVertical: s := s + ' FRAME="vsides"';
    obHorizontal: s := s + ' FRAME="hsides"';
    obNone: s := s + ' FRAME="void"';
    end;

    if FBorders.FColor <> clNone then
      s := s + ' bordercolor="' + HTMLClr(FBorders.FColor) + '"';

    if FBorders.FColorLight <> clNone then
      s := s + ' bordercolorlight="' + HTMLClr(FBorders.FColorLight) + '"';

    if FBorders.FColorDark <> clNone then
      s := s + ' bordercolordark="' + HTMLClr(FBorders.FColorDark) + '"';

    s := s +  ' style="font-size:'+IntToStr(Font.Size)+'pt;color:'+HTMLClr(Font.Color)+';';

    {
    if HasParent then
    begin
      ParentComponent := GetParentComponent;
      OutputDebugString(pchar('parent: ' + ParentComponent.Name));
    end;
    }

    //RenderInvisibleControls fix
    if Visible and FBorders.Collapsed and (Background.Gradient2 = clNone) then
    //if FBorders.Collapsed and (Background.Gradient2 = clNone) then
      s := s + 'border-collapse:collapse;';

    s := s + '"';

    if HasPercCols then
      WidthTable := Width
    else
      WidthTable := GetTableWidth(true);

    if ((StretchColumn <> -1 ) and (GridWidth > TotColWidth)) or HasPercCols then
      s := s + ' width="100%"'
    else
      s := s + ' width="'+IntToStr(WidthTable)+'"';

    s := s + '>';

    if RowCount = 0 then
      RowsToDo := FNumRows
    else
      RowsToDo := RowCount;

    if Scroll.Style = scNever then
      s := s + ch;

    for i := 1 to RowsToDo do
    begin
      ridx := inttostr(i);
      ridxj := inttostr(i - 1);

      if (i - 1 + RowOffset < FNumRows) then
      begin
        if FDefaultRowHeight > 0 then
        begin
          newrow := '<TR height="' + IntToStr(FDefaultRowHeight) + 'px" id="' +
            FIDS + 'row' + ridx + '">'
        end
        else
          newrow := '<TR id="' + FIDS + 'row' + ridx + '">';

        if i = 1 then
        begin
          subm := 'FindElem(''' + HTMLName + ''').value="';
          psubm := 'IWTop().FindElem(''' + HTMLName + ''').value="';
        end;

        if (i - 1 = FPageOffset) then
        begin
          for k := 1 to RowsToDo do
          begin
            if RowSelect[k - 1 + RowOffset] then
            begin
              subm := subm + '1';
              psubm := psubm + '1';
            end
            else
            begin
              subm := subm + '0';
              psubm := psubm + '0';
            end;
          end;
          // encoding = checkbox + radiobutton + scrollpos + detailstate + edit values + dyn. edits
          subm := subm + '|R'+IntToStr(RadioSelection + 1)+'|'+IntToStr(FScrollPos)+'^'+IntToStr(FScrollLeft)+'|x';
          psubm := psubm + '|R'+IntToStr(RadioSelection + 1)+'|'+IntToStr(FScrollPos)+'^'+IntToStr(FScrollLeft)+'|x';
        end;

        DetailRow := '';

        if (DState in [gsEdit, gsInsert]) and (i - 1 = FPageOffset) then
        begin
          if DState = gsEdit then
            DoEdit;

          if DState = gsInsert then
            DoInsert;
        end;

        for j := 1 to Columns.Count do
        begin
          cidx := inttostr(j);
          cidxj := inttostr(j - 1);

          EditableCell := (DState in [gsEdit, gsInsert]) and
            (i - 1 = FPageOffset) and (Columns[j - 1].Editor <> edNone) and
            not (Columns[j - 1].ColumnType in [ctDataButton,ctDynEdit,ctDynText,ctDynCombo,ctDynCheckbox,ctNode, ctDynMemo]);

          if EditableCell and Assigned(OnCanEditCell) then
            OnCanEditCell(Self, i - 1, j - 1, EditableCell);
                                                       
          TabIndex := EmptyStr;
//          if (cidx = '1') and (ridx = '1') then
//          begin
//            TabIndex := 'tabindex="0" onkeydown="return cellkey('+HTMLName+'Obj,event);"';
//            TabIndex := 'tabindex="0"';
//          end;

          colprop := ' '+TabIndex+' id="' + FIDS + 'c' + cidx + 'r' + ridx + '"';

          ACellFont.Assign(Columns[j - 1].Font);
          if ACellFont.FontName = '' then
            ACellFont.FontName := Font.FontName;

          ACellAlign := Columns[j - 1].Alignment;
          ACellColor := Columns[j - 1].Color;

          OldAdapt := AutoHTMLAdapt;

//          if EditableCell then
//            AutoHTMLAdapt := False;

          ACellValue := GetCellData(j - 1, i - 1);

          AutoHTMLAdapt := OldAdapt;

          if (i - 1 = FPageOffset) and (FActiveRowColor <> clNone) then
            ACellColor := FActiveRowColor;

          if (i - 1 = FPageOffset) and (FActiveRowFontColor <> clNone) then
            ACellFont.Color := FActiveRowFontColor;

          GetCellProp(i - 1, j - 1, ACellValue, ACellColor, ACellAlign, ACellFont);

          CellStyle := VAlignStyle(Columns[j - 1].VAlign);

          if RowSelect[i - 1 + RowOffset] and ShowSelect then
          begin
           if (SelectColor <> clNone) then           
            ACellColor := SelectColor;

            if CellStyle <> '' then
              CellStyle := CellStyle + ';';
            CellStyle := CellStyle + 'color:' + HTMLClr(SelectFontColor) + ';';
          end;

          if (DState in [gsEdit, gsInsert]) and (FEditColor <> clNone) and
             (i - 1 = FPageOffset) then
            ACellColor := FEditColor;

          if (ACellColor <> clNone) then
            colprop := colprop + ' ' + HTMLColor(ACellColor, 'bgcolor');

          case ACellAlign of
            taCenter: colprop := colprop + ' align="center"';
            taRightJustify: colprop := colprop + ' align="right"';
          end;

          WidthStyle := '';

          if ((j - 1) = StretchColumn) and (GridWidth > TotColWidth) then
          begin
            colprop := colprop + ' width="' + IntToStr(GridWidth - TotColWidth) + 'px;"';
            WidthStyle := ' width:' + IntToStr(GridWidth - TotColWidth) + 'px;"';
          end
          else
          begin
            if (Columns[j - 1].Width <> 0) and (StrToInt(ridx) = 1) then
            begin
              case Columns[j - 1].WidthType of
              wtAbsolute:
                begin
                  colprop := colprop + ' width="' + inttostr(Columns[j - 1].Width) + 'px;"';
                  WidthStyle := '"width:' + inttostr(Columns[j - 1].Width) + 'px;"';
                end;
              wtPercent: colprop := colprop + ' width=' + inttostr(Columns[j - 1].Width) + '%';
              end;
            end;
          end;

          {$IFDEF TMSIW6}
          if Columns[j - 1].ColumnType = ctNormal then
          begin
            case Columns[j - 1].Cursor of
            crDefault: CellStyle := CellStyle + 'cursor:default;';
            crPointer: CellStyle := CellStyle + 'cursor:pointer;cursor:hand;';
            crAuto: CellStyle := CellStyle;
            crCrossHair: CellStyle := CellStyle + 'cursor:crosshair;';
            crMove: CellStyle := CellStyle + 'cursor:move;';
            crEResize: CellStyle := CellStyle + 'cursor:e-resize;';
            crNEResize: CellStyle := CellStyle + 'cursor:ne-resize;';
            crNWResize: CellStyle := CellStyle + 'cursor:nw-resize;';
            crNResize: CellStyle := CellStyle + 'cursor:n-resize;';
            crSEResize: CellStyle := CellStyle + 'cursor:se-resize;';
            crSWResize: CellStyle := CellStyle + 'cursor:sw-resize;';
            crSResize: CellStyle := CellStyle + 'cursor:s-resize;';
            crWResize: CellStyle := CellStyle + 'cursor:w-resize;';
            crText: CellStyle := CellStyle + 'cursor:text;';
            crWait: CellStyle := CellStyle + 'cursor:wait;';
            crHelp: CellStyle := CellStyle + 'cursor:help;';
            end;
          end;
          {$ENDIF}

          if not Columns[j - 1].Visible then
            CellStyle := CellStyle + 'display:none;';

          try
            Val(StripThousandSep(ACellValue), tempval, err);
          except
            tempval := 0;
          end;

          if (ShowFooter) and (err = 0) then
          begin
            case Columns[j - 1].FooterType of
            ftPageSum, ftPageAvg: Columns[j - 1].CalcValue := Columns[j - 1].FCalcValue + tempval;
            ftPageMin:
              if i = 1 then
                Columns[j - 1].CalcValue := tempval
              else if tempval < Columns[j - 1].CalcValue then
                Columns[j - 1].CalcValue := tempval;
            ftPageMax:
              if i = 1 then
                Columns[j - 1].CalcValue := tempval
              else if tempval > Columns[j - 1].CalcValue then
                Columns[j - 1].CalcValue := tempval;
            end;
          end;

          if DefaultRowHeight > 0 then
          begin
            //HeightStyle :=' style="height:' + IntToStr(DefaultRowHeight) + 'px;"';
            HeightStyle :=' height:' + IntToStr(DefaultRowHeight) + 'px;';
            //EditHeightStyle := ' style="height:' + IntToStr(DefaultRowHeight - 3) + 'px;"';
            EditHeightStyle := ' height:' + IntToStr(DefaultRowHeight - 3) + 'px;';
          end;

          hover := '';

          if (HoverColor <> clNone) or (HoverFontColor <> clNone) then
            hover := ' onmouseover="RowHover('+HTMLName+'Obj,' + ridx + ',' +
                inttostr(Columns.Count) + ',true)"' +
                ' onmouseout="RowHover('+HTMLName+'Obj,' + ridx + ',' +
                inttostr(Columns.Count) + ',false)"';

          //Make sure ACellHint is set to empty for each column.
          ACellHint := EmptyStr;

          if Columns[j - 1].ShowHint then
          begin
            if Columns[j - 1].Hint <> '' then
              ACellHint := Columns[j - 1].Hint
            else if (ACellValue <> '&nbsp;') then
              ACellHint := HTMLStrip(ACellValue);

            if Assigned(OnGetCellHint) then
              OnGetCellHint(Self, i - 1, j - 1, ACellHint);

            ACellHint := IIF((ACellHint <> '') and (ACellHint <> '&nbsp;'), ' title="' + HTMLStrip(ACellHint) + '"', '');
          end
          else
            EnabledCell := Columns[j - 1].Enabled;
            if Assigned(OnGetCellEditorEnabled) then
              OnGetCellEditorEnabled(Self, i - 1, j - 1, EnabledCell);

            coltype := Columns[j - 1].ColumnType;
            coleditor := Columns[j - 1].Editor;
            coldynedit := Columns[j - 1].DynEditor;

            if Assigned(OnGetCellType) then
              OnGetCellType(Self, i - 1, j - 1, coltype, coleditor, coldynedit);

          if CellStyle <> '' then
            CellStyle := ' style="' + CellStyle + '"';

          newcell := '<TD ' + colprop + hover + ACellHint + CellStyle;


          if not (DState in [gsEdit, gsInsert]) and
            not (coltype in [ctCheckBox, ctDataButton, ctURL,
            ctEmail, ctDynEdit, ctDynCombo, ctDynCheckBox, ctNode, ctImageCheckBox, ctButton, ctDynMemo]) then
          begin

            case FMouseSelect of
              msSingleCell:
              begin

                {$IFDEF TMSIW9}
                if Assigned(FOnAsyncCellClick) then
                begin
                    Acontext.WebApplication.RegisterCallBack(HTMLName+'.DoAsyncCellClick', DoAsyncCellClick);
                end;
                {$ENDIF}

                newcell := newcell + ' onclick="cellclick('+HTMLName+'Obj,'
                + ridx + ',' + cidx
                {$IFDEF TMSIW9}
                  + ', ' + HTMLControlImplementation.IWCLName + ');"';
                {$ELSE}
                  + ', '''');"';
                {$ENDIF}
              end;
              msRow:
                newcell := newcell + ' onclick="cellrowclick('+HTMLName+'Obj,' + ridx + ','
                  + cidx + ',' + inttostr(Columns.Count) + ')"';
              msRowCheck:
              begin
                {$IFDEF TMSIW9}
                if Assigned(FOnAsyncRowSelect) then
                begin
                    Acontext.WebApplication.RegisterCallBack(HTMLName+'.DoAsyncRowSelect', DoAsyncRowSelect);
                end;
                {$ENDIF}

                newcell := newcell + ' onclick="RowCheck('+HTMLName+'Obj,'
                + ridx
                {$IFDEF TMSIW9}
                  + ', ' + HTMLControlImplementation.IWCLName
                {$ELSE}                                                              
                  + ','''''                                           
                {$ENDIF}
                + ',0,false);"';
              end;
              msSingleRowCheck:
              begin
                {$IFDEF TMSIW9}
                if Assigned(FOnAsyncRowSelect) then
                begin
                    Acontext.WebApplication.RegisterCallBack(HTMLName+'.DoAsyncRowSelect', DoAsyncRowSelect);
                end;
                {$ENDIF}

                newcell := newcell + ' onclick="RowCheck('+HTMLName+'Obj,'
                + ridx
                {$IFDEF TMSIW9}
                  + ', ' + HTMLControlImplementation.IWCLName
                {$ELSE}
                  + ','''''
                {$ENDIF}
                + ',1,false);"';
              end;
              msMove:
              begin
                 if not (Columns[j - 1].ColumnType in [ctLink, ctLinkField, ctLinkRowNumber, ctPopup]) then
                 begin
                  //if i - 1 <> FPageOffset then
                  //begin
                    {$IFDEF TMSIW9}
                    if AsyncActiveRowMove then
                      Acontext.WebApplication.RegisterCallBack(HTMLName+'.DoAsyncGotoRow', DoAsyncGotoRow);
                    {$ENDIF}
  //                  newcell := newcell + ' onclick=' + SubmitCall('Move' + ridxj + ':' + cidx);
                    newcell := newcell + ' onclick="RowMove('+HTMLName+'Obj,'
                    + cidxj + ',' + ridxj
                    {$IFDEF TMSIW9}
                      + ',' + HTMLControlImplementation.IWCLName
                    {$ELSE}
                      + ','''''
                    {$ENDIF}
                    + ');"'
                  //end;
                  end;
                end;
              msClient:
                newcell := newcell + ' onclick="clientclick('+HTMLName+'Obj,' + cidxj + ',' + ridxj + ')"';
              msNone:
                newcell := newcell + ' onkeydown="gridkeydown('+HTMLName+'Obj,' + cidxj + ',' + ridxj + ')"';
              msEdit:
              begin
              {$IFDEF TMSIW9}
                newcell := newcell + ' onclick="editclick('+HTMLName+'Obj,' + cidxj + ',' + ridxj + ',-1,'
                  + HTMLControlImplementation.IWCLName + ')"';
              {$ELSE}
                newcell := newcell + ' onclick="editclick('+HTMLName+'Obj,' + cidxj + ',' + ridxj + ',-1)"';
              {$ENDIF}
              end;
            end;                                                                                    
          end;
                                                    
          newcell := newcell + '>';

          DetailValue := '';

          if (Columns[j - 1].DetailTemplate <> '') or (Columns[j - 1].DetailSpan <> 0) then
          begin
            // new functionality
            DG := GetDetailGrid(i - 1);

            if Assigned(DG) then
              if (DG.Scroll.Style <> scNever) then
              begin
                DG.Width := DG.GetTableWidth(true) + 20;
                DG.Height := DG.FullHeight;
                DG.UseFullHeight := true;
              end;

            if Assigned(DG) and (Master or (DetailGrid <> Self)) and
               ((DetailStates[i - 1 + RowOffset]) or (DetailRowShow in [dsNormal,dsAllOpen,dsOneOpen])) then
            begin
              inc(MaxID);
              DG.ID := MaxId;
              NumDetails := NumDetails + 1;

              RenderPrepareDetail(DG);

              {$IFDEF TMSIW6}
              DetailValue := '<TABLE cellspacing="0" cellpadding="0"><TR><TD>&nbsp;</TD><TD>' + DG.RenderString((DG <> Self),AContext)+'</TD></TR></TABLE>';
              {$ELSE}
              DetailValue := '<TABLE cellspacing="0" cellpadding="0"><TR><TD>&nbsp;</TD><TD>' + DG.RenderString((DG <> Self))+'</TD></TR></TABLE>';
              {$ENDIF}

              MaxID := MaxID + DG.NumDetails;
              NumDetails := NumDetails + DG.NumDetails;

              DG.ID := 0;
            end
            else
            begin
              DetailValue := GetCellDetail(j - 1, i - 1);
            end;

            if Trim(HTMLStrip(DetailValue)) = '' then
              DetailValue := '&nbsp;';

            {$IFDEF TMSDEBUG}
            outputdebugstring(pchar(DetailValue));
            {$ENDIF}

            DetailRow := DetailRow + '<TD colspan="' + IntToStr(Columns[j - 1].DetailSpan) + '"';

            DetailRow := DetailRow + ' style="' + IIF((FDetailHeight > 0),
              'height:' + IntToStr(FDetailheight) + 'px;', '') + 'width:' +
              GetColWidths(j - 1, Columns[j - 1].DetailSpan) + ';"';

            if Columns[j - 1].DetailColor <> clNone then
              DetailRow := DetailRow + HTMLColor(Columns[j - 1].DetailColor,
                'bgcolor');

          ACellDetailFont.Assign(Columns[j - 1].DetailFont);
          if ACellDetailFont.FontName = '' then
          begin
            if Columns[j - 1].DetailFont.FontName <> '' then
              ACellDetailFont.FontName := Columns[j - 1].DetailFont.FontName
            else
              ACellDetailFont.FontName := Font.FontName;
          end;

            DetailRow := DetailRow + '>' + FontToTag(ACellDetailFont,DetailValue) + '</TD>';
          end;


          if i - 1 = FPageOffset then
          begin

            if (coleditor = edCombo) and (Columns[j - 1].ComboItems.Count > 0)
              and ((ACellValue = '&nbsp;') or (ACellValue = '')) then
            begin
              subm := subm + '|' + Columns[j - 1].ComboItems.Strings[0];
              psubm := psubm + '|' + Columns[j - 1].ComboItems.Strings[0];
            end
            else if (coleditor <> edNone) and (ACellValue <> '&nbsp;') then
            begin
              subm := subm + '|' + EncodeLF(GetLookupValue(j - 1, ACellValue));
              psubm := psubm + '|' + EncodeLF(GetLookupValue(j - 1, ACellValue));
            end
            else
            begin
              subm := subm + '|';
              psubm := psubm + '|';
            end;
          end;

          CRPar := cidxj + ',' + ridxj;


          //****************************************
          // NEW DIRECT EDIT SUPPORT
          //****************************************

          if (i = 1) and (MouseSelect = msEdit) then
          begin
            EditID := ' id="L' + FIDS + 'C' + cidxj + '"';

            if (coleditor <> edNone) and
               not (coltype in [ctDynCombo,ctDynText,ctDynText,ctDynCheckBox]) then
            he := he + '<DIV style="position:absolute;visibility:hidden;" id="HE' + FIDS + 'C' + cidxj + '">';

            {$IFDEF TMSDEBUG}
            outputdebugstring('rendering edits');
            {$ENDIF}

            if ACellColor = clNone then
              ACellColor := Color;

            if ACellValue = '&nbsp;' then
              ACellValue := '';

            ABorderColor := ACellColor;

            case coleditor of
              edCheckbox:
              if not (coltype in [ctDynCheckBox]) then
              begin
                he := he + '<INPUT onblur="UpdDirEdit('+HTMLName+'Obj,this,' + CRPar +
                {$IFDEF TMSIW9}
                  ','+HTMLControlImplementation.IWCLName+')" onclick="UpdCheck('+HTMLName+'Obj,this,' + CRPar +
                {$ELSE}
                  ','''')" onclick="UpdCheck('+HTMLName+'Obj,this,' + CRPar +
                {$ENDIF}
                  ')" TYPE="checkbox" ' + IIF(Uppercase(ACellValue) =
                  Uppercase(Columns[j - 1].CheckTrue), 'CHECKED', '') + EditId +
                  '>';
              end;
              edEdit:
                {$IFDEF TMSIW9}
                he := he + '<INPUT onblur="UpdDirEdit('+HTMLName+'Obj,this,' + CRPar + ','+HTMLControlImplementation.IWCLName+');"'+
                {$ELSE}
                he := he + '<INPUT onblur="UpdDirEdit('+HTMLName+'Obj,this,' + CRPar + ','''');"'+
                {$ENDIF}
                  ' TYPE="text" VALUE="' + EncodeLF(ACellValue) +
                  '" autocomplete="off" style="border-style:solid;border-width:0px;'
                  + 'border-color:' + HTMLClr(ABorderColor) + ';background-color:'
                  + HTMLClr(ACellColor) + ';width:100%;' +
                  {$IFDEF TMSIW6}
                  ACellFont.FontToStringStyle(AContext.WebApplication.Browser) + ';'
                  {$ELSE}                                                                  
                  ACellFont.FontToStringStyle(WebApplication.Browser) + ';'
                  {$ENDIF}
                  + EditHeightStyle + '" '
                  + ' onkeypress="return KeyPress('+HTMLName+'Obj,this,0,event,true,'+CRPAR+','+IntToStr(Columns[StrToInt(cidxj)].DynPrecision)+',1);"'
                  {$IFDEF TMSIW9}
                  + ' onkeydown="return DirKeyDown('+HTMLName+'Obj,event,this,'+cidxj+',' + ridxj+','+HTMLControlImplementation.IWCLName+');" '
                  {$ELSE}
                  + ' onkeydown="return DirKeyDown('+HTMLName+'Obj,event,this,'+cidxj+',' + ridxj+','''');" '
                  {$ENDIF}
                  + ' onfocus="'+HTMLName+'Obj.focusel=this;" '
                  + MakeAlign(ACellAlign) + EditID
                  + IIF(Columns[j - 1].MaxLength > 0, ' maxlength="' +
                  IntToStr(Columns[j - 1].MaxLength) + '"', '') + '>';

              edEditNumeric:
                he := he + '<div style="width:100%;overflow:hidden;"><INPUT onblur="UpdDirEdit('+HTMLName+'Obj,this,' + CRPar +
                {$IFDEF TMSIW9}
                  ','+HTMLControlImplementation.IWCLName+')" TYPE="text" VALUE="' + ACellValue +
                {$ELSE}
                  ','''')" TYPE="text" VALUE="' + ACellValue +
                {$ENDIF}
                  '" autocomplete="off" style="border-style:solid;border-width:0px;'
                  + 'border-color:' + HTMLClr(ABorderColor) + ';background-color:'
                  + HTMLClr(ACellColor) + ';width:100%;' +
                  {$IFDEF TMSIW6}
                  ACellFont.FontToStringStyle(AContext.WebApplication.Browser) + ';'
                  {$ELSE}
                  ACellFont.FontToStringStyle(WebApplication.Browser) + ';'
                  {$ENDIF}
                  + EditHeightStyle + '" '                                
                  + 'onkeypress="return KeyPress('+HTMLName+'Obj,this,1,event,true,'+CRPar+','+IntToStr(Columns[StrToInt(cidxj)].DynPrecision)+',1)"'
                  {$IFDEF TMSIW9}
                  + ' onkeydown="return DirKeyDown('+HTMLName+'Obj,event,this,'+cidxj+','+ridxj+','+HTMLControlImplementation.IWCLName+')"'
                  {$ELSE}
                  + ' onkeydown="return DirKeyDown('+HTMLName+'Obj,event,this,'+cidxj+','+ridxj+','''')"'
                  {$ENDIF}
                  + ' onkeyup="return WGKeyUp(this);" onfocus="'+HTMLName+'Obj.focusel=this;" '
                  + MakeAlign(ACellAlign) + EditID
                  + IIF(Columns[j - 1].MaxLength > 0, ' maxlength="' +
                  IntToStr(Columns[j - 1].MaxLength) + '"', '') + '></div>';
              edEditFloat:
                he := he + '<INPUT onblur="UpdDirEdit('+HTMLName+'Obj,this,' + CRPar +
                {$IFDEF TMSIW9}
                  ','+HTMLControlImplementation.IWCLName+')" autocomplete="off" TYPE="text" VALUE="' + ACellValue +
                {$ELSE}
                  ','''')" autocomplete="off" TYPE="text" VALUE="' + ACellValue +
                {$ENDIF}
                  '" style="border-style:solid;border-width:0px;'
                  + 'border-color:' + HTMLClr(ABorderColor) + ';background-color:'
                  + HTMLClr(ACellColor) + ';width:100%;' +
                  {$IFDEF TMSIW6}
                  ACellFont.FontToStringStyle(AContext.WebApplication.Browser) + ';'
                  {$ELSE}
                  ACellFont.FontToStringStyle(WebApplication.Browser) + ';'
                  {$ENDIF}
                  + EditHeightStyle + '" '
                  + 'onkeypress="return KeyPress('+HTMLName+'Obj,this,2,event,true,'+CRPar+','+IntToStr(Columns[StrToInt(cidxj)].DynPrecision)+',1)"'
                  {$IFDEF TMSIW9}
                  + ' onkeydown="return DirKeyDown('+HTMLName+'Obj,event,this,'+cidxj+','+ridxj+','+HTMLControlImplementation.IWCLName+')"'
                  {$ELSE}
                  + ' onkeydown="return DirKeyDown('+HTMLName+'Obj,event,this,'+cidxj+','+ridxj+','''')"'
                  {$ENDIF}
                  + ' onkeyup="return WGKeyUp(this);" onfocus="'+HTMLName+'Obj.focusel=this;" '
                  + MakeAlign(ACellAlign) + EditID
                  + IIF(Columns[j - 1].MaxLength > 0, ' maxlength="' +
                  IntToStr(Columns[j - 1].MaxLength) + '"', '') + '>';
              edEditLower:
                he := he + '<INPUT onblur="UpdDirEdit('+HTMLName+'Obj,this,' + CRPar +
                {$IFDEF TMSIW9}
                  ','+HTMLControlImplementation.IWCLName+')" autocomplete="off" TYPE="text" VALUE="' + EncodeLF(ACellValue) +
                {$ELSE}
                  ','''')" autocomplete="off" TYPE="text" VALUE="' + EncodeLF(ACellValue) +
                {$ENDIF}
                  '" style="border-style:solid;border-width:0px;'
                  + 'border-color:' + HTMLClr(ABorderColor) + ';background-color:'
                  + HTMLClr(ACellColor) + ';width:100%;' +
                  {$IFDEF TMSIW6}
                  ACellFont.FontToStringStyle(AContext.WebApplication.Browser) + ';'
                  {$ELSE}
                  ACellFont.FontToStringStyle(WebApplication.Browser) + ';'
                  {$ENDIF}
                  + EditHeightStyle + '" '
                  + 'onkeypress="return KeyPress('+HTMLName+'Obj,this,5,event,true,'+CRPar+','+IntToStr(Columns[StrToInt(cidxj)].DynPrecision)+',1)"'
                  {$IFDEF TMSIW9}
                  + ' onkeydown="return DirKeyDown('+HTMLName+'Obj,event,this,'+cidxj+','+ridxj+','+HTMLControlImplementation.IWCLName+')"'
                  {$ELSE}
                  + ' onkeydown="return DirKeyDown('+HTMLName+'Obj,event,this,'+cidxj+','+ridxj+','''')"'
                  {$ENDIF}
                  + ' onfocus="'+HTMLName+'Obj.focusel=this;" '
                  + MakeAlign(ACellAlign) + EditID
                  + IIF(Columns[j - 1].MaxLength > 0, ' maxlength="' +
                  IntToStr(Columns[j - 1].MaxLength) + '"', '') + '>';
              edEditUpper:
                he := he + '<INPUT onblur="UpdDirEdit('+HTMLName+'Obj,this,' + CRPar +
                {$IFDEF TMSIW9}
                  ','+HTMLControlImplementation.IWCLName+')" autocomplete="off" TYPE="text" VALUE="' + EncodeLF(ACellValue) +
                {$ELSE}
                  ','''')" autocomplete="off" TYPE="text" VALUE="' + EncodeLF(ACellValue) +
                {$ENDIF}
                  '" style="border-style:solid;border-width:0px;'
                  + 'border-color:' + HTMLClr(ABorderColor) + ';background-color:'
                  + HTMLClr(ACellColor) + ';width:100%;' +
                  {$IFDEF TMSIW6}
                  ACellFont.FontToStringStyle(AContext.WebApplication.Browser) + ';'
                  {$ELSE}
                  ACellFont.FontToStringStyle(WebApplication.Browser) + ';'
                  {$ENDIF}
                  + EditHeightStyle + '" '
                  + 'onkeypress="return KeyPress('+HTMLName+'Obj,this,3,event,true,'+CRPar+','+IntToStr(Columns[StrToInt(cidxj)].DynPrecision)+',1)"'
                  {$IFDEF TMSIW9}
                  + ' onkeydown="return DirKeyDown('+HTMLName+'Obj,event,this,'+cidxj+','+ridxj+','+HTMLControlImplementation.IWCLName+')"'
                  {$ELSE}
                  + ' onkeydown="return DirKeyDown('+HTMLName+'Obj,event,this,'+cidxj+','+ridxj+','''')"'
                  {$ENDIF}
                  + ' onfocus="'+HTMLName+'Obj.focusel=this;" '
                  + MakeAlign(ACellAlign) + EditID
                  + IIF(Columns[j - 1].MaxLength > 0, ' maxlength="' +
                  IntToStr(Columns[j - 1].MaxLength) + '"', '') + '>';
              edEditHex:
                he := he + '<INPUT onblur="UpdDirEdit('+HTMLName+'Obj,this,' + CRPar +
                {$IFDEF TMSIW9}
                  ','+HTMLControlImplementation.IWCLName+')" autocomplete="off" TYPE="text" VALUE="' + ACellValue +
                {$ELSE}
                  ','''')" autocomplete="off" TYPE="text" VALUE="' + ACellValue +
                {$ENDIF}
                  '" style="border-style:solid;border-width:0px;'
                  + 'border-color:' + HTMLClr(ABorderColor) + ';background-color:'
//                  + HTMLClr(ACellColor) + ';"' + EditWidthStyle + EditHeightStyle
                  + HTMLClr(ACellColor) + ';width:100%;' +
                  {$IFDEF TMSIW6}
                  ACellFont.FontToStringStyle(AContext.WebApplication.Browser) + ';'
                  {$ELSE}
                  ACellFont.FontToStringStyle(WebApplication.Browser) + ';'
                  {$ENDIF}
                  + EditHeightStyle + '" '
                  + 'onkeypress="return KeyPress('+HTMLName+'Obj,this,6,event,true,'+CRPar+','+IntToStr(Columns[StrToInt(cidxj)].DynPrecision)+',1)"'
                  {$IFDEF TMSIW9}
                  + ' onkeydown="return DirKeyDown('+HTMLName+'Obj,event,this,'+cidxj+','+ridxj+','+HTMLControlImplementation.IWCLName+')"'
                  {$ELSE}
                  + ' onkeydown="return DirKeyDown('+HTMLName+'Obj,event,this,'+cidxj+','+ridxj+','''')"'
                  {$ENDIF}
                  + ' onfocus="'+HTMLName+'Obj.focusel=this;" '
                  + MakeAlign(ACellAlign) + EditID
                  + IIF(Columns[j - 1].MaxLength > 0, ' maxlength="' +
                  IntToStr(Columns[j - 1].MaxLength) + '"', '') + '>';
              edPassword:
                he := he + '<INPUT onblur="UpdDirEdit('+HTMLName+'Obj,this,' + CRPar +
                {$IFDEF TMSIW9}
                  ','+HTMLControlImplementation.IWCLName+')" autocomplete="off" TYPE="password" VALUE="' + EncodeLF(ACellValue) +
                {$ELSE}
                  ','''')" autocomplete="off" TYPE="password" VALUE="' + EncodeLF(ACellValue) +
                {$ENDIF}
                  '" style="border-style:solid;border-width:0px;'
                  + 'border-color:' + HTMLClr(ABorderColor) + ';background-color:'
                  + HTMLClr(ACellColor) + ';width:100%;' +
                  {$IFDEF TMSIW6}
                  ACellFont.FontToStringStyle(AContext.WebApplication.Browser) + ';'
                  {$ELSE}
                  ACellFont.FontToStringStyle(WebApplication.Browser) + ';'
                  {$ENDIF}
                  + EditHeightStyle + '" '
                  + ' onfocus="'+HTMLName+'Obj.focusel=this;" '
                  + MakeAlign(ACellAlign) + EditID
                  + IIF(Columns[j - 1].MaxLength > 0, ' maxlength="' + IntToStr(Columns[j - 1].MaxLength) + '"', '')
                  {$IFDEF TMSIW9}
                  + ' onkeydown="return DirKeyDown('+HTMLName+'Obj,event,this,'+cidxj+','+ridxj+','+HTMLControlImplementation.IWCLName+')">';
                  {$ELSE}
                  + ' onkeydown="return DirKeyDown('+HTMLName+'Obj,event,this,'+cidxj+','+ridxj+','''')">';
                  {$ENDIF}
              edCombo:
                begin

                  {$IFDEF TMSIW9}
                  if Assigned(FOnAsyncComboChange) then
                  begin
                      Acontext.WebApplication.RegisterCallBack(HTMLName+'.DoAsyncComboChange', DoAsyncComboChange);
                  end;
                  {$ENDIF}

                  he := he + '<SELECT style=' +
                  {$IFDEF TMSIW6}
                  ACellFont.FontToStringStyle(AContext.WebApplication.Browser) + ';'
                  {$ELSE}
                  ACellFont.FontToStringStyle(WebApplication.Browser) + ';'
                  {$ENDIF}
                   + WidthStyle + ' onblur="' +
                    //'UpdDirEdit('+HTMLName+'Obj,this,' + CRPar + ')" onChange="UpdDirEdit('+HTMLName+'Obj,this,' + CRPar + ');UpdCombo('+HTMLName+'Obj(),this,' + CRPar + ')"'+ EditID + '>';
                  {$IFDEF TMSIW9}
                  'UpdDirEdit('+HTMLName+'Obj,this,' + CRPar + ','+HTMLControlImplementation.IWCLName+')" onChange="UpdCombo('+HTMLName+'Obj,this,' + CRPar + ','+HTMLControlImplementation.IWCLName+')"'+ EditID + '>';
                  {$ELSE}
                  'UpdDirEdit('+HTMLName+'Obj,this,' + CRPar + ','''')" onChange="UpdCombo('+HTMLName+'Obj,this,' + CRPar + ','''')"'+ EditID + '>';
                  {$ENDIF}
                  he := he + GetLookUpValues(j - 1, ACellValue);
                  he := he + '</SELECT>';
                end;

              edDatePicker:
                begin
                  he := he + '<DIV>' + RenderCalendar('L' + FIDS + 'C' + cidxj
                    , Columns[j - 1].Width,
                    ACellFont.FontName, ACellFont.Size, 'UpdDirEdit('+HTMLName+'Obj,ctrl,' +
                    {$IFDEF TMSIW9}
                    CRPar + ','+HTMLControlImplementation.IWCLName+')', ACellValue, ACellColor) + '</DIV>';
                    {$ELSE}
                    CRPar + ','''')', ACellValue, ACellColor) + '</DIV>';
                    {$ENDIF}
                end;

              edSpinEdit:  he := he + '<DIV>' + RenderSpin('L' + FIDS + 'C' + cidxj
                  , Columns[j - 1].MaxLength, Columns[j - 1].Width, ACellAlign,
                  ' style="' +
                  {$IFDEF TMSIW6}
                  ACellFont.FontToStringStyle(AContext.WebApplication.Browser) + '"'
                  {$ELSE}
                  ACellFont.FontToStringStyle(WebApplication.Browser) + '"'
                  {$ENDIF}
                  , ACellValue, ACellColor,
                  Columns[j - 1].SpinEditMaxValue, Columns[j - 1].SpinEditMinValue,
                  Columns[j - 1].SpinEditAutoSpin,
                  {$IFDEF TMSIW9}
                  'UpdDirEdit('+HTMLName+'Obj,ctrl,' + CRPar + ','+HTMLControlImplementation.IWCLName+')',isIE) + '</DIV>';
                  {$ELSE}
                  'UpdDirEdit('+HTMLName+'Obj,ctrl,' + CRPar + ','''')',isIE) + '</DIV>';
                  {$ENDIF}

              edPopupEdit:
                begin
                  he := he +
                    '<TABLE border="0" cellpadding="0" cellspacing="0"><TR><TD>'
                    + '<DIV style="overflow:hidden;width:' + IntToStr(Columns[j - 1].Width - 16) + 'px;height:'
                    {$IFDEF TMSIW6}
//                    + IntToStr(DefaultRowHeight) + 'px;'+ACellFont.FontToStringStyle(AContext.WebApplication.Browser)+'">' + ACellValue + '</DIV>'
                    + IntToStr(DefaultRowHeight) + 'px;'+ACellFont.FontToStringStyle(AContext.WebApplication.Browser)+'">...</DIV>'
                    {$ELSE}
                    + IntToStr(DefaultRowHeight) + 'px;'+ACellFont.FontToStringStyle(WebApplication.Browser)+'">' + '...' + '</DIV>'
                    {$ENDIF}
                    + '<DIV style="z-index:2;position:absolute;overflow:hidden;height:' + IntToStr(Columns[j - 1].PopupHeight) + ';width:'
                    + IntToStr(Columns[j - 1].PopupWidth) + ';'
                    + 'border-color:#000000;border-width:1px;border-style:solid;padding:2px; ';
                                                                                 
                    if (Columns[j - 1].PopupColorTo <> clNone) then
                      he := he + GradientStyle(Columns[j - 1].PopupColor, Columns[j - 1].PopupColorTo, Columns[j - 1].PopupColorGradientDirection) + '"'
                    else                                                                                
                      he := he + 'background:'+ HTMLClr(Columns[j - 1].PopupColor) + '" ';     
                                                                                                     
                    he := he + 'id="L' + FIDS + 'pd'
                    + '"><TEXTAREA WRAP ' + EditID + ' style="height:' + IntToStr(Columns[j - 1].PopupHeight - 30) + ';width:'
                    + IntToStr(Columns[j - 1].PopupWidth - 6) + ';"></TEXTAREA><BR>'
                    +'<INPUT TYPE="BUTTON" VALUE="Ok" '
                    {$IFDEF TMSIW9}
                    + 'onclick=''UpdDirEdit('+HTMLName+'Obj,document.getElementById("'+'L' + FIDS + 'C' + cidxj+'"),'+CRPar+','+HTMLControlImplementation.IWCLName+',event);''>'
                    {$ELSE}
                    + 'onclick=''UpdDirEdit('+HTMLName+'Obj,document.getElementById("'+'L' + FIDS + 'C' + cidxj+'"),'+CRPar+','''',event);''>'
                    {$ENDIF}                                      

//                    +'<INPUT TYPE="BUTTON" VALUE="Cancel" onclick="'+ FIDS +'PopCancel(this,'+IntToStr(j - 1)+','+IntToStr(i - 1)+')"></DIV>'
                    +'<INPUT TYPE="BUTTON" VALUE="Cancel" '
                    + 'onclick=''CancelDirEdit('+HTMLName+'Obj,document.getElementById("'+'L' + FIDS + 'C' + cidxj+'"),'+CRPar+',event);''>'

//                    onclick="document.getElementById(''L'+FIDS+'pd'').style.visibility=''hidden''"></DIV>'
                    + '</TD><TD></TD></TR></TABLE>';
                end;
              edMemo:
                begin
//                  he := he + '<TEXTAREA ' + EditWidthStyle + EditHeightStyle + ' onblur="'
                  he := he + '<TEXTAREA style="width:100%;' + EditHeightStyle + '" onblur="'
                  {$IFDEF TMSIW9}
                    + 'UpdDirEdit('+HTMLName+'Obj,this,' + CRPar + ','+HTMLControlImplementation.IWCLName+')"' + EditID + '>' +
                  {$ELSE}
                    + 'UpdDirEdit('+HTMLName+'Obj,this,' + CRPar + ','''')"' + EditID + '>' +
                  {$ENDIF}
                    ACellValue + '</TEXTAREA>';
                end;

            end;

            if (coleditor <> edNone) and
              not (coltype in [ctDynCombo,ctDynText,ctDynCheckBox]) then
                he := he + '</DIV>';
          end;

          {$IFDEF TMSIW9}
          if (coleditor in [edEdit, edEditNumeric, edEditFloat,
            edEditLower, edEditUpper, edEditHex, edPassword,
            edCombo, edDatePicker, edSpinEdit, edMemo, edPopupEdit]) then
          begin
              if ((Assigned(FOnAsyncEditDone) or Assigned(FOnAsyncValidate)) and (AsyncEdit) )  then
              begin
                  Acontext.WebApplication.RegisterCallBack(HTMLName+'.DoAsyncEditDone', DoAsyncEditDone);
              end;
          end;
          {$ENDIF}

          {$IFDEF TMSIW9}
          if EditableCell or AsyncEdit then
          {$ELSE}
          if EditableCell then
          {$ENDIF}
          begin

            EditID := ' id="' + FIDS + 'D' + ridxj + 'C' + cidxj + '"';
            if ACellColor = clNone then
              ACellColor := Color;

            if ACellValue = '&nbsp;' then
              ACellValue := '';

              newcell := newcell + '<DIV style="display:none;" id="CV' + FIDS + 'R' + ridxj + 'C' + cidxj + '">'
              + ACellValue + '</DIV>';              

            {$IFDEF TMSIW9}
//            if not EditableCell and AsyncEdit then
            if AsyncEdit then
            begin
              // hidden DIV start
              newcell := newcell + '<DIV';

              if not EditableCell then
                newcell := newcell + ' style="display:none;" ';

              newcell := newcell + ' id="HE' + FIDS + 'R' + ridxj + 'C' + cidxj + '">';

              EditID := ' id="' + FIDS + 'AER' + ridxj + 'C' + cidxj + '"';
            end;

           {$ENDIF}

            {$IFDEF TMSDEBUG}
            outputdebugstring('rendering edits');
            {$ENDIF}


            if (coleditor in [edEdit, edEditNumeric, edEditFloat,
              edEditLower, edEditUpper, edEditHex, edPassword]) and
              (FirstEdit = '') and (ActiveColumn = -1) then
              FirstEdit := FIDS + 'D' + ridxj + 'C' + cidxj;

            if (ActiveColumn = j - 1) and (FirstEdit = '') then
              FirstEdit := FIDS + 'D' + ridxj + 'C' + cidxj;

            ABorderColor := ACellColor;

            case coleditor of
              edCheckbox:
                newcell := newcell + '<INPUT onclick="UpdCheck('+HTMLName+'Obj,this,' + CRPar +
                  ')" TYPE="checkbox" ' + IIF(Uppercase(ACellValue) =
                  Uppercase(Columns[j - 1].CheckTrue), 'CHECKED', '') + EditId +
                  '>';

              edEdit:
                newcell := newcell + '<INPUT onblur="UpdEdit('+HTMLName+'Obj,this,' + CRPar +
                {$IFDEF TMSIW9}
                  ','+HTMLControlImplementation.IWCLName+')" TYPE="text" VALUE="' + EncodeLF(ACellValue) +
                {$ELSE}
                  ','''')" TYPE="text" VALUE="' + EncodeLF(ACellValue) +
                {$ENDIF}
                  '" style="border-style:solid;border-width:1px;'
                  + 'border-color:' + HTMLClr(ABorderColor) + ';background-color:'
                  + HTMLClr(ACellColor) + ';width:100%;' +
                  {$IFDEF TMSIW6}
                  ACellFont.FontToStringStyle(AContext.WebApplication.Browser) + ';'
                  {$ELSE}
                  ACellFont.FontToStringStyle(WebApplication.Browser) + ';'
                  {$ENDIF}
                  + EditHeightStyle + '" '
                  + ' onkeypress="return KeyPress('+HTMLName+'Obj,this,0,event,true,'+CRPAR+','+IntToStr(Columns[StrToInt(cidxj)].DynPrecision)+',1)"'
                  + ' onkeydown="return KeyDown('+HTMLName+'Obj,this,'+cidxj+',' + ridxj+',event)" '
                  + ' onfocus="'+HTMLName+'Obj.focusel=this;" '
                  + MakeAlign(ACellAlign) + EditID
                  + IIF(Columns[j - 1].MaxLength > 0, ' maxlength="'
                  + IntToStr(Columns[j - 1].MaxLength) + '"', '') + '>';
              edEditNumeric:
                newcell := newcell + '<INPUT onblur="UpdEdit('+HTMLName+'Obj,this,' + CRPar +
                {$IFDEF TMSIW9}
                  ','+HTMLControlImplementation.IWCLName+')" TYPE="text" VALUE="' + ACellValue +
                {$ELSE}
                  ','''')" TYPE="text" VALUE="' + ACellValue +
                {$ENDIF}
                  '" style="border-style:solid;border-width:1px;'
                  + 'border-color:' + HTMLClr(ABorderColor) + ';background-color:'
                  + HTMLClr(ACellColor) + ';width:100%;' +
                  {$IFDEF TMSIW6}
                  ACellFont.FontToStringStyle(AContext.WebApplication.Browser) + ';'
                  {$ELSE}
                  ACellFont.FontToStringStyle(WebApplication.Browser) + ';'
                  {$ENDIF}
                  + EditHeightStyle + '" '
                  + 'onkeypress="return KeyPress('+HTMLName+'Obj,this,1,event,true,'+CRPar+','+IntToStr(Columns[StrToInt(cidxj)].DynPrecision)+',1)"'
                  + ' onkeydown="return KeyDown('+HTMLName+'Obj,this,'+cidxj+','+ridxj+',event)"'
                  + ' onkeyup="return WGKeyUp(this);" onfocus="'+HTMLName+'Obj.focusel=this;" '
                  + MakeAlign(ACellAlign) + EditID
                  + IIF(Columns[j - 1].MaxLength > 0, ' maxlength="' +
                  IntToStr(Columns[j - 1].MaxLength) + '"', '') + '>';
              edEditFloat:
                newcell := newcell + '<INPUT onblur="UpdEdit('+HTMLName+'Obj,this,' + CRPar +
                {$IFDEF TMSIW9}
                  ','+HTMLControlImplementation.IWCLName+')" TYPE="text" VALUE="' + ACellValue +
                {$ELSE}
                  ','''')" TYPE="text" VALUE="' + ACellValue +
                {$ENDIF}
                  '" style="border-style:solid;border-width:1px;'
                  + 'border-color:' + HTMLClr(ABorderColor) + ';background-color:'
                  //+ HTMLClr(ACellColor) + ';"' + WidthStyle + HeightStyle
                  + HTMLClr(ACellColor) + ';width:100%;' +
                  {$IFDEF TMSIW6}
                  ACellFont.FontToStringStyle(AContext.WebApplication.Browser) + ';'
                  {$ELSE}
                  ACellFont.FontToStringStyle(WebApplication.Browser) + ';'
                  {$ENDIF}
                  + EditHeightStyle + '" '
                  + 'onkeypress="return KeyPress('+HTMLName+'Obj,this,2,event,true,'+CRPar+','+IntToStr(Columns[StrToInt(cidxj)].DynPrecision)+',1)"'
                  + ' onkeydown="return KeyDown('+HTMLName+'Obj,this,'+cidxj+','+ridxj+',event)"'
                  + ' onkeyup="return WGKeyUp(this);" onfocus="'+HTMLName+'Obj.focusel=this;" '
                  + MakeAlign(ACellAlign) + EditID
                  + IIF(Columns[j - 1].MaxLength > 0, ' maxlength="' +
                  IntToStr(Columns[j - 1].MaxLength) + '"', '') + '>';
              edEditLower:
                newcell := newcell + '<INPUT onblur="UpdEdit('+HTMLName+'Obj,this,' + CRPar +
                {$IFDEF TMSIW9}
                  ','+HTMLControlImplementation.IWCLName+')" TYPE="text" VALUE="' + EncodeLF(ACellValue) +
                {$ELSE}
                  ','''')" TYPE="text" VALUE="' + EncodeLF(ACellValue) +
                {$ENDIF}
                  '" style="border-style:solid;border-width:1px;'
                  + 'border-color:' + HTMLClr(ABorderColor) + ';background-color:'
                  + HTMLClr(ACellColor) + ';width:100%;' +
                  {$IFDEF TMSIW6}
                  ACellFont.FontToStringStyle(AContext.WebApplication.Browser) + ';'
                  {$ELSE}
                  ACellFont.FontToStringStyle(WebApplication.Browser) + ';'
                  {$ENDIF}
                  + EditHeightStyle + '" '
                  + 'onkeypress="return KeyPress('+HTMLName+'Obj,this,5,event,true,'+CRPar+','+IntToStr(Columns[StrToInt(cidxj)].DynPrecision)+',1)"'
                  + ' onkeydown="return KeyDown('+HTMLName+'Obj,this,'+cidxj+','+ridxj+',event)"'
                  + ' onfocus="'+HTMLName+'Obj.focusel=this;" '
                  + MakeAlign(ACellAlign) + EditID
                  + IIF(Columns[j - 1].MaxLength > 0, ' maxlength="' +
                  IntToStr(Columns[j - 1].MaxLength) + '"', '') + '>';
              edEditUpper:
                newcell := newcell + '<INPUT onblur="UpdEdit('+HTMLName+'Obj,this,' + CRPar +
                {$IFDEF TMSIW9}
                  ','+HTMLControlImplementation.IWCLName+')" TYPE="text" VALUE="' + EncodeLF(ACellValue) +
                {$ELSE}
                  ','''')" TYPE="text" VALUE="' + EncodeLF(ACellValue) +
                {$ENDIF}
                  '" style="border-style:solid;border-width:1px;'
                  + 'border-color:' + HTMLClr(ABorderColor) + ';background-color:'
                  + HTMLClr(ACellColor) + ';width:100%;' +
                  {$IFDEF TMSIW6}
                  ACellFont.FontToStringStyle(AContext.WebApplication.Browser) + ';'
                  {$ELSE}
                  ACellFont.FontToStringStyle(WebApplication.Browser) + ';'
                  {$ENDIF}
                  + EditHeightStyle + '" '
                  + 'onkeypress="return KeyPress('+HTMLName+'Obj,this,3,event,true,'+CRPar+','+IntToStr(Columns[StrToInt(cidxj)].DynPrecision)+',1)"'
                  + ' onkeydown="return KeyDown('+HTMLName+'Obj,this,'+cidxj+','+ridxj+',event)"'
                  + ' onfocus="'+HTMLName+'Obj.focusel=this;" '
                  + MakeAlign(ACellAlign) + EditID
                  + IIF(Columns[j - 1].MaxLength > 0, ' maxlength="' +
                  IntToStr(Columns[j - 1].MaxLength) + '"', '') + '>';
              edEditHex:
                newcell := newcell + '<INPUT onblur="UpdEdit('+HTMLName+'Obj,this,' + CRPar +
                {$IFDEF TMSIW9}
                  ','+HTMLControlImplementation.IWCLName+')" TYPE="text" VALUE="' + ACellValue +
                {$ELSE}
                  ','''')" TYPE="text" VALUE="' + ACellValue +
                {$ENDIF}
                  '" style="border-style:solid;border-width:1px;'
                  + 'border-color:' + HTMLClr(ABorderColor) + ';background-color:'
                  + HTMLClr(ACellColor) + ';width:100%;' +
                  {$IFDEF TMSIW6}
                  ACellFont.FontToStringStyle(AContext.WebApplication.Browser) + ';'
                  {$ELSE}
                  ACellFont.FontToStringStyle(WebApplication.Browser) + ';'
                  {$ENDIF}
                  + EditHeightStyle + '" '
                  + 'onkeypress="return KeyPress('+HTMLName+'Obj,this,6,event,true,'+CRPar+','+IntToStr(Columns[StrToInt(cidxj)].DynPrecision)+',1)"'
                  + ' onkeydown="return KeyDown('+HTMLName+'Obj,this,'+cidxj+','+ridxj+',event)"'
                  + ' onfocus="'+HTMLName+'Obj.focusel=this;" '
                  + MakeAlign(ACellAlign) + EditID
                  + IIF(Columns[j - 1].MaxLength > 0, ' maxlength="' +
                  IntToStr(Columns[j - 1].MaxLength) + '"', '') + '>';
              edPassword:
                newcell := newcell + '<INPUT onblur="UpdEdit('+HTMLName+'Obj,this,' + CRPar +
                {$IFDEF TMSIW9}
                  ','+HTMLControlImplementation.IWCLName+')" TYPE="password" VALUE="' + EncodeLF(ACellValue) +
                {$ELSE}
                  ','''')" TYPE="password" VALUE="' + EncodeLF(ACellValue) +
                {$ENDIF}
                  '" style="border-style:solid;border-width:1px;'
                  + 'border-color:' + HTMLClr(ABorderColor) + ';background-color:'
                  + HTMLClr(ACellColor) + ';width:100%;' +
                  {$IFDEF TMSIW6}
                  ACellFont.FontToStringStyle(AContext.WebApplication.Browser) + ';'
                  {$ELSE}
                  ACellFont.FontToStringStyle(WebApplication.Browser) + ';'
                  {$ENDIF}
                  + EditHeightStyle + '" '
                  + ' onfocus="'+HTMLName+'Obj.focusel=this;" '
                  + MakeAlign(ACellAlign) + EditID
                  + IIF(Columns[j - 1].MaxLength > 0, ' maxlength="' +
                  IntToStr(Columns[j - 1].MaxLength) + '"', '') + '>';
              edCombo:
                begin
                  {$IFDEF TMSIW9}
                  if Assigned(FOnAsyncComboChange) then
                  begin
                      Acontext.WebApplication.RegisterCallBack(HTMLName+'.DoAsyncComboChange', DoAsyncComboChange);
                  end;
                  {$ENDIF}

                  newcell := newcell + '<SELECT style="'+
                  {$IFDEF TMSIW6}
                  ACellFont.FontToStringStyle(AContext.WebApplication.Browser)
                  {$ELSE}
                  ACellFont.FontToStringStyle(WebApplication.Browser)
                  {$ENDIF}
                  + ';width:100%" onblur="UpdEdit('+HTMLName+'Obj,this,' + CRPar + ','
                  {$IFDEF TMSIW9}
                  + HTMLControlImplementation.IWCLName+')" onChange="UpdEdit('+HTMLName+'Obj,this,' + CRPar + ','
                  + HTMLControlImplementation.IWCLName+');UpdCombo('+HTMLName+'Obj,this,' + CRPar + ','
                  + HTMLControlImplementation.IWCLName+')"'+ EditID + '>';
                  {$ELSE}
                  + ''''')" onChange="UpdEdit('+HTMLName+'Obj,this,' + CRPar + ','
                  + ''''');UpdCombo('+HTMLName+'Obj,this,' + CRPar + ','
                  + ''''')"'+ EditID + '>';
                  {$ENDIF}
                  newcell := newcell + GetLookUpValues(j - 1, ACellValue);
                  newcell := newcell + '</SELECT>';
                end;

              edDatePicker:
                begin
                  newcell := newcell + '<DIV ' + EditID + '>' + RenderCalendar(FIDS
                  + cidx + ridx, Columns[j - 1].Width,
                  ACellFont.FontName, ACellFont.Size, 'UpdEdit('+HTMLName+'Obj,ctrl,' +
                  {$IFDEF TMSIW9}
                  CRPar + ','+HTMLControlImplementation.IWCLName+')', ACellValue, ACellColor) + '</DIV>';
                  {$ELSE}
                  CRPar + ','''')', ACellValue, ACellColor) + '</DIV>';
                  {$ENDIF}
                end;

              edSpinEdit: newcell := newcell + '<DIV ' + EditID + '>' + RenderSpin(FIDS +
                  cidx + 'R' + ridx, Columns[j - 1].MaxLength, Columns[j - 1].Width,
                  ACellAlign,
                  ' style="' +
                  {$IFDEF TMSIW6}
                  ACellFont.FontToStringStyle(AContext.WebApplication.Browser) + '"'
                  {$ELSE}
                  ACellFont.FontToStringStyle(WebApplication.Browser) + '"'
                  {$ENDIF}
                  , ACellValue, ACellColor,
                  Columns[j - 1].SpinEditMaxValue, Columns[j - 1].SpinEditMinValue,
                  Columns[j - 1].SpinEditAutoSpin,
                  {$IFDEF TMSIW9}
                  'UpdEdit('+HTMLName+'Obj,ctrl,' + CRPar + ','+HTMLControlImplementation.IWCLName+')',isIE) + '</DIV>';
                  {$ELSE}
                  'UpdEdit('+HTMLName+'Obj,ctrl,' + CRPar + ','''')',isIE) + '</DIV>';
                  {$ENDIF}

              edMemo:
                begin
//                  newcell := newcell + '<TEXTAREA ' + WidthStyle + HeightStyle + ' onblur="'
                    newcell := newcell + '<TEXTAREA style="width:100%;' + EditHeightStyle + '" onblur="'
                  {$IFDEF TMSIW9}
                    + 'UpdEdit('+HTMLName+'Obj,this,' + CRPar + ','+HTMLControlImplementation.IWCLName+')"' + EditID + '>' +
                  {$ELSE}
                    + 'UpdEdit('+HTMLName+'Obj,this,' + CRPar + ','''')"' + EditID + '>' +
                  {$ENDIF}
                    ACellValue + '</TEXTAREA>';
                end;                                                                   
                                                                                                 
              edPopupEdit:
                begin
                  newcell := newcell +
                    '<TABLE border="0" cellpadding="0" cellspacing="0"><TR><TD>'
                    + '<DIV ' + EditID + ' style="overflow:hidden;white-space:pre;width:' + IntToStr(Columns[j - 1].Width - 16) + 'px;height:'
                    {$IFDEF TMSIW6}
                    + IntToStr(DefaultRowHeight) + 'px;'+ACellFont.FontToStringStyle(AContext.WebApplication.Browser)+'">' + ACellValue + '</DIV>'
                    {$ELSE}
                    + IntToStr(DefaultRowHeight) + 'px;'+ACellFont.FontToStringStyle(WebApplication.Browser)+'">' + ACellValue + '</DIV>'
                    {$ENDIF}
                    + '<DIV style="z-index:2;position:absolute;overflow:hidden;height:' + IntToStr(Columns[j - 1].PopupHeight) + ';width:'
                    + IntToStr(Columns[j - 1].PopupWidth) + ';'
                    + 'visibility:hidden;border-color:#000000;border-width:1px;border-style:solid;padding:2px;';

                    if (Columns[j - 1].PopupColorTo <> clNone) then
                      newcell := newcell
                      + GradientStyle(Columns[j - 1].PopupColor, Columns[j - 1].PopupColorTo, Columns[j - 1].PopupColorGradientDirection) + '" '
                    else
                      newcell := newcell + 'background-color:'+ HTMLClr(Columns[j - 1].PopupColor) + '" ';

                    newcell := newcell + 'id="' + FIDS + 'pd'
                    + ridx + 'c' + cidx + '"><TEXTAREA WRAP ID="'+ FIDS + 'TA' + ridxj + 'c' + cidxj
                    +'" style="height:' + IntToStr(Columns[j - 1].PopupHeight - 30) + ';width:'
                    + IntToStr(Columns[j - 1].PopupWidth - 6) + ';"></TEXTAREA><BR>'
                    +'<INPUT TYPE="BUTTON" VALUE="Ok" ';

                    {$IFDEF TMSIW9}
                    newcell := newcell + 'onclick="PopOk('+HTMLName+'Obj,this,';
                    if not AsyncEdit then
                      newcell := newcell + #39+FIDS + 'D' + ridxj+'C'+ cidxj+#39
                    else
                      newcell := newcell + #39 + FIDS + 'AER' + ridxj + 'C' + cidxj + #39;
                    newcell := newcell + ','+cidxj+','+ridxj+','+HTMLControlImplementation.IWCLName+')">';
                    {$ELSE}
                    newcell := newcell + 'onclick="PopOk('+HTMLName+'Obj,this,'#39+FIDS + 'D' + ridxj+'C'+ cidxj+#39','+cidxj+','+ridxj+','''')">';
                    {$ENDIF}

                    newcell := newcell + '<INPUT TYPE="BUTTON" VALUE="Cancel" onclick="PopCancel('+HTMLName+'Obj,this)"></DIV>'
                    + '</TD><TD><INPUT TYPE="BUTTON" onclick='
                    + '"PopClick('+HTMLName+'Obj,document.getElementById('#39 + FIDS + 'pd'
                    + ridx + 'c' + cidx + #39'),';

                    {$IFDEF TMSIW9}
                    if not AsyncEdit then
                      newcell := newcell + #39 + FIDS + 'D' + ridxj + 'C' + cidxj + #39','
                    else
                    {$ENDIF}                    
                      newcell := newcell + #39 + FIDS + 'AER' + ridxj + 'C' + cidxj + #39',';

                    newcell := newcell + ridxj+','+cidxj+');" VALUE="..."></TD></TR></TABLE>';

                end;
            end;

            {$IFDEF TMSIW9}
            if AsyncEdit then                                 
            begin
              // hidden DIV end
              newcell := newcell + '</DIV>';
            end;
            {$ENDIF}

          end;

          {$IFDEF TMSIW9}
          if not EditableCell or AsyncEdit then
          {$ELSE}
          if not EditableCell then
          {$ENDIF}
          begin

            {$IFDEF TMSIW9}
            if EditableCell and AsyncEdit then
              coldisplay := 'display:none;'
            else
            {$ENDIF}
              coldisplay := EmptyStr;

            case coltype of
              ctNormal:
                begin
                  if (Columns[j - 1].Font.FontName = Font.FontName) and
                     (Columns[j - 1].Font.Size = Font.Size) and
                     (Columns[j - 1].Font.Color = Font.Color) and
                     (Columns[j - 1].Font.Style = []) and
                     {$IFNDEF TMSIW9}
                     (Columns[j - 1].Font.CSSStyle = Font.CSSStyle) and
                     {$ENDIF}
                      not Assigned(OnGetCellProp) then
                    newcell := newcell + '<DIV style="'
                      + iif((ActiveRowFontColor <> clNone),'color:' + HTMLClr(ACellFont.Color)
                      + ';','') + 'width:100%;'+coldisplay+'" id="' + FIDS + 'D'
                      + ridxj + 'C' + cidxj + '">' + ACellValue + '</DIV>'
                  else
                    newcell := newcell + '<DIV style="' + FontInsert(ACellFont)
                      + 'width:100%;'+coldisplay+'" id="' + FIDS + 'D'
                      + ridxj + 'C' + cidxj + '">' +  ACellValue + '</DIV>';
                end;

              ctPassword:
              begin
                pwd := '';

                for m := 0 to Length(ACellValue) - 1 do
                begin
                  if (AContext.WebApplication.Browser = brIE)
                  {$IFDEF TMSIW9}
                  and not AsyncEdit
                  {$ENDIF}
                  then
                    pwd := pwd + '='
                  else
                    pwd := pwd + '*';
                end;

                if (AContext.WebApplication.Browser = brIE)
                {$IFDEF TMSIW9}
                and not AsyncEdit
                {$ENDIF}                
                then
                    newcell := newcell + '<DIV style="font-family:webdings;'
                    + iif((ActiveRowFontColor <> clNone),'color:' + HTMLClr(ACellFont.Color) + ';','') + 'width:100%;'+coldisplay+'" id="' + FIDS + 'D'
                      + ridxj + 'C' + cidxj + '">' + pwd + '</DIV>'
                else
                  newcell := newcell + FontToTag(ACellFont,'<DIV style="width:100%;'+coldisplay+'" id="' + FIDS + 'D'
                    + ridxj + 'C' + cidxj + '">' +  pwd + '</DIV>');

              end;

              ctRowIndicator:                                              
                if (i - 1 = FPageOffset) then
                begin
                  case DState of
                    gsBrowse:
                    begin
                      if Indicators.BrowseURL <> EmptyStr then
                        newcell := newcell + ImageHTML(Indicators.BrowseURL, 0, 0, False, '').Render()
                      else
                        newcell := newcell + OutputBMP('BROWSE', FIndicators.Browse, False, '')
                    end;
                    gsEdit:
                    begin
                      if Indicators.EditURL <> EmptyStr then
                        newcell := newcell + ImageHTML(Indicators.EditURL, 0, 0, False, '').Render()
                      else
                        newcell := newcell + OutputBMP('EDIT', FIndicators.Edit, False, '');
                    end;
                    gsInsert:
                    begin
                      if Indicators.InsertURL <> EmptyStr then
                        newcell := newcell + ImageHTML(Indicators.InsertURL, 0, 0, False, '').Render()
                      else
                        newcell := newcell + OutputBMP('INSERT', FIndicators.Insert, False, '');
                    end;
                  end;
                end
                else
                  newcell := newcell + '&nbsp;';

              ctPopupImage:
                begin

                if not isIE then
                  ACellValue := '<div style="position:relative;top:-15px;">' + ACellValue + '</div>';

                  newcell := newcell + FontToTag(ACellFont,'<DIV id="' + FIDS + 'D'
                    + ridxj + 'C' + cidxj + '">' + ACellValue +
                    '</DIV>');
                end;

              ctNoWrap:
                begin
                  newcell := newcell
                    + FontToTag(ACellFont,'<DIV class="' + HTMLName + 'nowrapc' + IntToStr(j - 1)+ '" '
//                    + FontToTag(ACellFont,'<DIV style="'+coldisplay+'overflow:hidden;width:'
//                    + IntToStr(Columns[j - 1].Width-4-1) + 'px;height:'
//                    + IntToStr(DefaultRowHeight-4-1) + 'px" '
                    + 'style="'+coldisplay+'" '#13
                    + 'id="' + FIDS + 'D' + IntToStr(i - 1) + 'C' + IntToStr(j - 1) + '">' + ACellValue + '</DIV>');
                end;

              ctURL:
              begin
                if ACellValue = '&nbsp;' then
                  ACellValue := '';

                  ACellURL := GetURLText(j - 1,i - 1,ACellValue);

                  if (Pos('HTTP://', UpperCase(ACellValue)) = 0) then
                    newcell := newcell + '<A href="http://' + ACellValue + '"'
                  else
                    newcell := newcell + '<A href="' + ACellValue + '"';

                  if coldisplay <> EmptyStr then
                    newcell := newcell + ' style="' + coldisplay + '"';

                    newcell := newcell + ' target="_blank" id="' + FIDS + 'D' + IntToStr(i - 1) + 'C' + IntToStr(j - 1)+'">';

                  newcell := newcell + FontToTag(ACellFont,ACellURL) + '</A>';
              end;

              ctEmail:
              begin
                if ACellValue = '&nbsp;' then
                  ACellValue := '';

                  newcell := newcell + '<A  href="mailto:' + ACellValue
                  + '"  id="' + FIDS + 'D' + IntToStr(i - 1) + 'C' + IntToStr(j - 1)+'"';

                  if coldisplay <> EmptyStr then
                    newcell := newcell + 'style="' + coldisplay + '"';

                  newcell := newcell
                  + '>'
                  + FontToTag(ACellFont,ACellValue) + '</A>';
              end;

              ctDataButton:
                begin

                  if (DState in [gsEdit, gsInsert]) then
                  begin
                    DivPC := '';

                    if (i - 1 = FPageOffset) then
                    begin
                      dispPC := '';
                      dispE := 'display:none;'
                    end
                    else
                    begin
                      dispPC := 'display:none;';
                      dispE := 'display:none;'
                    end;

                  end
                  else
                  begin
                    dispPC := 'display:none;';
                    dispE := '';
                  end;

                  idBP := 'id="' + FIDS + 'DBP' + IntToStr(i - 1) + '"';
                  idBC := 'id="' + FIDS + 'DBC' + IntToStr(i - 1) + '"';

                  submitclick := SubmitCall('CancelRow' + IntToStr(i - 1));

                    {$IFDEF TMSIW9}
                    if (AsyncEdit) then
                    begin
                      submitclick := 'processAjaxEvent(''onCancel'', '
                        + HTMLControlImplementation.IWCLName
                        + ',''' + HTMLName + '.' + 'DoAsyncCancel' + ''','
                        + 'true' + ', null, '
                        + 'true' + ');';

                      Acontext.WebApplication.RegisterCallBack(HTMLName+'.DoAsyncCancel', DoAsyncCancel);

                      submitclick := '"GACancel('+HTMLName+'Obj,' + IntToStr(i - 1) + ');'
                      + submitclick + '"';

                    end;
                    {$ENDIF}
                      //if AsyncEdit then
                      //  submitclick := '"GACancel('+HTMLName+'Obj,' + IntToStr(i - 1) + ');"';


                      case Columns[j - 1].DataButtonType of
                      dbtImage:
                        begin

                          if Glyphs.PostButtonURL <> EmptyStr then
                            DIVPC := DIVPC + '<SPAN ' + idBP + ' style="'+dispPC+'cursor:pointer;" onclick="return ' + FIDS +
                              'PostValidate(' + IntToStr(i - 1) + ')"' +' '+ IIF(Glyphs.PostHint = '', '', 'title="'
                              + Glyphs.PostHint + '"')+'>'
                              + ImageHTML(Glyphs.PostButtonURL, 0, 0, False, '').Render()
                              + '</span>'
                          else if Assigned(Glyphs.PostButton) then
                            DIVPC := DIVPC + '<SPAN ' + idBP + ' style="'+dispPC+'cursor:pointer;" onclick="return ' + FIDS +
                              'PostValidate(' + IntToStr(i - 1) + ')"' +' '+ IIF(Glyphs.PostHint = '', '', 'title="'
                              + Glyphs.PostHint + '"')+'>'
                              + OutputBMP('POST', Glyphs.PostButton, False, '')
                              + '</span>';

                          if Glyphs.CancelButtonURL <> EmptyStr then
                            DIVPC := DIVPC + '<SPAN ' + idBC + ' style="'+dispPC+'cursor:pointer;" onclick=' + submitclick
                             + ' '+ IIF(Glyphs.CancelHint = '', '', 'title="' + Glyphs.CancelHint + '"')+'>'
                             + ImageHTML(Glyphs.CancelButtonURL, 0, 0, False, '').Render()
                             + '</SPAN>'
                          else if Assigned(Glyphs.CancelButton) then
                            DIVPC := DIVPC + '<SPAN ' + idBC + ' style="'+dispPC+'cursor:pointer;" onclick=' + submitclick
                             + ' '+ IIF(Glyphs.CancelHint = '', '', 'title="' + Glyphs.CancelHint + '"')+'>'
                             + OutputBMP('CANCEL', Glyphs.CancelButton, False, '')
                             + '</SPAN>';
                        end;
                      dbtLink:
                        begin
                          DIVPC := DIVPC + '<a ' + idBP + ' style="'+dispPC+'" href="#" onclick="return ' + FIDS +
                            'PostValidate(' + IntToStr(i - 1) + ')">' +
                            FontToTag(ACellFont,Glyphs.PostHint) + '</a> ';

                          DIVPC := DIVPC + '<a ' + idBC + ' style="'+dispPC+'" href="#" onclick=' + submitclick
                          + ' >' + FontToTag(ACellFont,Glyphs.CancelHint) + '</a>';
                        end;
                      dbtButton:
                        begin
                          DIVPC := DIVPC + '<BUTTON ' + idBP + ' style="'+dispPC+'font-family:webdings;width:22;" onclick="return ' + FIDS +
                            'PostValidate(' + IntToStr(i - 1) + ')" '+ IIF(Glyphs.PostHint = '', '', 'title="' + Glyphs.PostHint + '"')+'><font face="webdings">' + chr($61)+ '</font></BUTTON>';

                          DIVPC := DIVPC + '<BUTTON ' + idBC + ' style="'+dispPC+'font-family:webdings;width:22;" onclick=' + submitclick
                           + ' '+ IIF(Glyphs.CancelHint = '', '', 'title="' + Glyphs.CancelHint + '"')+'><font face="webdings">' + chr($72) + '</font></BUTTON>';
                        end
                      end;
                    //end
                    //else
                    //  DIVPC := DIVPC + '&nbsp;';

                    newcell := newcell + DIVPC;
//                  end
//                  else
//                  begin

                    idBE := 'id="' + FIDS + 'DBE' + IntToStr(i - 1) + '"';
                    DIVE := '';

                    submitclick := SubmitCall('EditRow' + IntToStr(i - 1) + FIDS);

                    {$IFDEF TMSIW9}
                    if (AsyncEdit) then
                    begin
                    {*
                      submitclick := 'processAjaxEvent(''onEdit'', '
                        + HTMLControlImplementation.IWCLName
                        + ',''' + HTMLName + '.' + 'DoAsyncEdit' + ''','
                        + 'true' + ', null, '
                        + 'true' + ');';
                        *}

                      Acontext.WebApplication.RegisterCallBack(HTMLName+'.DoAsyncEdit', DoAsyncEdit);

                      submitclick := '"GAEdit('+HTMLName+'Obj,' + IntToStr(i - 1) + ',' + HTMLControlImplementation.IWCLName + ',true);'
                      //+ submitclick
                      + '"';

                    end;
                    {$ENDIF}
                    //if AsyncEdit then
                    //  submitclick := '"GAEdit('+HTMLName+'Obj,' + IntToStr(i - 1) + ');"';


                    case Columns[j - 1].DataButtonType of
                    dbtImage:
                    begin

                      if Glyphs.EditButtonURL <> EmptyStr then
                        DIVE := DIVE + '<SPAN ' + idBE + ' style="'+dispE+'cursor:pointer;cursor:hand" onclick=' + submitclick
                          + ' '+ IIF(Glyphs.EditHint = '', '', 'title="' + Glyphs.EditHint + '"')+'>' +
                          ImageHTML(Glyphs.EditButtonURL, 0, 0, False, '').Render()
                          + '</SPAN>'
                      else if Assigned(Glyphs.EditButton) then
                        DIVE := DIVE + '<SPAN ' + idBE + ' style="'+dispE+'cursor:pointer;cursor:hand" onclick=' + submitclick
                          + ' '+ IIF(Glyphs.EditHint = '', '', 'title="' + Glyphs.EditHint + '"')+'>' +
                          OutputBMP('EDIT', Glyphs.EditButton, False, '')
                          + '</SPAN>';
                    end;
                    dbtLink:
                      DIVE := DIVE + '<a ' + idBE + ' style="'+dispE+'" href="#" onclick=' + submitclick
                        + ' >' + FontToTag(ACellFont,Glyphs.EditHint) + ' </a>';
                    dbtButton:
                      DIVE := DIVE + '<BUTTON ' + idBE + ' style="'+dispE+'" style="font-family:wingdings;width:22;" onclick=' + submitclick
                      + ' '+ IIF(Glyphs.EditHint = '', '', 'title="' + Glyphs.EditHint + '"')+'><font size=4 face="wingdings">' + char($33) + '</font></BUTTON>';
                    end;

                    newcell := newcell + DIVE;
                  //end;
                end;

              ctLinkField:
                begin
                  tmp := '<A href="#" id="' + FIDS + 'D' + IntToStr(i - 1) + 'C' + IntToStr(j - 1)+'"';

                  {$IFDEF TMSIW9}
                  if AsyncActiveRowMove then
                    Acontext.WebApplication.RegisterCallBack(HTMLName+'.DoAsyncGotoRow', DoAsyncGotoRow);
                  {$ENDIF}
                  tmp := tmp + ' onclick="RowMove('+HTMLName+'Obj,'
                  + IntToStr(j - 1) + ',' + IntToStr(i - 1)
                  {$IFDEF TMSIW9}
                    + ',' + HTMLControlImplementation.IWCLName
                  {$ELSE}
                    + ','''''
                  {$ENDIF}
                  + ');"'

                  //+ ' onclick=' + SubmitCall('Move' + IntToStr(i - 1) + ':' + IntToStr(j)) +

                  + '>' +  ACellValue + '</A>';

                  newcell := newcell + FontToTag(ACellFont,tmp);
                end;

              ctLink:
                begin
                  {$IFDEF TMSIW9}
                  if Assigned(FOnAsyncLinkClick) then
                  begin
                      Acontext.WebApplication.RegisterCallBack(HTMLName+'.DoAsyncLinkClick', DoAsyncLinkClick);
                  end;

                  tmp := '<A href="#" id="' + FIDS + 'D' + IntToStr(i - 1) + 'C'
                  + IntToStr(j - 1)+'" onclick="LnkClick('+HTMLName+'Obj,'
                  + IntToStr(j - 1) + ',' + IntToStr(i - 1) +','+HTMLControlImplementation.IWCLName+')">' +  ACellValue + '</A>';
                  {$ELSE}
                  tmp := '<A href="#" id="' + FIDS + 'D' + IntToStr(i - 1) + 'C'
                  + IntToStr(j - 1)+'" onclick="LnkClick('+HTMLName+'Obj,'
                  + IntToStr(j - 1) + ',' + IntToStr(i - 1) +','''')">' +  ACellValue + '</A>';
                  {$ENDIF}

                  newcell := newcell + FontToTag(ACellFont,tmp);
                end;

              ctCheckBox:
              begin
                {$IFDEF TMSIW9}
                if Assigned(FOnAsyncCheckClick) then
                begin
                    Acontext.WebApplication.RegisterCallBack(HTMLName+'.DoAsyncCheckClick', DoAsyncCheckClick);
                end;
                {$ENDIF}

                {$IFDEF TMSIW9}
                if Assigned(FOnAsyncRowSelect) then
                begin
                    Acontext.WebApplication.RegisterCallBack(HTMLName+'.DoAsyncRowSelect', DoAsyncRowSelect);
                end;
                {$ENDIF}

                newcell := newcell + '<INPUT TYPE="CHECKBOX" onclick="RowClick('+HTMLName
                +'Obj,this,' + inttostr(i) + ',' + inttostr(Columns.Count)
                + ',' + IntToStr(j)
                {$IFDEF TMSIW9}
                   + ',true,'+HTMLControlImplementation.IWCLName+')"' +
                {$ELSE}
                   + ',true,'''')"' +
                {$ENDIF}
                  IIF(Columns[j - 1].Enabled, ' ', ' DISABLED') + ' ' +
                  IIF(RowSelect[i - 1 + RowOffset], ' CHECKED', '') + ' id="' +
                  FIDS + 'CK' + IntToStr(j - 1) + 'R' + IntToStr(i - 1) + '"';

                  if coldisplay <> EmptyStr then
                    newcell := newcell + ' style="' + coldisplay + '"';

                  newcell := newcell
                  + '>';
              end;

              ctRadioButton: newcell := newcell + '<INPUT TYPE="RADIO" ID="' + FIDS + 'RADC' + IntToStr(j -1) + 'R' + inttostr(i - 1) + '" NAME="C' + IntToStr(j - 1)
                    + '" onclick="RadioClick('+HTMLName+'Obj,this,' + IntToStr(i)
                    + ',' + IntToStr(Columns.Count) + ',' + IntToStr(j - 1) + ')"'
                    + IIF(Columns[j - 1].Enabled,' ',' DISABLED') + ' '
                    + IIF( i - 1 = RadioSelection,' CHECKED','') + '>';

              ctDynEdit:
                begin
                  if ACellValue = '&nbsp;' then
                    ACellValue := '';
                  // initialize dyn edit on cell value
                  if (DynEdits[j - 1, i - 1 + RowOffset] = Columns[j - 1].DefaultDynEdit) and (ACellValue <> '')  then
                    DynEdits[j - 1, i - 1 + RowOffset] := ACellValue;

//                  newcell := newcell + '<INPUT ' + WidthStyle + ' TYPE="TEXT" id="' + FIDS +
                  newcell := newcell + '<INPUT style="width:100%" TYPE="TEXT" id="' + FIDS +
                    'D' + IntToStr(i - 1) + 'C' + IntToStr(j - 1) + '" NAME="C'
                      +
                    IntToStr(j - 1) + '" onkeyup="return ' + FIDS + 'DynaEditUpdate(this,'
                      + IntToStr(j - 1) + ',' + IntToStr(i - 1) + ',0,event)"' +
                    ' onblur="' + FIDS + 'DynaEditDone(this,'
                      + IntToStr(j - 1) + ',' + IntToStr(i - 1) + ',event)"' +
                    ' value="' + DynEdits[j - 1, i - 1 + RowOffset] + '"' +

                    IIF(Columns[j - 1].MaxLength > 0,' maxlength="' + IntToStr(Columns[j - 1].MaxLength) + '"', '') + ' ' +
                    MakeAlign(ACellAlign);

                  case coldynedit of
                    deSigned: newcell := newcell + ' onkeypress="' +
                      'return KeyPress('+HTMLName+'Obj,this,1,event,true,'+CRPar+','+IntToStr(Columns[StrToInt(cidxj)].DynPrecision)+')"';
                    deUnsigned: newcell := newcell + ' onkeypress="' +
                      'return KeyPress('+HTMLName+'Obj,this,1,event,false,'+CRPar+','+IntToStr(Columns[StrToInt(cidxj)].DynPrecision)+')"';
                    deFloatSigned: newcell := newcell + ' onkeypress="' +
                      'return KeyPress('+HTMLName+'Obj,this,2,event,true,'+CRPar+','+IntToStr(Columns[StrToInt(cidxj)].DynPrecision)+')"';
                    deFloatUnsigned: newcell := newcell + ' onkeypress="' +
                      'return KeyPress('+HTMLName+'Obj,this,2,event,false,'+CRPar+','+IntToStr(Columns[StrToInt(cidxj)].DynPrecision)+')"';
                    deText: newcell := newcell + ' onkeypress="' +
                      'return KeyPress('+HTMLName+'Obj,this,0,event,false,'+CRPar+','+IntToStr(Columns[StrToInt(cidxj)].DynPrecision)+',2)"';
                  end;

                  newcell := newcell + '>';
                end;

              ctDynMemo:
                begin
                  if ACellValue = '&nbsp;' then
                    ACellValue := '';
                  // initialize dyn edit on cell value
                  if (DynEdits[j - 1, i - 1 + RowOffset] = Columns[j - 1].DefaultDynEdit) and (ACellValue <> '')  then
                    DynEdits[j - 1, i - 1 + RowOffset] := ACellValue;

//                  newcell := newcell + '<TEXTAREA ' + WidthStyle + ' id="' + FIDS +
                  newcell := newcell + '<TEXTAREA style="width:100%' + HeightStyle + '" id="' + FIDS +
                    'D' + IntToStr(i - 1) + 'C' + IntToStr(j - 1) + '" NAME="C'
                      +
                    IntToStr(j - 1) + '" onkeyup="return ' + FIDS + 'DynaEditUpdate(this,'
                      + IntToStr(j - 1) + ',' + IntToStr(i - 1) + ',0)"' +
                    ' onblur="' + FIDS + 'DynaEditDone(this,'
                      + IntToStr(j - 1) + ',' + IntToStr(i - 1) + ',event)"' +

                    IIF(Columns[j - 1].MaxLength > 0,' maxlength="' + IntToStr(Columns[j - 1].MaxLength) + '"', '') + ' ' +
                    MakeAlign(ACellAlign);

                  case coldynedit of
                    deSigned: newcell := newcell + ' onkeypress="' +
                      'return KeyPress('+HTMLName+'Obj,this,1,event,true,'+CRPar+','+IntToStr(Columns[StrToInt(cidxj)].DynPrecision)+')"';
                    deUnsigned: newcell := newcell + ' onkeypress="' +
                      'return KeyPress('+HTMLName+'Obj,this,1,event,false,'+CRPar+','+IntToStr(Columns[StrToInt(cidxj)].DynPrecision)+')"';
                    deFloatSigned: newcell := newcell + ' onkeypress="' +
                      'return KeyPress('+HTMLName+'Obj,this,2,event,true,'+CRPar+','+IntToStr(Columns[StrToInt(cidxj)].DynPrecision)+')"';
                    deFloatUnsigned: newcell := newcell + ' onkeypress="' +
                      'return KeyPress('+HTMLName+'Obj,this,2,event,false,'+CRPar+','+IntToStr(Columns[StrToInt(cidxj)].DynPrecision)+')"';
                    deText: newcell := newcell + ' onkeypress="' +
                      'return KeyPress('+HTMLName+'Obj,this,0,event,false,'+CRPar+','+IntToStr(Columns[StrToInt(cidxj)].DynPrecision)+',2)"';
                  end;

                  newcell := newcell + '>' + DynEdits[j - 1, i - 1 + RowOffset] + '</TEXTAREA>';
                end;

              ctDynCombo:
                begin
                  if ACellValue = '&nbsp;' then
                    ACellValue := '';

                  // initialize dyn edit on cell value
                  if (DynEdits[j - 1, i - 1 + RowOffset] = Columns[j - 1].DefaultDynEdit) and (ACellValue <> '')  then
                    DynEdits[j - 1, i - 1 + RowOffset] := ACellValue;


                  newcell := newcell + '<SELECT style="width:100%;' +
                  {$IFDEF TMSIW6}
                  ACellFont.FontToStringStyle(AContext.WebApplication.Browser) + ';"'
                  {$ELSE}
                  ACellFont.FontToStringStyle(WebApplication.Browser) + ';"'
                  {$ENDIF}

                   + '" id="' + FIDS + 'D' +
                    IntToStr(i - 1) + 'C' + IntToStr(j - 1) + '" NAME="C' +
                    IntToStr(j - 1) + '" onchange="return ' + FIDS + 'DynaEditUpdate(this,'
                      + IntToStr(j - 1) + ',' + IntToStr(i - 1) + ',1)"' +
                    ' onblur="' + FIDS + 'DynaEditDone(this,'
                      + IntToStr(j - 1) + ',' + IntToStr(i - 1) + ',event)"' +
                    ' value="' + DynEdits[j - 1, i - 1 + RowOffset] + '"' +
                    MakeAlign(ACellAlign) + '>';
                  newcell := newcell + GetLookUpValues(j - 1, DynEdits[j - 1, i - 1 + RowOffset]);
                  newcell := newcell + '</SELECT>';
                end;

              ctDynCheckBox:
                begin
                  newcell := newcell + '<INPUT type="CHECKBOX" onclick="return ' + FIDS +
                    'DynaEditUpdate(this,' + IntToStr(j - 1) + ',' + IntToStr(i - 1) + ',2)" id="' +
                    FIDS + 'D' + IntToStr(i - 1) + 'C' + IntToStr(j - 1) + '"';

                  if (DynEdits[j - 1, i - 1 + RowOffset] <> '0') then
                    newcell := newcell + ' CHECKED';

                  newcell := newcell + '>';
                end;

              ctDynText:
                begin
                  if Assigned(FOnGetDynText) then
                    FOnGetDynText(Self, i - 1 + RowOffset, j - 1, ACellValue)
                  else
                    ACellValue := Columns[j - 1].DefaultDynText;

                    //s := s + FontToTag(ACellFont,'<DIV style="overflow:hidden;width= id="' + FIDS + 'D'

                    newcell := newcell + FontToTag(ACellFont,'<DIV style="overflow:hidden;width:'
                    + IntToStr(Columns[j - 1].Width - 4 - 1) + 'px;height:' + IntToStr(DefaultRowHeight-4-1)
                    + '" id="' + FIDS + 'D' + inttostr(i - 1) + 'C' + inttostr(j - 1) + '">' + ACellValue +
                    '</DIV>');
                end;

              ctDataCheckbox:
                begin
                  newcell := newcell + '<INPUT TYPE="CHECKBOX" id="' + FIDS + 'D'
                    + ridxj + 'C' + cidxj + '" DISABLED ' + IIF(Uppercase(ACellValue)
                    = Uppercase(Columns[j - 1].CheckTrue), ' CHECKED', '');

                  if coldisplay <> EmptyStr then
                    newcell := newcell + ' style="' + coldisplay + '"';

                  newcell := newcell
                    + '>';
                end;

              ctButton:
              begin
                {$IFDEF TMSIW9}
                if Assigned(FOnAsyncButtonClick) then
                begin
                    Acontext.WebApplication.RegisterCallBack(HTMLName+'.DoAsyncButtonClick', DoAsyncButtonClick);
                end;
                {$ENDIF}

                newcell := newcell + '<INPUT TYPE="BUTTON" ' + IIF(Columns[j - 1].ButtonColor <> clNone,'style="background-color:'
                  + HTMLClr(Columns[j - 1].ButtonColor)+'"','')
                  +' onclick="BtnClick('+HTMLName+'Obj,' + IntToStr(j - 1) + ',' + IntToStr(i - 1)
                  {$IFDEF TMSIW9}
                  + ','#39 + Columns[j - 1].ClickConfirm + #39', ' + HTMLControlImplementation.IWCLName + ');"' +
                  {$ELSE}
                  + ','#39 + Columns[j - 1].ClickConfirm + #39', '''');"' +
                  {$ENDIF}
                  ' VALUE="' + Columns[j - 1].ButtonText + '" ' +
                  IIF(Columns[j - 1].Enabled,' ',' DISABLED') + ' id="' + FIDS + 'D'
                    + ridxj + 'C' + cidxj + '"'
                  + iif(Columns[j - 1].ButtonWidth > 0,' style="width:'+IntToStr(Columns[j - 1].ButtonWidth)+'px"','') + '>';
              end;

              ctNode:
                begin
                   ShowNode := true;
                   if Assigned(OnNodeShow) then
                     OnNodeShow(Self, i, ShowNode);

                    if ShowNode then
                      newcell := newcell + GetNode(i, 'Toggle')
                    else
                      newcell := newcell + '&nbsp;';
                end;

              ctImageCheckBox:
                begin
                  newcell := newcell + GetCheck(i - 1, j - 1, 'CToggle', not RowSelect[i - 1 + RowOffset]);
                end;

              ctDataImageCheckBox:
                begin
                  newcell := newcell
                  + '<DIV id="' + FIDS + 'D' + ridxj + 'C' + cidxj + '"';

                  if coldisplay <> EmptyStr then
                    newcell := newcell + ' style="' + coldisplay + '"';

                  newcell := newcell
                  + '>'
                  + GetImageCheck(i - 1, j - 1, UpperCase(ACellValue) = UpperCase(Columns[j - 1].CheckTrue))
                  + '</DIV>';

                  {$IFDEF TMSIW9}
                  if (AsyncEdit or AsyncPaging) then
                  begin
                    newcell := newcell
                    + '<DIV id="' + FIDS + 'TD' + ridxj + 'C' + cidxj + '" style="display:none;">'
                    + GetImageCheck(i - 1, j - 1, True)
                    + '</DIV>'
                    + '<DIV id="' + FIDS + 'FD' + ridxj + 'C' + cidxj + '" style="display:none;">'
                    + GetImageCheck(i - 1, j - 1, False)
                    + '</DIV>';
                  end;
                  {$ENDIF}
                end;


              ctProgress:
                begin
                  Val(ACellValue, l, err);
                  newcell := newcell + '<DIV id="' + FIDS + 'D'
                    + ridxj + 'C' + cidxj + '" style="'+coldisplay+'background-color:' + HTMLClr(Columns[j -
                    1].ProgressColor) + ';width:' + IntToStr(round(Min(l, 100) /
                    100 * Columns[j - 1].Width)) + 'px">';

                  newcell := newcell + FontToTag(ACellFont,'&nbsp;' + ACellValue + '%');

                  newcell := newcell + '</DIV>';
                end;


              ctRowNumber:
                begin

                  if (Columns[j - 1].Font.FontName = Font.FontName) and
                     (Columns[j - 1].Font.Size = Font.Size) and
                     (Columns[j - 1].Font.Color = Font.Color) and
                     (Columns[j - 1].Font.Style = []) and
                     {$IFNDEF TMSIW9}
                     (Columns[j - 1].Font.CSSStyle = Font.CSSStyle) and
                     {$ENDIF}
                      not Assigned(OnGetCellProp) then
                    newcell := newcell + '<DIV style="'
                      + iif((ActiveRowFontColor <> clNone),'color:' + HTMLClr(ACellFont.Color)
                      + ';','') + 'width:100%;'+coldisplay+'" id="' + FIDS + 'D'
                      + ridxj + 'C' + cidxj + '">' + IntToStr(RowOffset + i) + '</DIV>'
                  else
                    newcell := newcell + '<DIV style="' + FontInsert(ACellFont)
                      +'width:100%;'+coldisplay+'" id="' + FIDS + 'D'
                      + ridxj + 'C' + cidxj + '">' +  IntToStr(RowOffset + i) + '</DIV>';
                end;

              ctLinkRowNumber:
                begin
                  newcell := newcell + '<A href="#" id="' + FIDS + 'D'
                    + ridxj + 'C' + cidxj + '"';

                  {$IFDEF TMSIW9}
                  if AsyncActiveRowMove then
                    Acontext.WebApplication.RegisterCallBack(HTMLName+'.DoAsyncGotoRow', DoAsyncGotoRow);
                  {$ENDIF}
                  newcell := newcell + ' onclick="RowMove('+HTMLName+'Obj,'
                  + IntToStr(j - 1) + ',' + IntToStr(i - 1)
                  {$IFDEF TMSIW9}
                    + ',' + HTMLControlImplementation.IWCLName
                  {$ELSE}
                    + ','''''
                  {$ENDIF}
                  + ');"'
                    //+ ' onclick=' + SubmitCall('Move' + IntToStr(i - 1) + ':' + IntToStr(j))

                  + '>' + IntToStr(RowOffset + i) + '</A>';

                  newcell := FontToTag(ACellFont,newcell);
                end;                                                

              ctScroll:
                begin
                //changed direct edit bug
//                  newcell := newcell + '<DIV style="overflow:auto;height:' +
//                    IntToStr(DefaultRowHeight) + 'px">' + FontToTag(ACellFont,ACellValue) + '</DIV>';

                  if (Columns[j - 1].Font.FontName = Font.FontName) and (Columns[j - 1].Font.Size = Font.Size) then
                    newcell := newcell + '<DIV style="'+coldisplay+'overflow:auto;height:100%;width:100%" id="' + FIDS + 'D'
                      + ridxj + 'C' + cidxj + '">' + ACellValue + '</DIV>'
                  else
                    newcell := newcell + FontToTag(ACellFont,'<DIV style="'+coldisplay+'overflow:auto;height:100%;width:100%" id="' + FIDS + 'D'
                      + ridxj + 'C' + cidxj + '">' + ACellValue + '</DIV>');
                end;

              ctPopup:
                begin
                  if Assigned(OnGetCellPopupText) then
                    OnGetCellPopupText(Self, i - 1, j - 1, ACellValue);

                    //popup div
                  tmp :=
                    '<DIV style="color:' + ColorToRGBString(Font.Color) + ';z-index:2;position:absolute;overflow:hidden;width:' +
                    IntToStr(Columns[j - 1].PopupWidth) + 'px;height:' +
                    IntToStr(Columns[j - 1].PopupHeight) +
                    'px;visibility:hidden;border-color:#000000;border-width:1px;border-style:solid;padding:4px; ';

                    if (Columns[j - 1].PopupColorTo <> clNone) then
                      tmp := tmp + GradientStyle(Columns[j - 1].PopupColor, Columns[j - 1].PopupColorTo, Columns[j - 1].PopupColorGradientDirection) + '"'
                    else
                      tmp := tmp + 'background-color:'+ HTMLClr(Columns[j - 1].PopupColor) + '" ';

                  tmp := tmp
                    + 'id="' + FIDS + 'pd'
                    + inttostr(i) + 'c' + inttostr(j) + '">' + ACellValue + '</DIV>';

                  tmp := FontToTag(Columns[j - 1].Font,tmp);

                    //cell div
                  tmp := tmp
                    + '<DIV style="' + FontInsert(ACellFont) + 'overflow:hidden;width:' + IntToStr(Columns[j - 1].Width - 20)
                    + ';height:' + IntToStr(DefaultRowHeight) + 'px" id="' + FIDS + 'pdt'
                    + inttostr(i) + 'c' + inttostr(j) + '">' + ACellValue + '</DIV>';

                  tmp := FontToTag(ACellFont,tmp);

                    //cell table
                  newcell := newcell
                    + '<TABLE border="0" cellpadding="0" cellspacing="0" id="' + FIDS + 'D'
                    + ridxj + 'C' + cidxj + '"';

                  if coldisplay <> EmptyStr then
                    newcell := newcell + ' style="' + coldisplay + '"';

                  newcell := newcell
                    + '><TR><TD>';

                  newcell := newcell + tmp;

                  newcell := newcell
                    + '</TD><TD><INPUT TYPE="BUTTON" style="width:18;" onclick=' +
                    'ExpClick('+HTMLName+'Obj,document.getElementById('#39 + FIDS + 'pd' +
                    IntToStr(i) + 'c' + inttostr(j) + #39')); VALUE="..."></TD></TR></TABLE>';

                end;                                              
              ctImage, ctDataImage:
              begin

                {$IFDEF TMSIW9}
                if Assigned(FOnAsyncImageClick) then
                begin
                    Acontext.WebApplication.RegisterCallBack(HTMLName+'.DoAsyncImageClick', DoAsyncImageClick);
                end;
                {$ENDIF}

                if (pos('<img',ACellValue) > 0) then
                begin
                  newcell := newcell + ACellValue;
                end
                else
                begin
                  if not Assigned(FImages) then
                  begin
                    if (Length(ACellValue) > 0) and (ACellValue <> '&nbsp;') then
                    begin
                      {$IFDEF TMSIW9}
                      if Assigned(FOnAsyncImageClick) or Assigned(FOnImageClick) then
                      begin
                      {$ELSE}
                      if Assigned(FOnImageClick) then
                      begin
                      {$ENDIF}
                        newcell := newcell + '<a href="#" onclick="ImgClick('+HTMLName+'Obj,' + CRPar + ','#39 +
                        {$IFDEF TMSIW9}
                          Columns[j - 1].ClickConfirm + #39','+HTMLControlImplementation.IWCLName+')">'
                        {$ELSE}
                          Columns[j - 1].ClickConfirm + #39','''')">'
                        {$ENDIF}
                          + '<img src="' + ACellValue + '" border=0></a>'
                      end
                      else
                        newcell := newcell + '<img src="' + ACellValue + '" border=0>';
                    end
                    else
                      newcell := newcell + '&nbsp;';
                  end
                  else if Assigned(FImages) then
                  begin

                    if coltype = ctImage then
                      AImageIdx := Columns[j - 1].ImageIndex
                    else
                    begin
                      val(ACellValue, AImageIdx, Err);
                    end;

                    if Assigned(FOnGetImageIdx) then
                      FOnGetImageIdx(Self, i - 1, j - 1, AImageIdx);

                    if (FImages.Count > AImageIdx) and (AImageIdx >= 0) then
                    begin

                      bmp := TBitmap.Create;
                      FImages.BkColor := ACellColor;
                      FImages.GetBitmap(AImageIdx, bmp);

                      {$IFDEF TMSIW9}
                      if Assigned(FOnAsyncImageClick) or Assigned(FOnImageClick) then
                      begin
                      {$ELSE}
                      if Assigned(FOnImageClick) then
                      begin
                      {$ENDIF}
                        newcell := newcell + '<a href="#" onclick="ImgClick('+HTMLName+'Obj,' + CRPar + ','#39 +
                        {$IFDEF TMSIW9}
                          Columns[j - 1].ClickConfirm + #39','+HTMLControlImplementation.IWCLName+')">' + OutputBMPEx('IMG'
                        {$ELSE}
                          Columns[j - 1].ClickConfirm + #39','''')">' + OutputBMPEx('IMG'
                        {$ENDIF}
                          + IntToStr(AImageIdx), bmp, True, '', Columns[j - 1].ImageHeight, Columns[j - 1].ImageWidth) + '</a>'
                      end
                      else
                        newcell := newcell + OutputBMPEx('IMG' + IntToStr(AImageIdx), bmp,
                          True, ACellHint, Columns[j - 1].ImageHeight, Columns[j - 1].ImageWidth);

                      bmp.Free;
                    end
                    else
                      newcell := newcell + '&nbsp;';
                  end;
                end;
              end;
            end;
          end;

          newrow := newrow + newcell + '</TD>';
        end;

        newrow := newrow + '</TR>';

        if HasDetail then
        begin
          if (DetailRowShow = dsAllOpen) or DetailStates[i - 1 + RowOffset] then
            newrow := newrow + '<TR id="' + FIDS + 'DET' + IntToStr(i) +
              '" style="display:;height:' + IntToStr(DetailRowHeight) + 'px">' + DetailRow + '</TR>'
          else
            newrow := newrow + '<TR id="' + FIDS + 'DET' + IntToStr(i) +
              '" style="display:none">' + DetailRow + '</TR>'
        end;

        NextRecord;
      end;
      s := s + newrow;
      newrow := '';
    end;

    s := s + '</TABLE>';

    if (Scroll.Style <> scNever) then
      s := s + '</DIV>';

    s := s + '</TD></TR>';

    //if FNumRows > 0 then
    if (subm <> '') and (FNumRows > 0) then
    begin
      subm := subm + '";' + EOL;
      psubm := psubm + '";' + EOL;
    end;

    if FShowFooter then
    begin
      s := s + '<TR>';

      //RowHeader Footer
      if (RowHeader.FShowRowHeader) then
      begin
       s := s + '<TD width="'+IntToStr(RowHeader.FRowHeaderWidth)+'"';
       // style="background:'+ HTMLClr(RowHeader.FRowHeaderColor) +'">

       s := s + CellColor(RowHeader.Color,RowHeader.Gradient1,RowHeader.Gradient2,RowHeader.GradientDirection);

       if (HeaderStyle = hsRaised) then
       {$IFDEF TMSIW7}
         s := s + RaisedStyle(AContext);
       {$ELSE}
         s := s + RaisedStyle;       
       {$ENDIF}

       s := s + '">&nbsp;</TD>';
       end;

      //Column Footer

   		if (Scroll.Style <> scNever) then
      begin
        if HasPercCols then
          s := s + '<TD style="background:'+ HTMLClr(FooterColor) +';width:100%">'
        else
          s := s + '<TD style="background:'+ HTMLClr(FooterColor) +';width:'+ IntToStr(GridWidth) +'">';
//autosize
//     		s := s + '<DIV id="'+HTMLName+'div4" style="height:22;width:';
     		s := s + '<DIV id="'+HTMLName+'div4" style="width:';

        if HasPercCols then
          s := s +'100%'
        else
        begin
          if (RowHeader.FShowRowHeader) then
            s := s +IntToStr(Width - RowHeader.FRowHeaderWidth)
          else
            s := s +IntToStr(Width);
          s := s+'px';
        end;

        s := s + ';overflow:hidden;">'

        end
        else
          s := s + '<TD>';

      s := s + '<TABLE id="' + HTMLName + '_" border="' +
        IntToStr(FFooterBorders.Width)
        + '" cellpadding="' + IntToStr(FFooterBorders.Padding) + '" cellspacing="' +
        IntToStr(FFooterBorders.Spacing) + '"';

    case FFooterBorders.FInner of
    ibColumns: s := s + ' RULES="cols"';
    ibRows: s := s + ' RULES="rows"';
    ibNone: s := s + ' RULES="none"';
    end;

    case FFooterBorders.FOuter of
    obVertical: s := s + ' FRAME="vsides"';
    obHorizontal: s := s + ' FRAME="hsides"';
    obNone: s := s + ' FRAME="void"';
    end;

    if FFooterBorders.FColor <> clNone then
      s := s + ' bordercolor="' + HTMLClr(FFooterBorders.FColor) + '"';
    if FFooterBorders.FColorLight <> clNone then
      s := s + ' bordercolorlight="' + HTMLClr(FFooterBorders.FColorLight) + '"';

    if FFooterBorders.FColorDark <> clNone then
      s := s + ' bordercolordark="' + HTMLClr(FFooterBorders.FColorDark) + '"';

    if FFooterBorders.Collapsed then
      s := s + ' style="border-collapse:collapse"';
//autosize
//     s := s + ' height="22"';

     if HasPercCols then
       WidthTable := Width
     else
       WidthTable := GetTableWidth(true);

      if ((StretchColumn <> -1 ) and (GridWidth > TotColWidth)) or (Columns[0].WidthType = wtPercent) then
          s := s + ' width="100%"'
      else
          s := s + ' width="'+IntToStr(WidthTable + Borders.Width)+'"';

      s := s + '><TR>';

      for j := 1 to Columns.Count do
      begin
        s := s + '<TD ';

        if isIE then
        begin
          if (Columns[j - 1].FooterGradient1 <> clNone) and
            (Columns[j - 1].FooterGradient2 <> clNone) then
          begin
              s := s + GradientStyle(Columns[j - 1].FooterGradient1,Columns[j - 1].FooterGradient2,Columns[j - 1].ColumnHeaderGradientDirection);
          end
          else
          begin
            s := s + ' style="';
          end
        end
        else
        begin
          s := s + ' style="';
        end;

        //firefox fix

        if (Columns[j - 1].FooterGradient1 <> clNone) then
          s := s + 'background-color:' + HTMLClr(Columns[j - 1].FooterGradient1) + ';'
        else
          s := s + 'background-color:' + HTMLClr(FooterColor) + ';';


        if not Columns[j - 1].Visible then
          s := s + 'display:none;';

     if ((j - 1) = StretchColumn) and (GridWidth > TotColWidth) then
     begin
       if Columns[j - 1].WidthType = wtAbsolute then
         s := s + ' width:' + IntToStr(GridWidth - TotColWidth) + 'px;'
       else
         s := s + ' width:' + IntToStr(GridWidth - TotColWidth) + '%;';
     end
     else
     begin
        if Columns[j - 1].WidthType = wtAbsolute then
          s := s + ' width:'+inttostr(Columns[j - 1].Width)+'px;'
        else
          s := s + ' width:'+inttostr(Columns[j - 1].Width)+'%;'
     end;

        if (HeaderStyle = hsRaised) then
        {$IFDEF TMSIW7}
          s := s + RaisedStyle(AContext);
        {$ELSE}
          s := s + RaisedStyle;        
        {$ENDIF}
{*
        s := s +
          '"><div style="overflow:hidden;';

       if Columns[j - 1].WidthType = wtAbsolute then
         s := s + ' width:' + IntToStr(GridWidth - TotColWidth) + 'px;'
       else
         s := s + ' width:' + IntToStr(GridWidth - TotColWidth) + '%;';
  *}
        s := s +
          '"><TABLE border="0" cellpadding="0" cellspacing="0" width="100%" style="';

        case Columns[j - 1].FooterAlignment of
          taRightJustify: s := s + 'text-align:right;';
          taCenter: s := s + 'text-align:center;';
        end;

        s := s +
          '"><TR><TD>';

        // ' style="width:'+inttostr(Columns[j - 1].Width)+'px"

        colhdr := '';
        temp := '';

        if Columns[j - 1].FooterType = ftPageAvg then
          Columns[j - 1].CalcValue := Columns[j - 1].CalcValue / RowsOnPage;

        coltitle := '';
        case Columns[j - 1].FooterType of
          ftText: coltitle := Columns[j - 1].FooterText;
          ftPageSum, ftPageMin, ftPageMax, ftPageAvg: coltitle :=
            Format(Columns[j - 1].FooterFormat, [Columns[j - 1].CalcValue]);
          ftDynSum, ftDynMin, ftDynMax, ftDynAvg:
            coltitle := '<DIV' + temp + ' id="' + FIDS + 'F' + IntToStr(j - 1) +
              '"></DIV>';
        end;

        if (coltitle = '') then
          coltitle := '&nbsp;';

        colhdr := colhdr + coltitle;

        if FontUsed(FooterFont) then
          s := s + FontToTag(FooterFont,colhdr)
        else
          s := s + FontToTag(Font,colhdr);

        colhdr := colhdr + '</TD>';

        s := s + '</TD>';
        s := s + '</TR></TABLE></TD>'; // </div>

      end;
      s := s + '</TR>';


      s := s + '</TABLE>';

      if (Scroll.Style <> scNever) then
        s := s + '</DIV>';

      s := s + '</TD></TR>';
    end;

    if (Controller.Position in [cpBottom,cpBoth]) and not (RowCount = 0) then
      s := s + GetController(isIE,false,false);

    s := s + '</TABLE>';
     //End Grid

    RenderDone;

    if DState = gsEdit then
      DoEdit;

    if DState = gsInsert then
      DoInsert;

      subm := StringReplace(subm,'\', '\\', [rfReplaceAll]);

    {$IFDEF TMSDEBUG}
    outputdebugstring(pchar('-*-' + subm + '-*-'));
    {$ENDIF}
    
    {$IFDEF TMSIW6}
     with AContext.PageContext as TIWPageContext40 do
     begin
       if WebApplication.IsPartialUpdate then
         TIWComponent40Context(AContext).AddToUpdateInitProc(psubm + EOL)
       else
         TIWComponent40Context(AContext).AddToInitProc(subm + EOL);
     end;
    {$ELSE}
    TIWAppForm(Form).AddToInitProc(subm + EOL);
    {$ENDIF}

    // Code to determine scrollbar width
    {$IFDEF TMSIW6}
     with AContext.PageContext as TIWPageContext40 do
     begin
       if WebApplication.IsPartialUpdate then
         TIWComponent40Context(AContext).AddToUpdateInitProc('IWTop().'+HTMLname + 'sbwidth();')
       else
         TIWComponent40Context(AContext).AddToInitProc(HTMLname + 'sbwidth();');
     end;
    {$ELSE}
    TIWAppForm(Form).AddToInitProc(HTMLname + 'sbwidth();');
    {$ENDIF}

    if Scroll.Persistent then
    begin
    {$IFDEF TMSIW6}
       with AContext.PageContext as TIWPageContext40 do
       begin
         if WebApplication.IsPartialUpdate then
           TIWComponent40Context(AContext).AddToUpdateInitProc('IWTop().'+FIDS + 'ScrollInit();' + EOL)
         else
           TIWComponent40Context(AContext).AddToInitProc(FIDS + 'ScrollInit();' + EOL);
        end;

    {$ELSE}
    TIWAppForm(Form).AddToInitProc(FIDS + 'ScrollInit();' + EOL);
    {$ENDIF}

    end;

    // inplace editors added at end
    s := s + he;

    if FirstEdit <> '' then
    begin
      {$IFDEF TMSIW6}
     with AContext.PageContext as TIWPageContext40 do
     begin
       if WebApplication.IsPartialUpdate then
         TIWComponent40Context(AContext).AddToUpdateInitProc('IWTop().'+FIDS + 'FocusInit("' + FirstEdit + '")' + EOL)
       else
         TIWComponent40Context(AContext).AddToInitProc(FIDS + 'FocusInit("' + FirstEdit + '")' + EOL);
      end;
      {$ELSE}
      TIWAppForm(Form).AddToInitProc(FIDS + 'FocusInit("' + FirstEdit + '")' +
        EOL);
      {$ENDIF}
    end;

    {$IFDEF TMSIW6}
    TIWComponent40Context(AContext).AddToJavaScriptOnce(MakeFormulas(HasDynEdits) + MakeScript + MakeValidates);
    {$ENDIF}

    {$IFNDEF TMSIW6}
    s := s + '<SCRIPT>' + MakeFormulas(HasDynEdits) + MakeScript + MakeValidates + '</SCRIPT>';
    {$ENDIF}

    if HasDynEdits then
    begin
      {$IFDEF TMSIW6}
       with AContext.PageContext as TIWPageContext40 do
       begin
         if WebApplication.IsPartialUpdate then
           TIWComponent40Context(AContext).AddToUpdateInitProc('IWTop().'+FIDS + 'PartialDynInit();' + EOL)
         else
           TIWComponent40Context(AContext).AddToInitProc(FIDS + 'DynInit();' + EOL);
       end;
      {$ELSE}
      TIWAppForm(Form).AddToInitProc(FIDS + 'DynInit();' + EOL);
      {$ENDIF}
    end;

    {
    with AContext.PageContext as TIWPageContext40 do
    begin
      if WebApplication.IsPartialUpdate then
        TIWComponent40Context(AContext).AddToUpdateInitProc('alert("update");'+EOL);
    end;
    }
    Result := s;

    ACellFont.Free;
    ACellDetailFont.Free;
  end;
end;

procedure TTIWCustomWebGrid.RestoreBookmark;
begin

end;

{$IFDEF TMSIW6}
function TTIWCustomWebGrid.RenderHTML(AContext: TIWBaseComponentContext): TIWHTMLTag;
{$ELSE}
function TTIWCustomWebGrid.RenderHTML: TIWHTMLTag;
{$ENDIF}
begin

      {$IFDEF TMSIW9}
      if (AsyncPaging) then
      begin
        Acontext.WebApplication.RegisterCallBack(HTMLName+'.DoAsyncNextPage', DoAsyncNextPage);
        Acontext.WebApplication.RegisterCallBack(HTMLName+'.DoAsyncPrevPage', DoAsyncPrevPage);
        Acontext.WebApplication.RegisterCallBack(HTMLName+'.DoAsyncFirstPage', DoAsyncFirstPage);
        Acontext.WebApplication.RegisterCallBack(HTMLName+'.DoAsyncLastPage', DoAsyncLastPage);
        Acontext.WebApplication.RegisterCallBack(HTMLName+'.DoAsyncGotoPage', DoAsyncGotoPage);
      end;

      if (AsyncSorting) then
        Acontext.WebApplication.RegisterCallBack(HTMLName+'.DoAsyncColumnHeaderClick', DoAsyncColumnHeaderClick);

      if ( (AsyncEdit) and (MouseSelect = msEdit) ) then
      begin
        Acontext.WebApplication.RegisterCallBack(HTMLName+'.DoAsyncEdit', DoAsyncEdit);
      end;
      {$ENDIF}                        

  {$IFDEF TMSIW6}
  with AContext.PageContext as TIWPageContext40 do
  begin
    if not WebApplication.IsPartialUpdate then
      TIWComponent40Context(AContext).AddScriptFile('/js/TMSGRID.js');
  end;
  {$ELSE}
  AddScriptFile('/js/TMSGRID.js');
  {$ENDIF}

  Result := TIWHTMLTag.CreateTag('DIV');

  if OuterBorder.FShow then
    Result.AddStringParam('style','border-width:1;border-style:solid;border-color:'+ HTMLClr(OuterBorder.FColor) +'');

  if FIsDetail then
    Result.Contents.AddText('&nbsp;')
  else
    {$IFDEF TMSIW6}
    Result.Contents.AddText(RenderString(True,AContext));
    {$ELSE}
    Result.Contents.AddText(RenderString(True));
    {$ENDIF}

  //add hidden input
  with Result.Contents.AddTag('INPUT') do
  begin
    AddStringParam('TYPE', 'hidden');
    AddStringParam('NAME', HTMLName);
    AddStringParam('ID', HTMLName + '_INPUT');
  end;
end;                                                                      

procedure TTIWCustomWebGrid.SetRowCount(const Value: Integer);            
begin
  FRowCount := Value;
  UpdateRowCount(Value);
  Invalidate;
end;

{$IFDEF  TMSIW6}
procedure TTIWCustomWebGrid.IWPaint;
{$ELSE}
procedure TTIWCustomWebGrid.Paint;
{$ENDIF}
var
  LWidth, UWidth: Integer;
  fr: TRect;
  a, s, fa, cd: string;
  xsize, ysize, hl, ml: integer;
  hr: trect;
  i,j: Integer;
  xoffs, yoffs, gridheight, footerheight: Integer;

begin
  if FIsDetail then
  begin
    Canvas.Brush.Color := clBtnFace;
    Canvas.Pen.Color := clGray;
    Canvas.Rectangle(0,0,Width - 1,Height - 1);

    Canvas.Pen.Color := clWhite;
    Canvas.MoveTo(0,Height);
    Canvas.LineTo(0,0);
    Canvas.LineTo(Width,0);

    Canvas.TextOut(8,6,'DG');
    Exit;
  end;


  with Canvas do
  begin
    Font.Assign(Self.Font);
    Brush.Style := bsSolid;

    {$IFDEF TMSIW6}
    Brush.Color := clWebWhite;
    {$ELSE}
    {$IFDEF TMSIW51}
    Brush.Color := clWebWhite;
    {$ELSE}
    if Color = clNone then
      Brush.Color := clWindow
    else
      Brush.Color := Color;
    {$ENDIF}
    {$ENDIF}

    Rectangle(ClientRect);

    if Columns.Count > 0 then
      LWidth := Width div Columns.Count
    else
      LWidth := Width;


//  if (Scroll.Style  <> scNever) and (Scroll.Height > 0) then
//    begin
//      gridHeight := Scroll.Height;
//    end
//    else
    begin
      if DefaultRowHeight <> 0 then
        gridHeight := DefaultRowHeight * RowCount
      else
        gridHeight := Height;
    end;

    xoffs := 0;
    yoffs := 0;
    footerheight := 0;

    if Controller.Position in [cpTop,cpBoth] then
    begin
      if Controller.Color <> clNone then
      begin
        Canvas.Brush.Color := Controller.Color;
        Canvas.Brush.Style := bsSolid;
      end;
      if Controller.Height > 0 then
        yoffs := Controller.Height
      else
        yoffs := 20;

      fr := Rect(0, 0, self.Width, yoffs);

      gridHeight := gridHeight + yoffs;
      Rectangle(fr);
      TextOut(1,1,'Page controller');
    end;

    if ShowColumnHeader then
    begin
      yoffs := yoffs + 20;
      gridHeight := gridHeight + DefaultRowHeight;
      if HasSubTitles then
      begin
        yoffs := yoffs + 20;
        gridHeight := gridHeight + DefaultRowHeight;
      end;
    end;

    if ShowFooter then
    begin
      gridHeight := gridHeight + DefaultRowHeight;
      footerheight := DefaultRowHeight;
    end;

    if Controller.Position in [cpBottom,cpBoth] then
    begin
      if Controller.Color <> clNone then
        Canvas.Brush.Color := Controller.Color;
      if Controller.Height > 0 then
        fr := Rect(0, gridHeight + 1, Width, gridHeight + Controller.Height)
      else
        fr := Rect(0, gridHeight + 1, Width, gridHeight + 20);

      Rectangle(fr);
      Canvas.TextOut(1,gridHeight + 2,'Page controller');
      footerheight := footerheight + Controller.Height;
    end;

    for i := 1 to Columns.Count do
    begin
      UWidth := LWidth;
      case Columns[i - 1].WidthType of
        wtNone: UWidth := LWidth;
        wtAbsolute: UWidth := Columns[i - 1].Width - 2;
        wtPercent: UWidth := Round(Width / 100 * Columns[i - 1].Width);
      end;

      UWidth := UWidth + Borders.Padding * 2 + Borders.Width;

      Canvas.Pen.Color := Borders.Color;
      if Canvas.Pen.Color = clNone then
        Canvas.Pen.Color := clBlack;

      Canvas.Pen.Width := Borders.Width;

      if ShowColumnHeader then
      begin
        Canvas.Brush.Color := ColumnHeaderColor;

        Canvas.Font.Color := ColumnHeaderFont.Color;

        if Canvas.Font.Color = clNone then
          Canvas.Font.Color := clBlack;

        if HasSubTitles then
          fr := Rect(xoffs, yoffs - 40, xoffs + UWidth, yoffs - 20)
        else
          fr := Rect(xoffs, yoffs - 20, xoffs + UWidth, yoffs);
        Rectangle(fr);
        InflateRect(fr, -Borders.Width, -Borders.Width);

        HTMLDrawEx(Canvas, Columns[i - 1].Title, fr, nil, 0, 0, -1, -1, 0,
          false, false, false, false, false, false, True, 1.0,
          clBlue, clNone, clNone, clGray, a, s, fa, xsize, ysize, hl, ml, hr
          {$IFNDEF LINUX}
          , ic, nil
          {$ENDIF}
          );

        if HasSubTitles then
        begin
          fr := Rect(xoffs, yoffs - 20, xoffs + UWidth, yoffs);
          Rectangle(fr);
          inflaterect(fr, -Borders.Width, -Borders.Width);

          HTMLDrawEx(Canvas, Columns[i - 1].SubTitle, fr, nil, 0, 0, -1, -1, 0,
            false, false, false, false, false, false, True, 1.0,
            clBlue, clNone, clNone, clGray, a, s, fa, xsize, ysize, hl, ml, hr
            {$IFNDEF LINUX}
            , ic, nil
            {$ENDIF}
            );
        end;
      end;

      if Columns[i - 1].Color <> clNone then
        Canvas.Brush.Color := Columns[i - 1].Color
      else
        Canvas.Brush.Color := clWhite;

      if Canvas.Brush.Color = clNone then
        Canvas.Brush.Color := clWhite;



      if ShowFooter then
      begin
        fr := Rect(xoffs, yoffs, xoffs + UWidth, gridHeight - 20)
      end
      else
        fr := Rect(xoffs, yoffs, xoffs + UWidth, gridHeight);

      Rectangle(fr);

      cd := GetCellData(i - 1, 0);

      if (cd <> '') then
        HTMLDrawEx(Canvas, cd, fr, nil, 0, 0, -1, -1, 0,
          false, false, false, false, false, false, True, 1.0,
          clBlue, clNone, clNone, clGray, a, s, fa, xsize, ysize, hl, ml, hr
          {$IFNDEF LINUX}
          , ic, nil
          {$ENDIF}
          );

      if (i = 1) and (DefaultRowHeight > 0) then
      begin
        for j := 1 to RowCount do
        begin
          if (fr.Top + 2 + (j - 1) * DefaultRowHeight < gridHeight - footerheight ) then
            Canvas.TextOut(fr.Left + 2,fr.Top + 2 + (j - 1) * DefaultRowHeight,IntToStr(j));
        end;
      end;

      if ShowFooter then
      begin
        Canvas.Brush.Color := FooterColor;
        fr := Rect(xoffs, gridHeight - 20, xoffs + UWidth, gridHeight);
        Rectangle(fr);
        inflaterect(fr, -Borders.Width, -Borders.Width);

        HTMLDrawEx(Canvas, Columns[i - 1].FooterText, fr, nil, 0, 0, -1, -1, 0,
          false, false, false, false, false, false, True, 1.0,
          clBlue, clNone, clNone, clGray, a, s, fa, xsize, ysize, hl, ml, hr
          {$IFNDEF LINUX}
          , ic, nil
          {$ENDIF}
          );
      end;

      xoffs := xoffs + UWidth + Borders.Spacing * 2;
    end;

    {$IFNDEF LINUX}
    if (Scroll.Style  <> scNever) then
    begin
      fr := rect(xoffs-16,yoffs,xoffs,yoffs + 16);
      DrawFrameControl(Canvas.Handle,fr,DFC_SCROLL,DFCS_SCROLLUP);
      fr := rect(xoffs-16,gridheight-footerheight - 32,xoffs,gridheight-footerheight - 16);
      DrawFrameControl(Canvas.Handle,fr,DFC_SCROLL,DFCS_SCROLLDOWN);
      fr := rect(xoffs-16,yoffs + 16 ,xoffs,gridheight - footerheight - 32);
      Brush.Color := clBtnFace;
      Pen.Color := clGray;
      Rectangle(fr);
      fr := rect(0,gridheight - footerheight -16,16,gridheight - footerheight);
      DrawFrameControl(Canvas.Handle,fr,DFC_SCROLL,DFCS_SCROLLLEFT);
      fr := rect(xoffs - 32,gridheight - footerheight -16,xoffs-16,gridheight - footerheight);
      DrawFrameControl(Canvas.Handle,fr,DFC_SCROLL,DFCS_SCROLLRIGHT);
      fr := rect(16,gridheight -footerheight - 16,xoffs - 32,gridheight - footerheight);
      Brush.Color := clBtnFace;
      Pen.Color := clGray;
      Rectangle(fr);

    end;
    {$ENDIF}

    {$IFNDEF TMSIW6}
    if FDesignMode then
    {$ENDIF}
    begin
      Brush.Style := bsClear;
      Pen.Style := psDot;
      Pen.Color := clBlack;
      Pen.Width := 1;
      Polygon([Point(0, 0), Point(Width - 1, 0), Point(Width - 1, Height - 1),
        Point(0, Height - 1)]);
      Pen.Style := psSolid;
    end;
  end;
end;

procedure TTIWCustomWebGrid.SetColumns(const Value: TTIWWebGridColumns);
begin
  FColumns.Assign(Value);
end;

procedure TTIWCustomWebGrid.SetController(
  const Value: TTIWAdvWebGridController);
begin
  FController.Assign(Value);
end;

procedure TTIWCustomWebGrid.Submit(const AValue: string);
var
  i, IVal, JVal, err: Integer;
  s: string;
  Allow: Boolean;
begin
  inherited;

  {$IFDEF TMSDEBUG}
  outputdebugstring(pchar('Submit:'+avalue));
  {$ENDIF}

  if AValue = 'Next' then
  begin
    RowOffset := RowOffset + RowCount;
    if Assigned(FOnNextPage) then
      FOnNextPage(Self);
    GotoRecord(RowOffset);
    Exit;
  end;

  if AValue = 'First' then
  begin
    RowOffset := 0;
    if Assigned(FOnFirstPage) then
      FOnFirstPage(Self);
    GotoRecord(RowOffset);
    Exit;
  end;

  if AValue = 'Last' then
  begin
    RowOffset := ((FNumRows - 1) div RowCount) * RowCount;
    if Assigned(FOnLastPage) then
      FOnLastPage(Self);
    GotoRecord(RowOffset);
    Exit;
  end;

  if AValue = 'Prev' then
  begin
    if RowOffset >= RowCount then
      RowOffset := RowOffset - RowCount
    else
      RowOffset := 0;
    if Assigned(FOnPrevPage) then
      FOnPrevPage(Self);
    GotoRecord(RowOffset);
    Exit;
  end;

  if Pos('Goto', AValue) > 0 then
  begin
    s := AValue;                           
    Delete(s, 1, 4);

    val(s, ival, err);

    RowOffset := ival * RowCount;

    if Assigned(FOnGotoPage) then
      FOnGotoPage(Self, ival + 1);

    GotoRecord(RowOffset);

    Exit;
  end;

  if Pos('Move', AValue) > 0 then
  begin
    s := AValue;
    Delete(s, 1, 4);

    if pos(':', s) > 0 then
    begin
      val(copy(s, 1, pos(':', s) - 1), IVal, err);
      val(copy(s, pos(':', s) + 1, length(s)), jval, err);

//      JVal := JVal - 1;

      //changed ActiveRow bug
      if RowCount > 0 then
        RowOffset := ((RowOffset + ival) div RowCount) * RowCount
      else
        RowOffset := 0;

//        FRowOffset := ival;

      if Assigned(FOnGotoRow) then
        FOnGotoRow(Self, ival);

      Allow := True;
      if Assigned(FOnBeforeGotoLink) then
        FOnBeforeGotoLink(Self, IVal, JVal, Allow);

      if Allow then
      begin
      //changed ActiveRow bug
        GotoRecord(RowOffset + ival);
        if Assigned(FOnAfterGotoLink) then
          FOnAfterGotoLink(Self, IVal, JVal);
      end;
    end;
    Exit;
  end;

  if Pos('EditRow', AValue) > 0 then
  begin
    s := AValue;
    Delete(s, 1, 7);
    if pos('G', s) > 0 then
    begin
      val(copy(s, 1, pos('G', s) - 1), IVal, err);
      val(copy(s, pos('G', s) + 1, length(s)), jval, err);
      FEditID := jval;
      FEditRow := RowOffset + ival;
      GotoRecord(FEditRow);
      DoEdit;
    end;
    Exit;
  end;

  if Pos('PostRow', AValue) > 0 then
  begin
    DoPost;
    Exit;
  end;

  if Pos('CancelRow', AValue) > 0 then
  begin
    DoCancel;
    Exit;
  end;

  if Pos('ColClick', AValue) > 0 then
  begin
    s := AValue;
    Delete(s, 1, 8);
    val(s, ival, err);

    ColumnHeaderClick(ival);

    Exit;
  end;

  if Pos('BtnClick', AValue) > 0 then
  begin
    s := AValue;
    Delete(s, 1, 8);
    if pos(':', s) > 0 then
    begin
      val(copy(s, 1, pos(':', s) - 1), IVal, err);
      val(copy(s, pos(':', s) + 1, length(s)), JVal, err);
      if Assigned(OnButtonClick) then
        OnButtonClick(Self, IVal, JVal);
    end;
    Exit;
  end;

  if Pos('LnkClick', AValue) > 0 then
  begin
    s := AValue;
    Delete(s, 1, 8);
    if pos(':', s) > 0 then
    begin
      val(copy(s, 1, pos(':', s) - 1), IVal, err);
      val(copy(s, pos(':', s) + 1, length(s)), JVal, err);
      if Assigned(OnLinkClick) then
        OnLinkClick(Self, IVal, JVal);
    end;
    Exit;
  end;

  if Pos('ComboChange', AValue) > 0 then
  begin
    s := AValue;
    Delete(s, 1, 11);
    if pos(':', s) > 0 then
    begin
      val(copy(s, 1, pos(':', s) - 1), IVal, err);
      delete(s,1,pos(':',s));
      val(copy(s, 1, pos(':', s) - 1), JVal, err);
      delete(s,1,pos(':',s));

      //val(copy(s, pos(':', s) + 1, length(s)), JVal, err);
      if Assigned(OnComboChange) then
        OnComboChange(Self, IVal, JVal, s);
    end;
//    DoPost;

    for i := 1 to FPostData.Count do
      SetCellData(i - 1, 0, FPostData.Strings[i - 1]);

    Exit;
  end;


  if Pos('RowCount', AValue) > 0 then
  begin
    s := AValue;
    Delete(s, 1, 8);
    val(s,IVal,err);
    FRowCount := IVal;
    if Assigned(OnRowCountChange) then
      OnRowCountChange(Self, IVal);

    Exit;
  end;


  if Pos('Filter', AValue) > 0 then
  begin
    s := AValue;
    Delete(s, 1, 6);
    if pos(':', s) > 0 then
    begin
      val(copy(s, 1, pos(':', s) - 1), IVal, err);
      delete(s, 1, pos(':', s));

      Columns[IVal].FilterIndex :=
        Columns[IVal].FilterList.IndexOf(s);

      if Assigned(OnFilterSelect) then
        OnFilterSelect(Self, IVal, s);
    end;
    Exit;
  end;

  if Pos('ImgClick', AValue) > 0 then
  begin
    s := AValue;
    Delete(s, 1, 8);
    if pos(':', s) > 0 then
    begin
      val(copy(s, 1, pos(':', s) - 1), IVal, err);
      val(copy(s, pos(':', s) + 1, length(s)), jval, err);
      if Assigned(OnImageClick) then
        OnImageClick(Self, IVal, JVal);
    end;
    Exit;
  end;

  if Pos('CheckClick', AValue) > 0 then
  begin
    s := AValue;
    Delete(s, 1, 10);
    if pos(':', s) > 0 then
    begin
      val(copy(s, 1, pos(':', s) - 1), IVal, err);
      val(copy(s, pos(':', s) + 1, length(s)), jval, err);
      if Assigned(OnCheckClick) then
        OnCheckClick(Self, IVal, JVal);
    end;
    Exit;
  end;

  if Pos('CellClick', AValue) > 0 then
  begin
    s := AValue;
    Delete(s, 1, 9);
    if pos(':', s) > 0 then
    begin
      val(copy(s, 1, pos(':', s) - 1), IVal, err);
      val(copy(s, pos(':', s) + 1, length(s)), jval, err);
      if Assigned(OnCellClick) then
        OnCellClick(Self, IVal - 1, JVal - 1);
    end;
    Exit;
  end;

  if Pos('ValClick', AValue) > 0 then
  begin
    s := AValue;
    Delete(s, 1, 8);
    if pos(':', s) > 0 then
    begin
      val(copy(s, 1, pos(':', s) - 1), IVal, err);
      delete(s,1,pos(':',s));
      val(copy(s, 1, pos(':', s) - 1), JVal, err);
      delete(s,1,pos(':',s));

      if Assigned(OnValueClick) then
        OnValueClick(Self, IVal - 1, JVal - 1,s);
    end;
    Exit;
  end;

  if Pos('NodeOpen', AValue) > 0 then
  begin
    s := AValue;
    Delete(s, 1, 8);
    begin
      val(s,IVal, err);
      DoNodeOpen(IVal - 1);

      if Assigned(DetailGrid) and (DetailRowShow = dsServerOneOpen) then
        DetailGrid.RowOffset := 0;
    end;
    Exit;
  end;

  if Pos('NodeClose', AValue) > 0 then
  begin
    s := AValue;
    Delete(s, 1, 9);
    begin
      val(s,IVal, err);
      DoNodeClose(IVal - 1);
    end;
    Exit;
  end;

  if Pos('EditClick', AValue) > 0 then
  begin
    s := AValue;
    Delete(s, 1, 9);
    if pos(':', s) > 0 then
    begin
      val(copy(s, 1, pos(':', s) - 1), IVal, err);
      GotoRecord(RowOffset + iVal - 1);
      Edit;
      DoEdit;
    end;
    Exit;
  end;

end;

procedure TTIWCustomWebGrid.SetShowColumnHeader(const Value: Boolean);
begin
  FShowColumnHeader := Value;
  {$IFNDEF LINUX}
  Changed;
  {$ENDIF}
end;

procedure TTIWCustomWebGrid.SetColumnHeaderColor(const Value: TIWColor);
begin
  FColumnHeaderColor := Value;
  Invalidate;
  {$IFNDEF LINUX}
  Changed;
  {$ENDIF}
end;

procedure TTIWCustomWebGrid.SetPage(const Value: Integer);
begin
  RowOffset := RowCount * Value;
  FPage := Value;
  GotoRecord(RowOffset);
end;

function TTIWCustomWebGrid.GetPage: Integer;
begin
  if RowCount > 0 then
    Result := RowOffset div RowCount
  else
    Result := -1;
end;

procedure TTIWCustomWebGrid.SetHoverColor(const Value: TIWColor);
begin
  FHoverColor := Value;
end;

procedure TTIWCustomWebGrid.SetHoverFontColor(const Value: TIWColor);
begin
  FHoverFontColor := Value;
end;

procedure TTIWCustomWebGrid.SetSelectColor(const Value: TIWColor);
begin
  FSelectColor := Value;
end;

function TTIWCustomWebGrid.HTMLClr(AColor: TIWColor): string;
begin
  Result := ColorToRGBString(AColor);
end;

procedure TTIWCustomWebGrid.SetSelectFontColor(const Value: TIWColor);
begin
  FSelectFontColor := Value;
end;

procedure TTIWCustomWebGrid.SetDefaultRowHeight(const Value: Integer);
begin
  FDefaultRowHeight := Value;
  Invalidate;
end;

procedure TTIWCustomWebGrid.SetColumnHeaderFont(const Value: TIWFont);
begin
  FColumnHeaderFont.Assign(Value);
  Invalidate;
end;

procedure TTIWCustomWebGrid.SetBands(const Value: TTIWAdvWebGridBands);
begin
  FBands := Value;
end;

procedure TTIWCustomWebGrid.GetCellProp(RowIndex, ColumnIndex: Integer;
  AValue: string; var AColor: TIWColor; var AAlignment: TAlignment;
  AFont: TIWFont);
begin
  if FBands.Active and (RowIndex <> FPageOffset) then
  begin
    if odd(RowIndex) then
      AColor := FBands.PrimaryColor
    else
      AColor := FBands.SecondaryColor;
  end;

  if Assigned(FOnGetCellProp) then
    FOnGetCellProp(Self, RowIndex, ColumnIndex, AValue, AColor, AAlignment,
      AFont);
end;

function TTIWCustomWebGrid.DirectEditUpdate(ACol,ARow: Integer;var value: string): Boolean;
var
  Allow: Boolean;
begin
  Allow := true;
  if Assigned(FOnDirectEditUpdate) then
    FOnDirectEditUpdate(Self,ACol,ARow,Value,Allow);

  Result := Allow;
end;

procedure TTIWCustomWebGrid.SetValue(const AValue: string);
var
  i, j, vp, err, ecol, erow, sp, dynp: Integer;
  su, ss: string;
  VarVal: string;
  FCheckValue: string;
  {$IFDEF TMSIW9}
  AsyncVal: string;
  posval, val1, val2: integer;
  {$ENDIF}
  //RowsReturned: integer;

  function AdaptForPage(s: string; Offset: Integer; var ACol, ARow: Integer):
      string;
  var
    sval: string;
    r, err: Integer;
  begin
    delete(s, 1, 1);

    if pos('C', s) > 0 then
    begin
      sval := copy(s, pos('C', s), length(s));
      s := copy(s, 1, pos('C', s) - 1);
      val(s, r, err);
      r := r + RowOffset;
      s := sval;
      delete(s, 1, 1);
      s := copy(s, 1, pos('^', s) - 1);
      val(s, ACol, err);

      delete(sval, 1, pos('^', sval));
      ARow := r;

      if (Columns[ACol].ColumnType = ctDynCheckBox) then
      begin
        if (uppercase(sval) = 'ON') or (uppercase(sval) = 'TRUE') or (uppercase(sval) = '1') then
          Result := '1'
        else
          Result := '0';
      end
      else
        Result := sval;
    end
    else
      Result := s;
  end;

begin
 // inherited;

  {$IFDEF TMSDEBUG}
  outputdebugstring(pchar('SetValue:'+Name + ' * ' + avalue));
  {$ENDIF}

  {$IFDEF TMSIW9}
  Asyncval := Avalue;

  posval := pos('|chclick', AsyncVal);
  if posval > 0 then
  begin
    val1 := length(AsyncVal);
    SortSettings.Column := StrToInt(Copy(AsyncVal, posval + 8, val1 ));
  end;                  

  posval := pos('|gotop', AsyncVal);
  if posval > 0 then
  begin
    val1 := length(AsyncVal);
    Page := StrToInt(Copy(AsyncVal, posval + 6, val1 ));
  end;

  posval := pos('|gotor', AsyncVal);
  if posval > 0 then
  begin
    val1 := length(AsyncVal);
    FCellRow := StrToInt(Copy(AsyncVal, posval + 6, val1 ));
  end;

  posval := pos('|editrow', AsyncVal);
  if posval > 0 then
  begin
    val1 := length(AsyncVal);
    FEditRow := RowOffset + StrToInt(Copy(AsyncVal, posval + 8, val1 ));
  end;

  posval := pos('|cellval', AsyncVal);
  if posval > 0 then
  begin
    val1 := pos('|cellr', AsyncVal);
    FCellValue := Copy(AsyncVal, posval + 8, val1 - (posval + 8) );
  end;

  posval := pos('|rselr', AsyncVal);
  if posval > 0 then
  begin
    val1 := pos('|rselc', AsyncVal);
    val2 := length(AsyncVal);
    FCellRow := StrToInt(Copy(AsyncVal, posval + 6, val1 - (posval + 6) ));
    if Copy(AsyncVal, val1 + 6, val2 ) = 'true' then
      FChecked := true
    else
      FChecked := false;
  end;

  posval := pos('|cellr', AsyncVal);
  if posval > 0 then
  begin
    val1 := pos('|cellc', AsyncVal);
    val2 := length(AsyncVal);
//    Copy(S, StartPoint, EndPoint + 1 - StartPoint);
    FCellRow := StrToInt(Copy(AsyncVal, posval + 6, val1 - (posval + 6) ));
    FCellCol := StrToInt(Copy(AsyncVal, val1 + 6, val2 ));
  end;

  {$ENDIF}

  varval := AValue;

  FPostData.Clear;
  {
  if RowCount = 0 then
    RowsReturned := FNumRows
  else
    RowsReturned := RowCount;
  }

  for i := 0 to Columns.Count + 3 do
  begin
    vp := pos('|', VarVal);
    if vp > 0 then
    begin
      su := copy(VarVal, 1, vp - 1);
      Delete(VarVal, 1, vp);
    end
    else
    begin
      su := VarVal;
      VarVal := '';
    end;

    {$IFDEF TMSDEBUG}
    outputdebugstring(pchar('after copy :' + su + '*'));
    {$ENDIF}
    case i of
    0: // retrieve the checkboxes states
      begin
        FCheckValue := su;

        if (Length(FCheckValue) >= 0) then
        begin
          for j := 1 to Length(FCheckValue) do
          begin
            if FCheckValue[j] = '1' then
              FSelectList.Items[RowOffset + j - 1] := 1
            else
              FSelectList.Items[RowOffset + j - 1] := 0;
          end;
        end;
      end;
    1: // retrieve the radiobutton selection
      begin
        delete(su, 1, 1);
        val(su, FRadioSelection, err);
        FRadioSelection := FRadioSelection - 1;
      end;
    2: // retrieve scroll position
      begin
        sp := pos('^', su);
        if sp > 0 then
        begin
          ss := copy(su, 1, sp - 1);
         Delete(su, 1, sp);
        end
        else
          ss := su;

        val(ss, FScrollPos, err);

        sp := pos('^', su);
        if sp > 0 then
        begin
          ss := copy(su, sp + 1, sp - Length(su));
         Delete(su, 1, sp);
        end
        else
          ss := su;

        val(ss, FScrollLeft, err);
      end;
    3: // retrieve detail states here
      begin
        FCheckValue := su;
        if (Length(FCheckValue) >= 0) then
        begin
          if FCheckValue <> 'x' then
          begin
            for j := 1 to Length(FCheckValue) do
            begin
              if FCheckValue[j] = '1' then
                FDetailStates[RowOffset + j - 1] := 1
              else
                FDetailStates[RowOffset + j - 1] := 0;
            end;
          end;
        end;
      end;
      else
      begin
        // retrieve normal cell data
        if su = '&nbsp;' then
          su := '';
        FPostData.Add(su);
        if not FDirectPost then
        begin
          SetCellData(i - 4, 0, su);
        end;
      end;
    end;
  end;

  {$IFDEF TMSDEBUG}
  outputdebugstring(pchar('varval:'+varval));
  {$ENDIF}

  // dyn edit & direct edit updates
  while (VarVal <> '') do
  begin
    vp := pos('|', VarVal);
    if vp > 0 then
    begin
      su := copy(VarVal, 1, vp - 1);
      Delete(VarVal, 1, vp);
    end
    else
    begin
      su := VarVal;
      VarVal := '';
    end;

    dynp := pos('^', su);
    if dynp > 0 then
    begin
      if pos('E',su) = 1 then
      begin
        su := AdaptForPage(su, RowOffset, ecol, erow);
        DirectEditUpdate(ecol,erow,su);
      end
      else
      begin
        su := AdaptForPage(su, RowOffset, ecol, erow);
        DynEdits[ecol, erow] := su;
      end;
    end;
  end;                                                             
                                                                      
  {$IFDEF TMSDEBUG}                                                 
  outputdebugstring(' DYN EDIT LIST ');                                
  for i := 1 to FDynEdits.Count do
    outputdebugstring(pchar(FDynEdits.Strings[i - 1]));
  outputdebugstring(' DYN EDIT LIST ');
  {$ENDIF}

end;


procedure TTIWCustomWebGrid.DeleteSelection(i: Integer);
begin
  if i < FSelectList.Count then
    FSelectList.Delete(i);
end;

function TTIWCustomWebGrid.GetRowSelect(r: Integer): Boolean;
begin
  Result := FSelectList.Items[r] = 1;
end;

procedure TTIWCustomWebGrid.SetRowSelect(r: Integer; const Value: Boolean);
begin
  if Value then
    FSelectList.Items[r] := 1
  else
    FSelectList.Items[r] := 0;
end;

procedure TTIWCustomWebGrid.GotoRecord(RecordIndex: Integer);
begin
end;

procedure TTIWCustomWebGrid.SetIndicators(const Value: TTIWRGIndicators);
begin
  FIndicators.Assign(Value);
end;

procedure TTIWCustomWebGrid.SetBorders(const Value: TTIWRGBorders);
begin
  FBorders.Assign(Value);
end;

procedure TTIWCustomWebGrid.SetColumnSizing(const Value: Boolean);
begin
  FColumnSizing := Value;
  {$IFDEF TMSIW6}
  SetRenderSize(not Value);
  {$ELSE}
  FRenderSize := not Value;
  {$ENDIF}
end;

procedure TTIWCustomWebGrid.SetSortSettings(
  const Value: TTIWRGSortSettings);
begin
  FSortSettings.Assign(Value);
end;

procedure TTIWCustomWebGrid.SetFooterColor(const Value: TIWColor);
begin
  FFooterColor := Value;
  Invalidate;
end;

procedure TTIWCustomWebGrid.SetFooterFont(const Value: TIWFont);
begin
  FFooterFont.Assign(Value);
end;

procedure TTIWCustomWebGrid.SetShowFooter(const Value: Boolean);
begin
  FShowFooter := Value;
  Invalidate;
end;

procedure TTIWCustomWebGrid.Notification(AComponent: TComponent;
  AOperation: TOperation);
begin
  inherited;
  if (AOperation = opRemove) and (AComponent = FImages) then
    FImages := nil;
  if (AOperation = opRemove) and (AComponent = FDetailGrid) then
    FDetailGrid := nil;
end;

function TTIWCustomWebGrid.GetLookupValues(ACol: Integer; ACellValue: string):
  string;
begin

end;

function TTIWCustomWebGrid.GetLookupValue(ACol: Integer; ACellValue: string):
  string;
begin
end;

procedure TTIWCustomWebGrid.SetGlyphs(const Value: TTIWRGGlyphs);
begin
  FGlyphs.Assign(Value);
end;

procedure TTIWCustomWebGrid.ClearImageCache;
begin
  FCache.Clear;
end;  

procedure TTIWCustomWebGrid.ClearRowSelect;
var
  i: Integer;
begin
  for i := 1 to FSelectList.Count do
  begin
    FSelectList.Items[i - 1] := 0;
  end;
  Invalidate;
end;

function TTIWCustomWebGrid.GetDynEdits(col, row: Integer): string;
var
  i: Integer;
  s: string;
begin
  if Columns.Count > col then
    Result := Columns[col].DefaultDynEdit;

  s := 'E' + inttostr(row) + 'C' + inttostr(col) + '^';

  for i := 1 to FDynEdits.Count do
  begin
    if (pos(s, FDynEdits.Strings[i - 1]) = 1) then
    begin
      Result := Copy(FDynEdits.Strings[i - 1], pos('^', FDynEdits.Strings[i - 1]) + 1, 255);
      Break;
    end;
  end;
end;

procedure TTIWCustomWebGrid.SetDynEdits(col, row: Integer; const Value: string);
var
  i: Integer;
  s: string;
begin
  s := 'E' + inttostr(row) + 'C' + inttostr(col) + '^';
  for i := 1 to FDynEdits.Count do
  begin
    if (pos(s, FDynEdits.Strings[i - 1]) = 1) then
    begin
      FDynEdits.Strings[i - 1] := s + value;
      Exit;
    end;
  end;
  FDynEdits.Add(s + value);
  Invalidate;
end;

procedure TTIWCustomWebGrid.ClearDynEdits;
begin
  FDynEdits.Clear;
  Invalidate;
end;

procedure TTIWCustomWebGrid.ClearCells;
begin

end;

procedure TTIWCustomWebGrid.ClearDetailStates;
begin
  FDetailStates.Clear;
  Invalidate;
end;

function TTIWCustomWebGrid.CreateColumns: TTIWWebGridColumns;
begin
  Result := TTIWWebGridColumns.Create(Self);
end;

function TTIWCustomWebGrid.GetColumnTitle(ACol: Integer): string;
begin
end;

procedure TTIWCustomWebGrid.DoEdit;
begin
  if Assigned(OnEdit) then
    OnEdit(Self);
end;

procedure TTIWCustomWebGrid.DoCancel;
begin
  if Assigned(OnCancel) then
    OnCancel(Self);
end;

function TTIWCustomWebGrid.DoPost(postalways:boolean=false): Boolean;
var
  i: Integer;
  allow: Boolean;
begin

  Allow := True;
  if Assigned(OnPostValidate) then
    OnPostValidate(Self, FPostData, Allow);

  if Allow then
  begin
    for i := 1 to FPostData.Count do
    begin
      SetCellData(i - 1, 0, FPostData.Strings[i - 1],postalways);
    end;
  end;

  if Assigned(OnPost) then
    OnPost(Self);  

  Result := Allow;
end;

procedure TTIWCustomWebGrid.SetCellData(ACol, ARow: Integer;
  Value: string;postalways:boolean=false);
begin
end;

function TTIWCustomWebGrid.GetGridState: TTIWGridState;
begin
  Result := gsBrowse;
end;

function TTIWCustomWebGrid.IsDBAware: boolean;
begin
  Result := false;
end;

function TTIWCustomWebGrid.IsValidRow(ARow: integer): boolean; 
begin
  Result := true;
end;

procedure TTIWCustomWebGrid.GetRowInfo(var NumRows, RowOffset, PageOffset:
  Integer);
begin

end;

procedure TTIWCustomWebGrid.DoInsert;
begin

end;

procedure TTIWCustomWebGrid.RenderDone;
begin

end;
                                
function TTIWCustomWebGrid.RenderPrepare: Boolean;
begin
  Result := True;
end;

function TTIWCustomWebGrid.NextRecord: boolean;
begin
  Result := false;
end;

procedure TTIWCustomWebGrid.Edit;
begin

end;

procedure TTIWCustomWebGrid.SetRowOffset(AValue: Integer);
begin
  RowOffset := AValue;
end;

procedure TTIWCustomWebGrid.SetRowOffsetTemp(const Value: Integer);
begin
  if (Value < 0) then
    FRowOffset := 0
  else
    FRowOffset := Value;
end;

function TTIWCustomWebGrid.HasSubTitles: Boolean;
var
  i: Integer;
begin
  Result := False;
  for i := 1 to Columns.Count do
  begin
    if Columns[i - 1].SubTitle <> '' then
      Result := True;
  end;
end;

function TTIWCustomWebGrid.HasDetail: Boolean;
var
  i: Integer;
begin
  Result := False;
  for i := 1 to Columns.Count do
  begin
    if (Columns[i - 1].DetailTemplate <> '') or (Columns[i - 1].DetailSpan <> 0) then
      Result := True;
  end;
end;

procedure TTIWCustomWebGrid.SetID(const Value: Integer);
begin
  FID := Value;
  FIDS := 'G' + IntToStr(FID);
end;

procedure TTIWCustomWebGrid.SetCheckFalsePicture(const Value: TIPicture);
begin
  FCheckFalsePicture.Assign(Value);
end;

procedure TTIWCustomWebGrid.SetCheckTruePicture(const Value: TIPicture);
begin
  FCheckTruePicture.Assign(Value);
end;

procedure TTIWCustomWebGrid.ColumnHeaderClick(AColumn: Integer);
begin

  if GetGridState = gsBrowse then
  begin
    {$IFDEF TIMSIW9}
    if (not AsyncPaging) and Assigned(OnColumnHeaderClick) then
    {$ELSE}
    if Assigned(OnColumnHeaderClick) then
    {$ENDIF}
        OnColumnHeaderClick(Self, AColumn);
  end;
end;

function TTIWCustomWebGrid.RenderSpin(Name: string; MaxLength, Width: Integer;
  Alignment: TAlignment;
  AFontStyle: string; CellValue: string; AColor: TIWColor;
  MaxValue: Integer; MinValue: Integer;
  AutoSpin: Boolean;
  blurevent: string; isIE: bool): string;
var
  htmlres, ubtnval, dbtnval: string;

  function MakeAlign(AAlignment: TAlignment): string;
  begin
    Result := '';
    case AAlignment of
      taRightJustify: Result := 'text-align:right;';
      taCenter: Result := 'text-align:center;';
    end;
  end;

  function MakeScript(Name: string): string;
  begin
    Result :=
      '<Script Language="JavaScript">'#13

        + 'var '+Name+'decrement;'#13
        + 'var '+Name+'increment;'#13
        + 'var '+Name+'cancel = false;'#13

        + 'function '+Name+'UpdateVal(ctrl){'#13
        + '  if (ctrl.value > '+IntToStr(MaxValue)+' || ctrl.value < '+IntToStr(MinValue)+')'#13
        + '  ctrl.value = 0;'#13
        + 'if ('+Name+'cancel == false){'#13
        +   blurevent
        + ' }'#13
        + '}'#13

        + 'function ' + Name + 'HandleMin(ctrl)'#13
        + ' {'#13
        + '  s = ctrl.value'#13
        + '  if (s.indexOf("-") == -1)'#13
        + '    ctrl.value = "-" + s;'#13
        + '  else'#13
        + '    ctrl.value = s.substring(1);'#13
        + '}'#13

        + 'function ' + Name + 'StartSpinUp(el)'#13
        + ' {'#13
        + '  if ( (el.value == "") || (parseInt(el.value) + "" == "NaN") ) el.value = "0";'#13
        + '  if (el.value < '+IntToStr(MaxValue)+')'#13
        + '   el.value = parseInt(el.value) + 1;'#13
        + ' el.focus();'#13
        + '}'#13

        + 'function ' + Name + 'StartSpinDown(el)'#13
        + ' {'#13
        + '  if ( (el.value == "") || (parseInt(el.value) + "" == "NaN") ) el.value = "0";'#13
        + '  if (el.value > '+IntToStr(MinValue)+')'#13
        + '   el.value = parseInt(el.value) - 1;'#13
        + ' el.focus();'#13
        + '}'#13

        + ' function '+Name+'StopSpin()'#13
        + ' {'#13
        + ' clearInterval('+Name+'increment);'#13
        + ' clearInterval('+Name+'decrement);'#13
        + ' el = document.getElementById("'+Name+'")'#13
        + ' el.focus();'#13
        + Name + 'cancel = false;'#13
        + '}'#13

       + 'function '+Name+'ClickProc(editctrl,ctrl) {'#13
        + Name + 'cancel = true;'#13
        + ' el = document.getElementById("'+Name+'")'#13
        + ' if (ctrl==1){'#13
        + ' '+Name+'StartSpinUp(el)'#13
        + IIF (AutoSpin, Name+'increment = setInterval("'+Name+'StartSpinUp(el)",200);', '')
        + '  } else{'#13
        + ' '+Name+'StartSpinDown(el)'#13
        + IIF (AutoSpin, Name+'decrement = setInterval("'+Name+'StartSpinDown(el)",200);', '')
         + '  }'#13

        + '}'#13

    + 'function ' + Name + 'KeyPress(ctrl,edittype,event) {'#13
      + ' key = (isIE) ? event.keyCode : event.which;'#13
      + ' if (edittype == 1) { '#13
      + '  if (key < 48 || key > 57) { event.returnValue = false; return false;}'#13
      + '  if (key == 45) return' + Name + 'HandleMin(ctrl);'#13
      + '  } '#13
      + '}'#13
      + 'function ' + Name + 'Focus(ctrl) {'#13
      + Name + 'cancel = false;'#13
      + '}'
      + '</Script>';
  end;

  function StripCRLF(s: string): string;
  begin
    while pos(#13, s) > 0 do
      delete(s, pos(#13, s), 1);
    while pos(#10, s) > 0 do
      delete(s, pos(#10, s), 1);
    Result := s;
  end;

begin
  if Glyphs.FSpinEditButtonUpImageURL <> EmptyStr then
    begin
      ubtnval := '<img src="' + Glyphs.FSpinEditButtonUpImageURL + '" '
        +iif(enabled,' onMouseUp="'+Name+'StopSpin();" onMouseOut="'+Name+'StopSpin();" onMouseDown="'+Name+'ClickProc('+Name+',1);"', '') + '>';
    end
    else if Glyphs.FSpinEditButtonUpImage.Empty then
    begin

      if (isIE) then
      begin
       ubtnval := ubtnval
       + '<BUTTON id="'+Name+'upbtnIE" '+iif(enabled,'',' DISABLED')+ ' onMouseUp="'+Name+'StopSpin();" onMouseOut="'+Name+'StopSpin();" onMouseDown="'+Name+'ClickProc('+Name
       +',1);" style="display:;width:18px;height:14px;vertical-align:middle;text-align:center;padding:0px;top:-4px;position:relative;">'
       + ' <DIV style=" font-family:Webdings;font-size:9pt;margin:0px;padding:0px;border:0px;margin-top:-0.4em;margin-right:-0.1em;">'
       + ' 5</DIV></BUTTON>'#13;
      end
      else
      begin
       ubtnval := ubtnval
       + '<BUTTON id="'+Name+'upbtnNS" '+iif(enabled,'',' DISABLED')+ ' onMouseUp="'+Name+'StopSpin();" onMouseOut="'+Name+'StopSpin();" onMouseDown="'+Name+'ClickProc('+
       HTMLName+',1);return false;" style="width:18px;height:14px;vertical-align:middle;text-align:center;padding:0px;top:-1px;position:relative;">'
       +' <DIV style="font-size:9pt;margin:-2px;padding:-1px;position:relative;top:-5;border:0px;margin-top:-0em;margin-right:0em;">'
       +'+</DIV></BUTTON>'#13;
      end;

    end
    else
    begin

      if Glyphs.FSpinEditButtonUpImage.IsGIF then
      {$IFDEF TMSIW71}
        ubtnval := TIWServerControllerBase.NewCacheFile('gif', true)
      {$ELSE}
        ubtnval := TIWServerControllerBase.NewCacheFile('gif')
      {$ENDIF}
      else
      {$IFDEF TMSIW71}
        ubtnval := TIWServerControllerBase.NewCacheFile('jpg', true);
      {$ELSE}
        ubtnval := TIWServerControllerBase.NewCacheFile('jpg');
      {$ENDIF}

      Glyphs.FSpinEditButtonUpImage.SaveToFile(ubtnval);

      ubtnval := '<img src="' + GetCacheDir(Self) + ExtractFilename(ubtnval)+ '" '
        +iif(enabled,' onMouseUp="'+Name+'StopSpin();" onMouseOut="'+Name+'StopSpin();" onMouseDown="'+Name+'ClickProc('+Name+',1);"', '') + '>';

    end;

    if Glyphs.FSpinEditButtonDownImageURL <> EmptyStr then
    begin
      dbtnval := '<img src="' + Glyphs.FSpinEditButtonDownImageURL + '" '
        +iif(enabled,' onMouseUp="'+Name+'StopSpin();" onMouseOut="'+Name+'StopSpin();" onMouseDown="'+Name+'ClickProc('+Name+',2);"', '') + '>';
    end
    else if Glyphs.FSpinEditButtonDownImage.Empty then
    begin

      if (isIE) then
      begin
       dbtnval := dbtnval
       + ' <BUTTON id="'+Name+'dnbtnIE" '+iif(enabled,'',' DISABLED')+ ' onMouseUp="'+Name+'StopSpin();" onMouseOut="'+Name+'StopSpin();" onMouseDown="'+Name+'ClickProc('+Name+
       ',2);" style="display:;width:18px;height:14px;vertical-align:middle;text-align:center;padding:0px;top:-11px;position:relative;">'
       + ' <DIV style=" font-family:Webdings;font-size:9pt;margin:0px;padding:0px;border:0px;margin-top:-0.4em;margin-right:-0.1em;">'
       + ' 6</DIV></BUTTON>'#13;
      end
      else
      begin
       dbtnval := dbtnval
       + '<BUTTON id="'+Name+'dnbtnNS" '+iif(enabled,'',' DISABLED')+ ' onMouseUp="'+Name+'StopSpin();" onMouseOut="'+Name+'StopSpin();" onMouseDown="'+Name+'ClickProc('
       + Name+',2);return false;" style="width:18px;height:14px;vertical-align:middle;text-align:center;padding:0px;top:-5px;position:relative;">'
       +' <DIV style="font-size:9pt;margin:-2px;padding:-5px;position:relative;top:-1;border:0px;margin-top:-0.4em;margin-right:0em;">'
       +'-</DIV></BUTTON>'#13;
      end;

    end
    else
    begin

      if Glyphs.FSpinEditButtonDownImage.IsGIF then
      {$IFDEF TMSIW71}
        dbtnval := TIWServerControllerBase.NewCacheFile('gif', true)
      {$ELSE}
        dbtnval := TIWServerControllerBase.NewCacheFile('gif')
      {$ENDIF}
      else
      {$IFDEF TMSIW71}
        dbtnval := TIWServerControllerBase.NewCacheFile('jpg', true);
      {$ELSE}
        dbtnval := TIWServerControllerBase.NewCacheFile('jpg');
      {$ENDIF}

      Glyphs.FSpinEditButtonDownImage.SaveToFile(dbtnval);

      dbtnval := '<img src="' + GetCacheDir(Self) + ExtractFilename(dbtnval)+ '" '
        +iif(enabled,' onMouseUp="'+Name+'StopSpin();" onMouseOut="'+Name+'StopSpin();" onMouseDown="'+Name+'ClickProc('+Name+',2);"', '') + '>';

    end;

  htmlres :=
    MakeScript(Name)
    + '<table cellspacing="0" cellpadding="0" border="0" style="border-collapse: collapse"><tr>'#13
    + '<td rowspan="2">'#13
    + '<input autocomplete="off" type="input" name="'+Name+'" id="' + Name + '"'
    + IIF(MaxLength > 0, ' maxlength=' + IntToStr(MaxLength)) //+ AFontStyle
    + ' style="border-width:0;width:'+IntToStr(Width-16)+'px;' + IIF(AColor <> clWindow, 'background-color:' + HTMLClr(AColor),'')+';'+IIF(Alignment <> taLeftJustify, MakeAlign(Alignment))+'" '
    + ' value="' + CellValue + '"'
    + ' onKeyPress="return ' + Name + 'KeyPress(this,1,event);"'
    + ' onFocus="return ' + Name + 'Focus(this);" onBlur="return '+Name+'UpdateVal(this);"'
    + '></td>'#13;

   htmlres := htmlres

     + '<td valign="bottom">'#13
     + ubtnval
     + ' </div>'#13
     + ' </td></tr>'#13
     + ' <tr><td valign="top">'#13
     + dbtnval
     + ' </div>'#13
     + ' </td>'#13

     + ' </tr></table>';

  Result := htmlres;
end;


function TTIWCustomWebGrid.RenderCalendar(Name: string; Width: Integer;
  AFontName: string; AFontSize: Integer;
  blurevent, cellvalue: string; AColor: TIWColor): string;
var
  i: integer;
  reshandle: THandle;
  hglobal: THandle;
  ressize: dword;
  ptr: pointer;
  html: string;
  Day, Month, Year: Word;
  p: ansichar;

begin
  try
    DecodeDate(DateStrToDate(CellValue), Year, Month, Day);
  except
    DecodeDate(Now, Year, Month, Day);
  end;

  reshandle := FindResource(hinstance, 'TMSIWGRID', RT_RCDATA);
  hglobal := LoadResource(hinstance, reshandle);
  Ressize := SizeOfResource(hinstance, reshandle);
  ptr := LockResource(hglobal);

  html := '';
  for i := 1 to ressize do
  begin
    p := ansichar(ptr^);
    html := html + string(p);
    ptr := pointer(integer(ptr) + 1);
  end;

  html := StringReplace(html, '<#BKCOLOR>', HTMLClr(clWhite), [rfReplaceAll, rfIgnoreCase]);
  html := StringReplace(html, '<#HDRCOLOR>', HTMLClr(clWhite), [rfReplaceAll, rfIgnoreCase]);
  html := StringReplace(html, '<#WKCOLOR>', HTMLClr(clWhite), [rfReplaceAll, rfIgnoreCase]);
  html := StringReplace(html, '<#FNTCOLOR>', HTMLClr(clBlack), [rfReplaceAll, rfIgnoreCase]);
  html := StringReplace(html, '<#SELCOLOR>', HTMLClr(clred), [rfReplaceAll, rfIgnoreCase]);
  html := StringReplace(html, '<#HOVERCOLOR>', HTMLClr(clblue), [rfReplaceAll, rfIgnoreCase]);
  html := StringReplace(html, '<#FNTIWColor>', HTMLClr(clblack), [rfReplaceAll, rfIgnoreCase]);
  html := StringReplace(html, '<#FONTNAME>', AFontName, [rfReplaceAll, rfIgnoreCase]);
  html := StringReplace(html, '<#FONTSIZE>', IntToStr(AFontSize), [rfReplaceAll, rfIgnoreCase]);
  html := StringReplace(html, '<#SELMONTH>', IntToStr(10), [rfReplaceAll, rfIgnoreCase]);
  html := StringReplace(html, '<#SELYEAR>', IntToStr(2002), [rfReplaceAll, rfIgnoreCase]);
  html := StringReplace(html, '<#SELDAY>', IntToStr(1), [rfReplaceAll, rfIgnoreCase]);
  html := StringReplace(html, '<#COMPNAME>', Name + 'N', [rfReplaceAll, rfIgnoreCase]);
  html := StringReplace(html, '<#VALUEID>', Name , [rfReplaceAll, rfIgnoreCase]);

  html := StringReplace(html, '<#COLWIDTH>', IntToStr(Width div 7),
    [rfReplaceAll, rfIgnoreCase]);
  html := StringReplace(html, '<#ROWHEIGHT>', IntToStr(Width div 7),
    [rfReplaceAll, rfIgnoreCase]);

  html := StringReplace(html, '<#EDITWIDTH>', IntToStr((Width - 40) div 7),
    [rfReplaceAll, rfIgnoreCase]);

  html := StringReplace(html, '<#DATESEP>', #39 + FDateSeparator + #39,
    [rfReplaceAll, rfIgnoreCase]);

  if CellValue = '' then
    html := StringReplace(html, '<#CALVALUE>','', [rfReplaceAll, rfIgnoreCase])
  else
  begin
    if DateFormat = gdEU then
      html := StringReplace(html, '<#CALVALUE>', IntToStr(Day) + FDateSeparator +
        IntToStr(Month) + FDateSeparator + IntToStr(Year), [rfReplaceAll, rfIgnoreCase])
    else
      html := StringReplace(html, '<#CALVALUE>', IntToStr(Month) + FDateSeparator
      + IntToStr(Day) + FDateSeparator + IntToStr(Year), [rfReplaceAll, rfIgnoreCase]);
  end;


  if DateFormat = gdEU then
    html := StringReplace(html, '<#FORMAT>', '0', [rfReplaceAll, rfIgnoreCase])
  else
    html := StringReplace(html, '<#FORMAT>', '1', [rfReplaceAll, rfIgnoreCase]);

  InitDays;

  html := StringReplace(html, '<#BUTTONSTYLES>', '', [rfReplaceAll,
    rfIgnoreCase]);
  html := StringReplace(html, '<#INPUTSTYLES>',
    ' style="border-style:solid;border-width:' + IntToStr(1) + 'px;border-color:'
    + HTMLClr(AColor) + ';background-color:' + HTMLClr(AColor) + '";',
    [rfReplaceAll, rfIgnoreCase]);

  if Glyphs.DropDownImageURL <> EmptyStr then
  begin
    html := StringReplace(html,'<#BUTTONVISIBLE>','display:none;', [rfReplaceAll, rfIgnoreCase]);
    html := StringReplace(html,'<#IMAGEVISIBLE>','', [rfReplaceAll, rfIgnoreCase]);

    html := StringReplace(html,'<#BUTTONIMAGE>','src="' + Glyphs.DropDownImageURL + '"', [rfReplaceAll, rfIgnoreCase]);
  end
  else if Assigned(Glyphs.DropDownImage) and not Glyphs.DropDownImage.Empty then
  begin
    html := StringReplace(html,'<#BUTTONVISIBLE>','display:none;', [rfReplaceAll, rfIgnoreCase]);
    html := StringReplace(html,'<#IMAGEVISIBLE>','', [rfReplaceAll, rfIgnoreCase]);
    html := StringReplace(html,'<#BUTTONIMAGE>','src="'+ OutputBMPFileName('DROPDOWN', Glyphs.DropDownImage) +'"', [rfReplaceAll, rfIgnoreCase]);
  end
  else
  begin
    html := StringReplace(html,'<#BUTTONVISIBLE>','', [rfReplaceAll, rfIgnoreCase]);
    html := StringReplace(html,'<#BUTTONIMAGE>','', [rfReplaceAll, rfIgnoreCase]);
    html := StringReplace(html,'<#IMAGEVISIBLE>','display:none;', [rfReplaceAll, rfIgnoreCase]);
  end;


  for i := 0 to 6 do
  begin
    html := StringReplace(html, '<#DAY' + inttostr(i) + '>', FNameOfDays[i],
      [rfReplaceAll, rfIgnoreCase]);
  end;

  html := StringReplace(html, '<#SUBMITCALL>', '', [rfReplaceAll,
    rfIgnoreCase]);

  for i := 0 to 11 do
  begin
    html := StringReplace(html, '<#MONTH' + inttostr(i) + '>', FNameOfMonths[i],
      [rfReplaceAll, rfIgnoreCase]);
  end;

  html := StringReplace(html, '<#BLUR>', blurevent, [rfReplaceAll,
    rfIgnoreCase]);

  Result := html;
end;

function TTIWCustomWebGrid.DateStrToDate(AValue: string): TDateTime;
var
  s: string;
  da, mo, ye: word;
  err: Integer;
begin
  Result := Now;
  s := AValue;
  if pos(FDateSeparator, s) > 0 then
  begin
    val(copy(s, 1, pos(FDateSeparator, s) - 1), da, err);
    delete(s, 1, pos(FDateSeparator, s));
    if pos(FDateSeparator, s) > 0 then
    begin
      val(copy(s, 1, pos(FDateSeparator, s) - 1), mo, err);
      delete(s, 1, pos(FDateSeparator, s));
      val(s, ye, err);
      if err = 0 then
      begin
        if DateFormat = gdEU then
        begin
          Result := EncodeDate(ye, mo, da);
        end
        else
        begin
          Result := EncodeDate(ye, da, mo);
        end;
      end;
    end;
  end;
end;

function TTIWCustomWebGrid.DateToDateStr(AValue: TDateTime): string;
var
  Day, Month, Year: word;
begin
  DecodeDate(AValue, Year, Month, Day);

  if DateFormat = gdEU then
    Result := IntToStr(Day) + FDateSeparator + IntToStr(Month) + FDateSeparator
      + IntToStr(Year)
  else
    Result := IntToStr(Month) + FDateSeparator + IntToStr(Day) + FDateSeparator
      + IntToStr(Year);
end;

function TTIWCustomWebGrid.GetVersionNr: Integer;
begin
  Result := 0;
end;

function TTIWCustomWebGrid.GetVersionString: string;
begin
  Result := '';
end;

function TTIWCustomWebGrid.GetCellDetail(ACol, ARow: Integer): string;
var
  Condition: Boolean;

begin
  Condition := True;
  if (DetailRowShow in [dsServerOpen, dsServerOneOpen]) then
  begin
    Condition := DetailStates[RowOffset + ARow];
  end;

  if Condition then
  begin
    Result := Columns[ACol].DetailTemplate;
    if Assigned(FOnGetCellDetail) then
      FOnGetCellDetail(Self, ARow, ACol, Result);
  end
  else
    Result := '';
end;

procedure TTIWCustomWebGrid.InitMonths;
begin
  FNameOfMonths.Add('January');
  FNameOfMonths.Add('February');
  FNameOfMonths.Add('March');
  FNameOfMonths.Add('April');
  FNameOfMonths.Add('May');
  FNameOfMonths.Add('June');
  FNameOfMonths.Add('July');
  FNameOfMonths.Add('August');
  FNameOfMonths.Add('September');
  FNameOfMonths.Add('October');
  FNameOfMonths.Add('November');
  FNameOfMonths.Add('December');
end;

procedure TTIWCustomWebGrid.InitDays;
begin
  FNameOfDays.Add('Sun');
  FNameOfDays.Add('Mon');
  FNameOfDays.Add('Tue');
  FNameOfDays.Add('Wed');
  FNameOfDays.Add('Thu');
  FNameOfDays.Add('Fri');
  FNameOfDays.Add('Sat');
end;

procedure TTIWCustomWebGrid.SetNodes(const Value: TIWGridNode);
begin
  FNodes.Assign(Value);
end;

procedure TTIWCustomWebGrid.SetBackground(const Value: TIWGridBackground);
begin
  FBackground.Assign(Value);
end;

procedure TTIWCustomWebGrid.SetClientEvents(
  const Value: TIWGridClientEvents);
begin
  FClientEvents.Assign(Value);
end;

procedure TTIWCustomWebGrid.ControllerChanged(Sender: TObject);
begin
  Invalidate;
end;

procedure TTIWCustomWebGrid.DeleteRows(RowIndex,RowCount: Integer);
var
  i: Integer;
  s: string;
  r,c,err,vp: Integer;
begin
  i := 0;
  while i < FDynEdits.Count do
  begin
    s := FDynEdits.Strings[i]; // format is ExCy^value
    delete(s,1,1);
    if varpos('C',s,vp) > 0 then
    begin
      val(copy(s,1,vp - 1),r,err);
      delete(s,1,vp);
      if varpos('^',s,vp) > 0 then
      begin
        val(copy(s,1,vp - 1),c,err);
        s := copy(s,vp + 1,length(s));
        if (r >= RowIndex + RowCount) then
        begin
          FDynEdits[i] := 'E' + IntToStr(r - RowCount) + 'C' + IntToStr(c) + '^' + s;
        end;
        if (r >= RowIndex) and (r < RowIndex + RowCount) then
        begin
          FDynEdits.Delete(i);
        end
        else
          inc(i);
      end;
    end;
  end;
  for i := 1 to RowCount do
  begin
    if FDetailStates.Count > RowIndex then
      FDetailStates.Delete(RowIndex);
  end;

end;

procedure TTIWCustomWebGrid.InsertRows(RowIndex,RowCount: Integer);
var
  i: Integer;
  s: string;
  r,c,err,vp: Integer;
begin
  i := 0;
  while i < FDynEdits.Count do
  begin
    s := FDynEdits.Strings[i]; // format is ExCy^value
    delete(s,1,1);
    if varpos('C',s,vp) > 0 then
    begin
      val(copy(s,1,vp - 1),r,err);
      delete(s,1,vp);
      if varpos('^',s,vp) > 0 then
      begin
        val(copy(s,1,vp - 1),c,err);
        s := copy(s,vp + 1,length(s));
        if (r >= RowIndex) then
        begin
          FDynEdits[i] := 'E' + IntToStr(r + RowCount) + 'C' + IntToStr(c) + '^' + s;
        end;
        
        inc(i);
      end;
    end;
  end;

  for i := 1 to RowCount do
  begin
    if FDetailStates.Count > RowIndex then
      FDetailStates.Insert(RowIndex,nil);
  end;

end;

procedure TTIWCustomWebGrid.UpdateRowCount(const Value: Integer);
begin

end;

procedure TTIWCustomWebGrid.UpdateTotalRows(const Value: Integer);
begin
  // virtual
end;

procedure TTIWCustomWebGrid.SetScroll(const Value: TTIWWebGridScroll);
begin
  FScroll := Value;
end;

function TTIWCustomWebGrid.GetDetailStates(row: Integer): Boolean;
begin
  if row < FDetailStates.Count then
    Result := (FDetailStates.Items[row] <> 0)
  else
    Result := False;  
end;

procedure TTIWCustomWebGrid.SetDetailStates(row: Integer;
  const Value: Boolean);
begin
  while row >= FDetailStates.Count do
    FDetailStates.Add(0);

  if row < FDetailStates.Count then
  begin
    if Value then
      FDetailStates.Items[row] := 1
    else
      FDetailStates.Items[row] := 0;
  end;
end;

function TTIWCustomWebGrid.FontInsert(Font: TIWFont): string;
begin
  if not Font.Enabled then
  begin
    Result := '';
    Exit;
  end;

  Result := 'font-size:' + IntToStr(Font.Size) + 'pt;color:' + ColorToRGBString(Font.Color) + ';';

  if Font.FontName <> EmptyStr then
    Result := 'font-family:' + Font.FontName + ';' + Result
  else
    Result := 'font-family:' + Font.FontFamily + ';' + Result;

  if (fsBold in Font.Style) then
    Result := Result + 'font-weight:bold;';

  if (fsItalic in Font.Style) then
    Result := Result + 'font-style:italic;';
end;


function TTIWCustomWebGrid.FontToTag(Font: TIWFont; s: string): string;
var
  IWHTMLTag: TIWHTMLTag;
begin
  if not Font.Enabled then
  begin
    Result := s;
    Exit;
  end;

  {$IFNDEF TMSIW9}
  if Font.CSSStyle <> '' then
  begin
    Result := '<FONT class="'+Font.CSSStyle+'">' + s + '</FONT>';
  end
  else
  {$ENDIF}
  begin
    IWHTMLTag := Font.FontToStringTag(s);
    Result := IWHTMLTag.Render;
    IWHTMLTag.Free;
  end;
end;

function TTIWCustomWebGrid.FontUsed(Font: TIWFont): Boolean;
begin
  Result := { Font.Enabled or }
    {$IFNDEF TMSIW9}
    (Font.CSSStyle <> '') or
    {$ENDIF}
    (Font.FontName <> '') or (Font.Color <> clNone) or
    (Font.Style <> []);
end;

function TTIWCustomWebGrid.GetURLText(ACol, ARow: Integer; AValue: string): string;
begin
  Result := AValue;
  if Assigned(FOnGetURLText) then
    FOnGetURLText(Self,ARow,ACol,Result);
end;

procedure TTIWCustomWebGrid.SetBounds(ALeft, ATop, AWidth, AHeight: Integer);
begin
  inherited;

  if FIsDetail and (csDesigning in ComponentState) then
  begin
    if AWidth > 29 then
      Width := 29;
    if AHeight > 29 then
      Height := 29;
  end;
end;


function TTIWCustomWebGrid.GetDetailGrid(ARow: Integer): TTIWCustomWebGrid;
begin
  Result := DetailGrid;
  if Assigned(OnGetDetailGrid) then
    OnGetDetailGrid(Self, ARow, Result);
end;

procedure TTIWCustomWebGrid.RenderPrepareDetail(AGrid: TTIWCustomWebGrid);
begin

end;

procedure TTIWCustomWebGrid.DoNodeClose(ARow: Integer);
begin
  if Assigned(OnNodeClose) then
    OnNodeClose(Self,RowOffset + ARow);
end;

procedure TTIWCustomWebGrid.DoNodeOpen(ARow: Integer);
begin
  if Assigned(OnNodeOpen) then
    OnNodeOpen(Self,RowOffset + ARow);
end;

function TTIWCustomWebGrid.GetActiveDetailRow: Integer;
var
  i: Integer;
begin
  Result := -1;
  for i := 1 to FDetailStates.Count do
  begin
    if DetailStates[i - 1] then
    begin
      Result := i - 1;
      Break;
    end;
  end;
end;

procedure TTIWCustomWebGrid.SetRadioSelection(const Value: Integer);
begin
  FRadioSelection := Value;
  Invalidate;
end;

procedure TTIWCustomWebGrid.SaveBookmark;
begin

end;

procedure TTIWCustomWebGrid.SetActiveDetailRow(const Value: Integer);
var
  i: Integer;
begin
  for i := 1 to FDetailStates.Count do
  begin
    DetailStates[i - 1] := False;
  end;
  DetailStates[Value] := True;
end;

function TTIWCustomWebGrid.HTMLAdapt(Value: string): string;
var
  i: integer;
begin
  if not AutoHTMLAdapt then
  begin
    Result := Value;
    Exit;
  end;
  Result := '';
  for i := 1 to Length(Value) do
  begin
    case Value[i] of
    '<': Result := Result + '&lt;';
    '>': Result := Result + '&gt;';
    else
      Result := Result + Value[i];
    end;
  end;

  Result := StringReplace(Result,#13,'<BR>',[rfReplaceAll]);
  Result := StringReplace(Result,#10,'',[rfReplaceAll]);
end;

function TTIWCustomWebGrid.HTMLAdaptInv(Value: string): string;
begin
  Result := StringReplace(Value,'&lt;','<', [rfIgnoreCase,rfReplaceAll]);
  Result := StringReplace(Value,'&gt;','>', [rfIgnoreCase,rfReplaceAll]);
end;

{$IFDEF TMSIW72}
function TTIWCustomWebGrid.get_HasTabOrder: boolean;
begin
  {$IFNDEF TMSIW72_NEW}
  Result := false;
  {$ELSE}                                             
  Result := true;
  {$ENDIF}
end;
{$ENDIF}

{$IFDEF TMSIW72_NEW}
function TTIWCustomWebGrid.get_ShouldRenderTabOrder: Boolean;
begin
  Result := false;
end;
{$ENDIF}



{ TTIWWebGridColumns }

function TTIWWebGridColumns.Add: TTIWWebGridColumn;
begin
  Result := TTIWWebGridColumn(inherited Add);
  if Count > 1 then
  begin
    Result.Assign(Items[Count - 2]);
    Result.Title := '';
  end;  
end;

constructor TTIWWebGridColumns.Create(AOwner: TTIWCustomWebGrid);
begin
  inherited Create(GetItemClass);
  FOwner := AOwner;
end;

function TTIWWebGridColumns.GetItem(Index: Integer): TTIWWebGridColumn;
begin
  Result := TTIWWebGridColumn(inherited Items[Index]);
end;

function TTIWWebGridColumns.GetItemClass: TCollectionItemClass;
begin
  Result := TTIWWebGridColumn;
end;

function TTIWWebGridColumns.GetOwner: TPersistent;
begin
  Result := FOwner;
end;

function TTIWWebGridColumns.Insert(index: Integer): TTIWWebGridColumn;
begin
  Result := TTIWWebGridColumn(inherited Insert(Index));
end;

procedure TTIWWebGridColumns.SetItem(Index: Integer;
  const Value: TTIWWebGridColumn);
begin
  inherited Items[Index] := Value;
end;

procedure TTIWWebGridColumns.Update(Item: TCollectionItem);
begin
  inherited;
  FOwner.Invalidate;
end;

{ TTIWWebGridColumn }

constructor TTIWWebGridColumn.Create(AOwner: TCollection);
begin
  inherited;
  FAlignment := taLeftJustify;
  FAllowSizing := false;
  FButtonColor := clNone;  
  FButtonWidth := 64;
  FColor := clNone;
  FColumnHeaderColor := clNone;
  FColumnHeaderAlignment := taLeftJustify;
  FCanSort := true;
  FCheckTrue := 'true';
  FCheckFalse := 'false';
  FColumnType := ctNormal;
  FColumnHeaderCheckBox := false;
  FColumnHeaderClick := true;
  FColumnHeaderGradient1 := clNone;
  FColumnHeaderGradient2 := clNone;
  FColumnHeaderNode := false;
  FColumnHeaderFont := TIWFont.Create;
  FComboItems := TStringList.Create;
  FComboValues := TStringList.Create;

  FDataButtonType := dbtButton;
  FDetailColor := clNone;
  FDetailFont := TIWFont.Create;
  FDetailSpan := 0;
  FDynPrecision := 0;
  FDynEditor := deText;
  FEditor := edNone;
  FEnabled := true;
  FFilter := false;
  FFilterIndex := 0;
  FFont := TIWFont.Create;
  FFooterAlignment := taLeftJustify;
  FFooterFormat := '%g';
  FFooterGradient1 := clNone;
  FFooterGradient2 := clNone;
  FFooterType := ftText;
  FFilterList := TStringList.Create;

  FGradientDirection := gdHorizontal;
  FImageHeight := 0;
  FImageIndex := -1;
  FImageWidth := 0;
  FMaxLength := 0;
  FOwner := TTIWWebGridColumns(AOwner);

  FPopupWidth := 200;
  FPopupHeight := 200;
  FPopupColor := clWebWHITE;
  FPopupColorTo := clNone;
  FProgressColor := clWebRED;
  FPopupColorGradientDirection := gdHorizontal;
  FShowHint := false;
  FSpinEditMaxValue := 100;
  FSpinEditMinValue := 0;
  FSpinEditAutoSpin := True;
  FSubTitleSpan := 0;
  FSubTitleVAlign := vaNone;
  FTag := 0;
  FTitleRowSpan := false;
  FTitleSpan := 0;
  FTitleVAlign := vaNone;
  FVisible := True;
  FWidth := 128;
  FWidthType := wtAbsolute;

  {$IFDEF TMSIW6}
  FCursor := crAuto;
  {$ENDIF}

  if (csDesigning in (TTIWCustomWebGrid(FOwner.GetOwner).ComponentState)) and
    not (csLoading in (TTIWCustomWebGrid(FOwner.GetOwner).ComponentState)) then
  begin
    FDefaultDynEdit := '0';
    FDefaultDynText := '0';
  end;
end;

procedure TTIWWebGridColumn.SetAlignment(const Value: TAlignment);
begin
  FAlignment := Value;
  Changed;
end;

procedure TTIWWebGridColumn.SeTIWColor(const Value: TIWColor);
begin
  FColor := Value;
  Changed;
end;

procedure TTIWWebGridColumn.SetTemplate(const Value: string);
begin
  FTemplate := Value;
  Changed;
end;

procedure TTIWWebGridColumn.SetTitle(const Value: string);
begin
  FTitle := Value;
  Changed;
end;

procedure TTIWWebGridColumn.SetColumnHeaderColor(const Value: TIWColor);
begin
  FColumnHeaderColor := Value;
  Changed;
end;

procedure TTIWWebGridColumn.SetWidth(const Value: integer);
begin
  FWidth := Value;
  Changed;
end;

procedure TTIWWebGridColumn.SetWidthType(const Value: TTIWWidthType);
begin
  FWidthType := Value;
  Changed;
end;

procedure TTIWWebGridColumn.SetColumnType(const Value: TTIWColumnType);
begin
  FColumnType := Value;
  Changed;
end;

procedure TTIWWebGridColumn.SetButtonText(const Value: string);
begin
  FButtonText := Value;
  Changed;
end;

procedure TTIWWebGridColumn.SetColumnHeaderClick(const Value: boolean);
begin
  FColumnHeaderClick := Value;
end;

procedure TTIWWebGridColumn.SetColumnHeaderAlignment(
  const Value: TAlignment);
begin
  FColumnHeaderAlignment := Value;
  Changed;
end;

procedure TTIWWebGridColumn.SetFont(const Value: TIWFont);
begin
  FFont.Assign(Value);
  Changed;
end;

destructor TTIWWebGridColumn.Destroy;
begin
  FFont.Free;
  FDetailFont.Free;
  FColumnHeaderFont.Free;
  FComboItems.Free;
  FComboValues.Free;
  FFilterList.Free;
  inherited;
end;

procedure TTIWWebGridColumn.SetColumnHeaderFont(const Value: TIWFont);
begin
  FColumnHeaderFont.Assign(Value);
  Changed;
end;

procedure TTIWWebGridColumn.SetComboItems(const Value: TStringList);
begin
  FComboItems.Assign(Value);
end;

procedure TTIWWebGridColumn.SetComboValues(const Value: TStringList);
begin
  FComboValues.Assign(Value);                                              
end;

procedure TTIWWebGridColumn.SetFooterText(const Value: string);
begin
  FFooterText := Value;
  Changed;
end;

procedure TTIWWebGridColumn.SetFooterType(const Value: TTIWFooterType);
begin
  FFooterType := Value;
  Changed;
end;

procedure TTIWWebGridColumn.SetFooterAlignment(const Value: TAlignment);
begin
  FFooterAlignment := Value;
  Changed;
end;

procedure TTIWWebGridColumn.Changed;
begin
  FOwner.FOwner.Invalidate;
end;

procedure TTIWWebGridColumn.SetFooterFormat(const Value: string);
begin
  FFooterFormat := Value;
  Changed;
end;

procedure TTIWWebGridColumn.SetImageIndex(const Value: Integer);
begin
  FImageIndex := Value;
end;

procedure TTIWWebGridColumn.SetFilterList(const Value: TStringList);
begin
  FFilterList.Assign(Value);
end;

procedure TTIWWebGridColumn.SetSubTitle(const Value: string);
begin
  FSubTitle := Value;
  Changed;
end;

procedure TTIWWebGridColumn.SetSubTitleSpan(const Value: Integer);
begin
  FSubTitleSpan := Value;
  Changed;
end;

procedure TTIWWebGridColumn.SetTitleSpan(const Value: Integer);
begin
  FTitleSpan := Value;
  Changed;
end;

function TTIWWebGridColumn.GetDisplayName: string;
begin
  if Name = '' then
    Result := 'Column ' + Inttostr(Index)
  else
    Result := Name;
end;

procedure TTIWWebGridColumn.SetVisible(const Value: Boolean);
begin
  FVisible := Value;
  Changed;
end;

procedure TTIWWebGridColumn.SetTitleRowSpan(const Value: Boolean);
begin
  FTitleRowSpan := Value;
  Changed;
end;



procedure TTIWWebGridColumn.Assign(Source: TPersistent);
begin
  Alignment := (Source as TTIWWebGridColumn).Alignment;

  AllowSizing := (Source as TTIWWebGridColumn).AllowSizing;
  ButtonText := (Source as TTIWWebGridColumn).ButtonText;
  ButtonWidth := (Source as TTIWWebGridColumn).ButtonWidth;
  CheckTrue := (Source as TTIWWebGridColumn).CheckTrue;
  CheckFalse := (Source as TTIWWebGridColumn).CheckFalse;
  ClickConfirm := (Source as TTIWWebGridColumn).ClickConfirm;
  Color := (Source as TTIWWebGridColumn).Color;

  ColumnHeaderAlignment := (Source as TTIWWebGridColumn).ColumnHeaderAlignment;
  ColumnHeaderClick := (Source as TTIWWebGridColumn).ColumnHeaderClick;
  ColumnHeaderColor := (Source as TTIWWebGridColumn).ColumnHeaderColor;
  ColumnHeaderFont.Assign((Source as TTIWWebGridColumn).Font);
  ColumnHeaderGradient1 := (Source as TTIWWebGridColumn).ColumnHeaderGradient1;
  ColumnHeaderGradient2 := (Source as TTIWWebGridColumn).ColumnHeaderGradient2;
  ColumnHeaderGradientDirection := (Source as TTIWWebGridColumn).ColumnHeaderGradientDirection;
  ColumnHeaderCheckBox := (Source as TTIWWebGridColumn).ColumnHeaderCheckBox;
  ColumnHeaderNode := (Source as TTIWWebGridColumn).ColumnHeaderNode;

  FooterGradient1 := (Source as TTIWWebGridColumn).FooterGradient1;
  FooterGradient2 := (Source as TTIWWebGridColumn).FooterGradient2;

                                                                   
  ColumnType := (Source as TTIWWebGridColumn).ColumnType;

  ComboItems.Assign((Source as TTIWWebGridColumn).ComboItems);
  ComboValues.Assign((Source as TTIWWebGridColumn).ComboValues);
  DetailColor := (Source as TTIWWebGridColumn).DetailColor;
  DetailTemplate := (Source as TTIWWebGridColumn).DetailTemplate;
  DetailSpan := (Source as TTIWWebGridColumn).DetailSpan;
  DynPrecision := (Source as TTIWWebGridColumn).DynPrecision;
  DynEditor := (Source as TTIWWebGridColumn).DynEditor;
  Hint := (Source as TTIWWebGridColumn).Hint;                        
  ImageIndex := (Source as TTIWWebGridColumn).ImageIndex;
                                                                        
  //Editor := (Source as TTIWWebGridColumn).Editor;
                                                                  
  Filter := (Source as TTIWWebGridColumn).Filter;
  FilterIndex := (Source as TTIWWebGridColumn).FilterIndex;
  FilterList.Assign((Source as TTIWWebGridColumn).FilterList);
  Font.Assign((Source as TTIWWebGridColumn).Font);
  FooterAlignment := (Source as TTIWWebGridColumn).FooterAlignment;
  FooterFormat := (Source as TTIWWebGridColumn).FooterFormat;
  FooterText := (Source as TTIWWebGridColumn).FooterText;
  FooterType := (Source as TTIWWebGridColumn).FooterType;
  Formula := (Source as TTIWWebGridColumn).Formula;
  MaxLength := (Source as TTIWWebGridColumn).MaxLength;

  //Name := (Source as TTIWWebGridColumn).Name;

  PopupColor := (Source as TTIWWebGridColumn).PopupColor;
  PopupColorTo := (Source as TTIWWebGridColumn).PopupColorTo;
  PopupColorGradientDirection := (Source as TTIWWebGridColumn).PopupColorGradientDirection;
  PopupHeight := (Source as TTIWWebGridColumn).PopupHeight;
  PopupWidth := (Source as TTIWWebGridColumn).PopupWidth;
  ProgressColor := (Source as TTIWWebGridColumn).ProgressColor;
  RequiredMsg := (Source as TTIWWebGridColumn).RequiredMsg;
  ShowHint := (Source as TTIWWebGridColumn).ShowHint;
  SubTitle := (Source as TTIWWebGridColumn).SubTitle;
  SubTitleSpan := (Source as TTIWWebGridColumn).SubTitleSpan;
  SubTitleVAlign := (Source as TTIWWebGridColumn).SubTitleVAlign;
  Template := (Source as TTIWWebGridColumn).Template;
  Tag := (Source as TTIWWebGridColumn).Tag;
  Title := (Source as TTIWWebGridColumn).Title;
  TitleRowSpan := (Source as TTIWWebGridColumn).TitleRowSpan;
  TitleSpan := (Source as TTIWWebGridColumn).TitleSpan;
  TitleVAlign := (Source as TTIWWebGridColumn).TitleVAlign;
  VAlign := (Source as TTIWWebGridColumn).VAlign;
  Visible := (Source as TTIWWebGridColumn).Visible;
  Width := (Source as TTIWWebGridColumn).Width;
  WidthType := (Source as TTIWWebGridColumn).WidthType;

  CanSort := (Source as TTIWWebGridColumn).CanSort;
end;

procedure TTIWWebGridColumn.AssignVisualProperties(Source: TPersistent);
begin
  Alignment := (Source as TTIWWebGridColumn).Alignment;
  AllowSizing := (Source as TTIWWebGridColumn).AllowSizing;
  ButtonText := (Source as TTIWWebGridColumn).ButtonText;
  ButtonWidth := (Source as TTIWWebGridColumn).ButtonWidth;
  CheckTrue := (Source as TTIWWebGridColumn).CheckTrue;
  CheckFalse := (Source as TTIWWebGridColumn).CheckFalse;
  ClickConfirm := (Source as TTIWWebGridColumn).ClickConfirm;
  Color := (Source as TTIWWebGridColumn).Color;

  ColumnHeaderAlignment := (Source as TTIWWebGridColumn).ColumnHeaderAlignment;
  ColumnHeaderClick := (Source as TTIWWebGridColumn).ColumnHeaderClick;
  ColumnHeaderColor := (Source as TTIWWebGridColumn).ColumnHeaderColor;
  ColumnHeaderFont.Assign((Source as TTIWWebGridColumn).Font);
  ColumnHeaderGradient1 := (Source as TTIWWebGridColumn).ColumnHeaderGradient1;
  ColumnHeaderGradient2 := (Source as TTIWWebGridColumn).ColumnHeaderGradient2;
  ColumnHeaderGradientDirection := (Source as TTIWWebGridColumn).ColumnHeaderGradientDirection;
  ColumnHeaderCheckBox := (Source as TTIWWebGridColumn).ColumnHeaderCheckBox;
  ColumnHeaderNode := (Source as TTIWWebGridColumn).ColumnHeaderNode;

  FooterGradient1 := (Source as TTIWWebGridColumn).FooterGradient1;
  FooterGradient2 := (Source as TTIWWebGridColumn).FooterGradient2;

  DetailColor := (Source as TTIWWebGridColumn).DetailColor;
  DynPrecision := (Source as TTIWWebGridColumn).DynPrecision;
  Hint := (Source as TTIWWebGridColumn).Hint;
  ImageIndex := (Source as TTIWWebGridColumn).ImageIndex;

  Font.Assign((Source as TTIWWebGridColumn).Font);
  FooterAlignment := (Source as TTIWWebGridColumn).FooterAlignment;
  FooterFormat := (Source as TTIWWebGridColumn).FooterFormat;

  PopupColor := (Source as TTIWWebGridColumn).PopupColor;
  PopupColorTo := (Source as TTIWWebGridColumn).PopupColorTo;
  PopupColorGradientDirection := (Source as TTIWWebGridColumn).PopupColorGradientDirection;
  PopupHeight := (Source as TTIWWebGridColumn).PopupHeight;
  PopupWidth := (Source as TTIWWebGridColumn).PopupWidth;
  ProgressColor := (Source as TTIWWebGridColumn).ProgressColor;
  RequiredMsg := (Source as TTIWWebGridColumn).RequiredMsg;
  ShowHint := (Source as TTIWWebGridColumn).ShowHint;

  SubTitleVAlign := (Source as TTIWWebGridColumn).SubTitleVAlign;
  Tag := (Source as TTIWWebGridColumn).Tag;
  TitleVAlign := (Source as TTIWWebGridColumn).TitleVAlign;
  VAlign := (Source as TTIWWebGridColumn).VAlign;
  Width := (Source as TTIWWebGridColumn).Width;
  WidthType := (Source as TTIWWebGridColumn).WidthType;
  CanSort := (Source as TTIWWebGridColumn).CanSort;
end;


procedure TTIWWebGridColumn.SetDetailFont(const Value: TIWFont);
begin
  FDetailFont.Assign(Value);
  Changed;
end;

{ TTIWAdvWebGridController }

procedure TTIWAdvWebGridController.Changed;
begin
  if Assigned(OnChange) then
    OnChange(Self);
end;

constructor TTIWAdvWebGridController.Create;
begin
  inherited;
  FTextNext := 'Next';
  FTextPrev := 'Prev';
  FTextFirst := 'First';
  FTextLast := 'Last';
  FHintFind := 'Find';
  FColor := clNone;
  FIndicatorFormat := '%d of %d';
  FFont := TIWFont.Create;
  FGradient1 := clNone;
  FGradient2 := clNone;
  FImgPrev := TIPicture.Create;
  FImgNext := TIPicture.Create;
  FImgLast := TIPicture.Create;
  FImgFirst := TIPicture.Create;
  FMaxPages := 10;
  FHeight := 22; 
  FRowCountValues := TStringList.Create;
end;

destructor TTIWAdvWebGridController.Destroy;
begin
  FFont.Free;
  FImgPrev.Free;
  FImgNext.Free;
  FImgLast.Free;
  FImgFirst.Free;
  FRowCountValues.Free;
  FControllerBorders.Free;
  inherited;
end;

procedure TTIWAdvWebGridController.SetAlignment(const Value: TAlignment);
begin
  FAlignment := Value;
  Changed;
end;

procedure TTIWAdvWebGridController.SetCaption(const Value: string);
begin
  FCaption := Value;
  Changed;
end;

procedure TTIWAdvWebGridController.SeTIWColor(const Value: TIWColor);
begin
  FColor := Value;
  Changed;
end;

procedure TTIWAdvWebGridController.SetControllerPager(
  const Value: TControllerPager);
begin
  FControllerPager := Value;
  Changed;
end;

procedure TTIWAdvWebGridController.SetFont(const Value: TIWFont);
begin
  FFont.Assign(Value);
  Changed;
end;

procedure TTIWAdvWebGridController.SetHeight(const Value: Integer);
begin
  FHeight := Value;
  Changed;
end;

procedure TTIWAdvWebGridController.SetImgFirst(const Value: TIPicture);
begin
  FImgFirst.Assign(Value);
  Changed;
end;

procedure TTIWAdvWebGridController.SetImgLast(const Value: TIPicture);
begin
  FImgLast.Assign(Value);
  Changed;
end;

procedure TTIWAdvWebGridController.SetImgNext(const Value: TIPicture);
begin
  FImgNext.Assign(Value);
  Changed;
end;

procedure TTIWAdvWebGridController.SetImgPrev(const Value: TIPicture);
begin
  FImgPrev.Assign(Value);
  Changed;
end;

procedure TTIWAdvWebGridController.SetIndicatorFormat(const Value: string);
begin
  FIndicatorFormat := Value;
end;

procedure TTIWAdvWebGridController.SetIndicatorType(
  const Value: TControllerIndicatorType);
begin
  FIndicatorType := Value;
end;

procedure TTIWAdvWebGridController.SetPagerType(
  const Value: TControllerPagerType);
begin
  FPageType := Value;
  Changed;
end;

procedure TTIWAdvWebGridController.SetPosition(
  const Value: TControllerPosition);
begin
  FPosition := Value;
  Changed;
end;

procedure TTIWAdvWebGridController.SetRowCountValues(
  const Value: TStringList);
begin
  FRowCountValues.Assign(Value);
end;

procedure TTIWAdvWebGridController.SetTextFirst(const Value: string);
begin
  FTextFirst := Value;
  Changed;
end;

procedure TTIWAdvWebGridController.SetTextLast(const Value: string);
begin
  FTextLast := Value;
  Changed;
end;

procedure TTIWAdvWebGridController.SetTextNext(const Value: string);
begin
  FTextNext := Value;
  Changed;
end;

procedure TTIWAdvWebGridController.SetTextPrev(const Value: string);
begin
  FTextPrev := Value;
  Changed;
end;

{ TTIWAdvWebGridBands }

constructor TTIWAdvWebGridBands.Create(AOwner: TTIWCustomWebGrid);
begin
  inherited Create;
  FOwner := AOwner;
  FPrimaryColor := clInfoBk;
  FSecondaryColor := clWhite;
end;

procedure TTIWAdvWebGridBands.SetActive(const Value: Boolean);
begin
  FActive := Value;
end;

procedure TTIWAdvWebGridBands.SetPrimaryColor(const Value: TIWColor);
begin
  FPrimaryColor := Value;
end;

procedure TTIWAdvWebGridBands.SetSecondaryColor(const Value: TIWColor);
begin
  FSecondaryColor := Value;
end;

{ TTIWRGIndicator }

constructor TTIWRGIndicators.Create(AOwner: TTIWCustomWebGrid);
begin
  inherited Create;
  FOwner := AOwner;
  FInsert := TBitmap.Create;
  FEdit := TBitmap.Create;
  FBrowse := TBitmap.Create;

  if (csDesigning in AOwner.ComponentState) then
  begin
    FInsert.LoadFromResourceName(HInstance, 'IWRGINSERT');
    FEdit.LoadFromResourceName(HInstance, 'IWRGEDIT');
    FBrowse.LoadFromResourceName(HInstance, 'IWRGBROWSE');
  end;
end;

destructor TTIWRGIndicators.Destroy;
begin
  FEdit.Free;
  FInsert.Free;
  FBrowse.Free;
  inherited;
end;

procedure TTIWRGIndicators.SetBrowse(const Value: TBitmap);
begin
  FBrowse.Assign(Value);
end;

procedure TTIWRGIndicators.SetEdit(const Value: TBitmap);
begin
  FEdit.Assign(Value);
end;

procedure TTIWRGIndicators.SetInsert(const Value: TBitmap);
begin
  FInsert.Assign(Value);
end;

{ TTIWRGBorders }

constructor TTIWRGBorders.Create(AOwner: TTIWCustomWebGrid);
begin
  inherited Create;
  FOwner := AOwner;
  FWidth := 1;
  FColor := clNone;
  FColorLight := clNone;
  FColorDark := clNone;
end;

procedure TTIWRGBorders.SetInner(const Value: TInnerBorders);
begin
  FInner := Value;
  FOwner.Invalidate;  
end;

procedure TTIWRGBorders.SetOuter(const Value: TOuterBorders);
begin
  FOuter := Value;
  FOwner.Invalidate;
end;

procedure TTIWRGBorders.SeTIWColor(const Value: TIWColor);
begin
  FColor := Value;
  FOwner.Invalidate;
end;

procedure TTIWRGBorders.SetPadding(const Value: Integer);
begin
  FPadding := Value;
  FOwner.Invalidate;
end;

procedure TTIWRGBorders.SetSpacing(const Value: Integer);
begin
  FSpacing := Value;
  FOwner.Invalidate;
end;

procedure TTIWRGBorders.SetWidth(const Value: Integer);
begin
  FWidth := Value;
  FOwner.Invalidate;
end;

procedure TTIWRGBorders.SetIWColorDark(const Value: TIWColor);
begin
  FColorDark := Value;
  FOwner.Invalidate;
end;

procedure TTIWRGBorders.SetIWColorLight(const Value: TIWColor);
begin
  FColorLight := Value;
  FOwner.Invalidate;
end;

procedure TTIWRGBorders.SetCollapsed(const Value: Boolean);
begin
  FCollapsed := Value;
  FOwner.Invalidate;
end;

{ TTIWRGSortSettings }

constructor TTIWRGSortSettings.Create(AOwner: TTIWCustomWebGrid);
begin
  inherited Create;
  FOwner := AOwner;
  FAscending := TBitmap.Create;
  FDescending := TBitmap.Create;
end;

destructor TTIWRGSortSettings.Destroy;
begin
  FAscending.Free;
  FDescending.Free;
  inherited;
end;

procedure TTIWRGSortSettings.SetAscending(const Value: TBitmap);
begin
  FAscending.Assign(Value);
end;

procedure TTIWRGSortSettings.SetColumn(const Value: Integer);
begin
  FColumn := Value;
end;

procedure TTIWRGSortSettings.SetDescending(const Value: TBitmap);
begin
  FDescending.Assign(Value);
end;

procedure TTIWRGSortSettings.SetDirection(const Value: TSortDirection);
begin
  FDirection := Value;
end;

procedure TTIWRGSortSettings.SetShow(const Value: Boolean);
begin
  FShow := Value;
end;

{ TTIWRGGlyphs }

constructor TTIWRGGlyphs.Create(AOwner: TTIWCustomWebGrid);
begin
  inherited Create;
  FOwner := AOwner;

  FCancelButton := TBitmap.Create;
  FCancelHint := 'Cancel';
  FEditButton := TBitmap.Create;
  FEditHint := 'Edit';
  FPostButton := TBitmap.Create;
  FPostHint := 'Post';

  FDropDownImage := TBitmap.Create;

  FSpinEditButtonDownImage := TIPicture.Create;
  FSpinEditButtonUpImage := TIPicture.Create;

  if (csDesigning in AOwner.ComponentState) then
  begin // initialize the post/edit/cancel buttons
    FPostButton.LoadFromResourceName(Hinstance, 'IWRGPOSTBTN');
    FEditButton.LoadFromResourceName(Hinstance, 'IWRGEDITBTN');
    FCancelButton.LoadFromResourceName(Hinstance, 'IWRGCANCELBTN');
  end;
end;

destructor TTIWRGGlyphs.Destroy;
begin
  FPostButton.Free;
  FEditButton.Free;
  FCancelButton.Free;
  FDropDownImage.Free;
  FSpinEditButtonDownImage.Free;
  FSpinEditButtonUpImage.Free;
  inherited;
end;

procedure TTIWRGGlyphs.SetCancelButton(const Value: TBitmap);
begin
  FCancelButton.Assign(Value);
end;

procedure TTIWRGGlyphs.SetDropDownImage(const Value: TBitmap);
begin
  FDropDownImage.Assign(Value);
end;

procedure TTIWRGGlyphs.SetEditButton(const Value: TBitmap);
begin
  FEditButton.Assign(Value);
end;

procedure TTIWRGGlyphs.SetPostButton(const Value: TBitmap);
begin
  FPostButton.Assign(Value);
end;

procedure TTIWRGGlyphs.SetSpinEditButtonDownImage(const Value: TIPicture);
begin
  FSpinEditButtonDownImage.Assign(Value);
end;

procedure TTIWRGGlyphs.SetSpinEditButtonUpImage(const Value: TIPicture);
begin
  FSpinEditButtonUpImage.Assign(Value);
end;

{ TIWGridNode }

procedure TIWGridNode.Assign(Source: TPersistent);
begin
  FHintClosed := (Source as TIWGridNode).HintClosed;
  FHintOpen := (Source as TIWGridNode).HintOpen;
end;

constructor TIWGridNode.Create(AOwner: TTIWCustomWebGrid);
begin
  inherited Create;

  FOwner := AOwner;
  FNodeOpen := TIPicture.Create;

  if (csDesigning in FOwner.ComponentState) then
  begin
    {$IFDEF LINUX}
    FNodeOpen.LoadFromResourceName(HInstance, 'IWRGEXPANDB');
    {$ELSE}
    FNodeOpen.LoadFromResourceName(HInstance, 'IWRGEXPAND');
    {$ENDIF}
  end;  

  FNodeClosed := TIPicture.Create;

  if (csDesigning in FOwner.ComponentState) then
  begin
    {$IFDEF LINUX}
    FNodeClosed.LoadFromResourceName(HInstance, 'IWRGCOLLAPSB');
    {$ELSE}
    FNodeClosed.LoadFromResourceName(HInstance, 'IWRGCOLLAPS');
    {$ENDIF}
  end;  
end;

destructor TIWGridNode.Destroy;
begin
  FNodeClosed.Free;
  FNodeOpen.Free;
  inherited;
end;

procedure TIWGridNode.SetNodeClosed(const Value: TIPicture);
begin
  FNodeClosed.Assign(Value);
end;

procedure TIWGridNode.SetNodeOpen(const Value: TIPicture);
begin
  FNodeOpen.Assign(Value);
end;

{ TIWGridBackground }

procedure TIWGridBackground.Assign(Source: TPersistent);
begin
  inherited;

end;

constructor TIWGridBackground.Create;
begin
  inherited;
  FPicture := TIPicture.Create;
  FPictureURL := EmptyStr;
  FGradient1 := clNone;
  FGradient2 := clNone;
end;

destructor TIWGridBackground.Destroy;
begin
  FPicture.Free;
  inherited;
end;

procedure TIWGridBackground.SetPicture(const Value: TIPicture);
begin
  FPicture := Value;
end;

{ TIWGridClientEvents }

procedure TIWGridClientEvents.Assign(Source: TPersistent);
begin
  inherited;
  FButtonClick.Assign((Source as TIWGridClientEvents).ButtonClick);
end;

constructor TIWGridClientEvents.Create;
begin
  inherited Create;
  FButtonClick := TStringList.Create;
  FCellClick := TStringList.Create;
  FCheckClick := TStringList.Create;
  FEditChange := TStringList.Create;
  FEditDone := TStringList.Create;
  FImageClick := TStringList.Create;
  FComboChange := TStringList.Create;
  FDynComboChange := TStringList.Create;
  FDynCheckClick := TStringList.Create;
  FDynEditChange := TStringList.Create;
  FDynEditDone := TStringList.Create;
  FNodeClick := TStringList.Create;
  FGridKeyDown := TStringList.Create;
  FPopupEditOk := TStringList.Create;                  
  FPopupEditCancel := TStringList.Create;
  FHoverRow := TStringList.Create;
end;

destructor TIWGridClientEvents.Destroy;
begin
  FButtonClick.Free;
  FCellClick.Free;
  FCheckClick.Free;
  FEditChange.Free;
  FEditDone.Free;
  FImageClick.Free;
  FComboChange.Free;
  FDynComboChange.Free;
  FDynCheckClick.Free;
  FDynEditChange.Free;
  FDynEditDone.Free;
  FNodeClick.Free;
  FGridKeyDown.Free;
  FPopupEditOk.Free;
  FPopupEditCancel.Free;
  FHoverRow.Free;
  inherited;
end;

function TIWGridClientEvents.GetJSFunction(PropName: string): string;
begin
  if PropName = 'ButtonClick' then
    Result := 'ButtonClick(obj,c,r,s); // obj=Object, c=Column, r=Row, s=Confirm Message';

  if PropName = 'ImageClick' then
    Result := 'ImageClick(obj,c,r,s); // obj=Object, c=Column, r=Row, s=Confirm Message';

  if PropName = 'CellClick' then
    Result := 'CellClick(obj,c,r); // obj=Object, c=Column, r=Row';

  if PropName = 'CheckClick' then
    Result := 'CheckClick(obj,ctrl,c,r); // obj=Object, ctrl=dyn. edit, c=Column, r=Row';

  if PropName = 'ComboChange' then
    Result := 'ComboChange(obj,ctrl,c,r); // obj=Object, ctrl=combobox, c=Column, r=Row';

  if PropName = 'DynEditChange' then
    Result := 'DynEditChange(obj,ctrl,c,r); // obj=Object, ctrl=dyn. edit, c=Column, r=Row';

  if PropName = 'DynComboChange' then
    Result := 'DynComboChange(obj,ctrl,c,r); // obj=Object, ctrl=dyn. edit, c=Column, r=Row';

  if PropName = 'DynCheckClick' then
    Result := 'DynCheckClick(obj,ctrl,c,r); // obj=Object, ctrl=dyn. edit, c=Column, r=Row';

  if PropName = 'DynEditDone' then
    Result := 'DynEditDone(obj,ctrl,c,r); // obj=Object, ctrl=dyn. edit, c=Column, r=Row';

  if PropName = 'EditDone' then
    Result := 'EditDone(obj,ctrl,c,r); // obj=Object, ctrl=dyn. edit, c=Column, r=Row';

  if PropName = 'PopupEditOk' then
    Result := 'PopupEditOk(obj,ctrl,cellid,c,r); // obj=Object, ctrl=edit, cellid = id of cell, c=Column, r=Row';

  if PropName = 'PopupEditCancel' then
    Result := 'PopupEditCancel(obj,ctrl,c,r); // obj=Object, ctrl=edit, c=Column, r=Row';

  if PropName = 'NodeClick' then
    Result := 'NodeClick(obj,r); // obj=Object, r=Row';

  if PropName = 'GridKeyDown' then
    Result := 'GridKeyDown(obj,c,r); // obj=Object, c=Column, r=Row';

  if PropName = 'HoverRow' then
    Result := 'HoverRow(obj,r,active); //obj=Object, r = row, active=true on hover over row';
end;                                                           
                                                       
procedure TIWGridClientEvents.SetButtonClick(const Value: TStringList);
begin
  FButtonClick.Assign(Value);
end;

procedure TIWGridClientEvents.SetCellClick(const Value: TStringList);
begin
  FCellClick.Assign(Value);
end;

procedure TIWGridClientEvents.SetComboChange(const Value: TStringList);
begin
  FComboChange.Assign(Value);
end;

procedure TIWGridClientEvents.SetCheckClick(const Value: TStringList);
begin
  FCheckClick.Assign(Value);
end;

procedure TIWGridClientEvents.SetDynCheckClick(const Value: TStringList);
begin
  FDynCheckClick.Assign(Value);
end;

procedure TIWGridClientEvents.SetDynComboChange(const Value: TStringList);
begin
  FDynComboChange.Assign(Value);
end;

procedure TIWGridClientEvents.SetDynEditChange(const Value: TStringList);
begin
  FDynEditChange.Assign(Value);
end;

procedure TIWGridClientEvents.SetDynEditDone(const Value: TStringList);
begin
  FDynEditDone.Assign(Value);
end;

procedure TIWGridClientEvents.SetEditChange(const Value: TStringList);
begin
  FEditChange.Assign(Value);
end;

procedure TIWGridClientEvents.SetEditDone(const Value: TStringList);
begin
  FEditDone.Assign(Value);
end;

procedure TIWGridClientEvents.SetPopupEditOk(const Value: TStringList);
begin
  FPopupEditOk.Assign(Value);
end;

procedure TIWGridClientEvents.SetPopupEditCancel(const Value: TStringList);
begin
  FPopupEditCancel.Assign(Value);
end;

procedure TIWGridClientEvents.SetGridKeyDown(const Value: TStringList);
begin
  FGridKeyDown.Assign(Value);
end;


procedure TIWGridClientEvents.SetImageClick(const Value: TStringList);
begin
  FImageClick.Assign(Value);
end;

procedure TIWGridClientEvents.SetNodeClick(const Value: TStringList);
begin
  FNodeClick.Assign(Value);
end;

procedure TIWGridClientEvents.SetHoverRow(const Value: TStringList);
begin
  FHoverRow.Assign(Value);
end;

{ TTIWWebGridScroll }

procedure TTIWWebGridScroll.Changed;
begin
  if Assigned(FOnChange) then
    FOnChange(Self);
end;

constructor TTIWWebGridScroll.Create;
begin
  inherited;
  FPersistent := True;
end;

procedure TTIWWebGridScroll.SetStyle(const Value: TTIWScroll);
begin
  FStyle := Value;
  Changed;
end;

{ TTIWWebGridRowHeader }

constructor TTIWWebGridRowHeader.Create(AOwner: TTIWCustomWebGrid);
begin
  inherited Create;
  FRowHeaderWidth := 22;
  FRowHeaderGradient1 := clNone;
  FRowHeaderGradient2 := clNone;
  FRowHeaderColor := clBtnFace;
  FRowHeaderBorders := TTIWRGBorders.Create(AOwner);
  FRowHeaderBorders.Collapsed := true;
end;

destructor TTIWWebGridRowHeader.Destroy;
begin
  FRowHeaderBorders.Free;
  inherited;
end;

initialization

  {$IFDEF FREEWARE}
  {$IFDEF TMSIW51}
  GLicense.ThirdPartyHook(FWNOTICE, True);
  {$ELSE}

  {$IFNDEF DELPHI7_LVL}
  GLicense.ThirdPartyHook(FWNOTICE, True);
  {$ELSE}
  AddThirdPartyLogo(FWNOTICE, True);
  {$ENDIF}

  {$ENDIF}
  {$ENDIF}

end.
