{***********************************************************************}
{ TPlanner component                                                    }
{ for Delphi & C++Builder                                               }
{                                                                       }
{ written by TMS Software                                               }
{            copyright © 1999-2016                                      }
{            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 Planner;

{$I TMSDEFS.INC}


{$HPPEMIT ''}
{$HPPEMIT '#include "winuser.h"'}
{$HPPEMIT ''}
{$H+}
{$J+}
{$Y+}
{$T-}
{$DEFINE REMOVESTRIP}
{$DEFINE REMOVEDRAW}
{$DEFINE HILIGHT}
{$DEFINE TMSSKINS}

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Dialogs,
  StdCtrls, ExtCtrls, Grids, Buttons, ComCtrls, Menus, Mask,
  Printers, PlanUtil, PlanObj, PlanCheck, PlanCombo, Forms,
  PictureContainer, AdvStyleIF, ShellApi, CommCtrl, ComObj, PlanXPVS,
  Variants, Types
  {$IFNDEF DELPHI_UNICODE}
  , PlanUni
  {$ENDIF}
  {$IFDEF DELPHIXE3_LVL}
  , System.UITypes
  {$ENDIF}
  ;

const
{$IFDEF VER90}
  crSizeAll = crCross;
{$ENDIF}
  MAJ_VER = 3; // Major version nr.
  MIN_VER = 3; // Minor version nr.
  REL_VER = 7; // Release nr.
  BLD_VER = 2; // Build nr.
  DATE_VER = 'Jan, 2016'; // Month version

  // version history
  // 3.0.0.0  : Improved : Caption drawing
  //          : Improved : Auto Position size calculation
  //          : Improved : HTML export of font colors in items
  //          : Improved : HTML export of header, group header
  //          : Improved : precise drawing
  //          : Improved : Text positioning in Planner items
  //          : Improved : Updating Planner mode performance
  //          : New : Visual item link indication
  //          : New : Mode plActiveDayPeriod added
  //          : New : OnPlannerMouseLeave, OnPlannerMouseEnter events added
  //          : New : OnSideBarClick, OnSideBarRightClick, OnSideBarDblClick events added
  //          : New : OnHeaderAnchorClick, OnHeaderAnchorEnter, OnHeaderAnchorLeave events added
  //          : New : OnItemAfterPaint event added
  //          : New : Planner.Header.GroupHeight property added
  //          : New : Exposed WheelAction property
  //          : New : PlannerItem.HTMLTemplate added for DB-aware templating
  //          : New : OnHeaderDraw, OnHeaderDrawProp events added
  //          : New : Easy translatable event edit dialogs
  //          : New : PlannerItem.ColorDirection, PlannerItem.CaptionBkgDirection properties added
  //          : New : PlannerItem.TrackBrushStyle
  //          : New : Automatic selection limitation in multimonth mode
  //          : New : Planner.Display.ColorNonSelect, Planner.Display.BrushNonSelect properties added
  //          : New : OnItemCanSelect event added
  //          : New : AutoPositionPrevNext property added
  //          : New : Method LinkItems(), UnlinkItems(), SelectLinkedItems() added
  //          : New : AutoSelectLinkedItems, AutoDeleteLinkedItems property added
  //          : New : SyncPlanner capability added
  //          : New : OnPlannerNextPosition/OnPlannerPrevPosition events added
  //          : New : DragItemImage , drag & drop to move items with drag image support added
  //          : New : SideBar.TimeIndicatorType & SideBar.TimeIndicatorGlyph properties added
  //          : New : PlannerItem HintIndicator / HintIndicatorColor added
  //          : New : Full Office 2007, 2010 automatic theme adapt
  //          : Fixed : Header drawing in plCustomList mode

  // 3.0.0.1  : Fixed : Issue with color initialisation
  //          : Fixed : Exposed events OnPlannerNextPosition/OnPlannerPrevPosition
  // 3.0.0.2  : Fixed : Issue with using PositionProps when SelMin/SelMax = 0
  // 3.0.0.3  : Fixed : Issue with position width calculation when SideBar.Visible = false
  // 3.0.0.4  : Fixed : Issue with resizing & position width
  // 3.0.0.5  : Fixed : Issue with header group printing for horiz. Planner
  //          : Fixed : Issue with recurrency handler for 5th weekday in a month
  // 3.0.0.6  : Fixed : Planner item focus drawing
  // 3.0.0.7  : Fixed : Issue with positioning item on Planner in plCustomList mode
  // 3.0.0.8  : Fixed : Issue with timeline start time position calculation
  //          : Improved : Click accuracy when large nr. of overlapping items are in a cell
  // 3.0.0.9  : Fixed : Issue with Display.CurrentColor when Mode = plDay
  // 3.0.0.10 : Fixed : Issue with Mode.Day property setter for last day of month
  // 3.0.0.11 : Improved : Click accuracy when large nr. of overlapping items are in a cell in horiz. mode
  // 3.0.0.12 : Fixed : Painting issue in horiz. mode due to rounding
  // 3.0.1.0  : New : Function IsVisibleCell added
  // 3.0.2.0  : New : PlannerItem.SelectCaptionBkg,PlannerItem.SelectCaptionBkgTo added
  // 3.0.2.1  : Fixed : Center aligned text in top timeline sidebar
  //          : Fixed : Issue with background bitmap and disjunct selection in horiz. mode
  // 3.0.2.2  : Fixed : Issue with AutoHeaderUpdate for TDBPeriodSource
  // 3.0.2.3  : Fixed : Issue with LineFeeds & SaveToHTML
  // 3.0.2.4  : Improved : Footer.Captions initialization for custom completion calculation
  //          : Improved : Printing in halfdayperiod mode with horiz. time axis
  // 3.0.2.5  : Fixed : Issue with header anchors when position groups are used
  // 3.0.2.6  : Fixed : Issue with header anchors when position groups with specified group size is used
  // 3.0.2.7  : Fixed : Issue with completion display in horiz. time axis mode
  // 3.0.2.8  : Fixed : DivByZero issue with specific timeline settings
  // 3.0.2.9  : Fixed : Issue for specific click position in Planner header.
  // 3.0.2.10 : Fixed : Issue with adding items with date in plDay mode with date overlapping time axis
  //          : Fixed : Issue with header group caption drawing when using custom groups
  // 3.0.2.11 : Fixed : Issue with setting end time in plCustomList mode
  // 3.0.2.12 : Fixed : Issue with ShowCurrent & OnGetCurrentTime with a TDBDaySource
  //          : Fixed : Issue with use of HTMLOptions.TableStyle for horiz. time axis.
  // 3.0.2.13 : Fixed : Issue with anchor handling when PlannerItem.ImageId is used
  // 3.0.2.14 : Improved : Minor item caption rendering issue when caption images are used
  // 3.0.2.15 : Improved : Small performance improvement when rendering ShowCurrentTime
  // 3.0.3.0  : New : Support added for import & export to Google & Windows Live Calendar via TMS Cloud Pack
  //          : Fixed : Issue with monthly recurrencies at end of the month
  // 3.0.3.1  : Fixed : Issue with AutoCreateOnSelect and Overlap = false
  //          : Fixed : Cut-off hour text on horizontal time-axis
  // 3.0.3.2  : Fixed : Event OnItemCreated now triggered for items created via AutoCreateOnSelect
  // 3.0.3.3  : Fixed : Issue with Planner export to HTML and sidebar position in right, left/right positions
  // 3.0.3.4  : Fixed : Issue with HasItem() and selected items
  // 3.0.3.5  : Fixed : Small issue with OnPlannerGetSideBarLines for plTimeLine mode in specific conditions
  // 3.0.3.6  : Fixed : Issue with possible division by zero in plTimeLine mode
  // 3.0.3.7  : Fixed : Issue with painting of item links
  // 3.0.3.8  : Fixed : Issue with OnItemImageClick when many images are used in the PlannerItem
  // 3.0.3.9  : Fixed : Rare issue with division by zero in timeline mode
  //          : Fixed : Issue with OnPlannerSelectCell triggered unnecessary
  // 3.0.4.0  : New : Delphi XE5 & C++Builder XE5 support
  // 3.0.4.1  : Fixed: Issue with vertically oriented text in timeline mode
  // 3.0.4.2  : Fixed: Issue with printing PictureContainer images in header
  // 3.0.5.0  : New : Exposed Touch property & OnGesture event
  //          : Fixed: Issue with Assign()
  // 3.0.6.0  : New : PlannerItem.CaptionDivider: boolean property added
  //          : New : SideBar.TimeIndicatorType itFullLine added
  // 3.0.6.1  : Fixed : Issue with sidebar horizontal printing in timeline mode
  // 3.0.7.0  : New : property SelectOnRightClick added
  // 3.0.8.0  : New : Support for Delphi XE6 & C++Builder XE6 Prof, Ent. Architect added
  // 3.0.8.1  : Fixed : Issue with ShowLinks in horiz. time axis mode
  // 3.0.8.2  : Fixed : Issue with PlannerItem imagelist imageclick detection in vertical mode
  // 3.0.9.0  : Improved : Automatic handling of radio button click in HTML formatted planner items
  // 3.1.0.0  : New : Property DrawTag: string added in TPlannerItem
  //          : New : TImageDrawTool component added to draw images on the planner
  // 3.1.1.0  : New : OnPlannerBkgProp event added
  // 3.2.0.0  : New : EditOnSelectedClick property added
  //          : New : TimePointers
  //          : Improved : OnItemDblClick event triggered for background items
  // 3.2.0.1  : Fixed : Issue with loading from DB for items crossing end of time axis
  // 3.2.1.0  : New : Configurable arrows on link lines between items
  // 3.2.1.1  : Fixed : Calculation of event position in plDay mode for overlapping days
  // 3.2.2.0  : New : LineArrowSize, LineArrowShape properties added
  //          : New : Wordwrapped header drawing now also takes VAlignment in account
  //          : Improved : Painting performance for showing links
  // 3.2.2.1  : Fixed : Issue with multiday DBPlanner views
  // 3.2.2.2  : Improved : Time pointer painting
  //          : Improved : Painting performance with linked items
  // 3.2.3.0  : New : Delphi XE7 & C++Builder XE7 support
  // 3.2.3.1  : Fixed : Issue with setting end time on items for multiday Planner
  //          : Fixed : Issue with updating Planner.Display while items are being displayed
  // 3.2.3.2  : Fixed : Issue with HTML generation
  // 3.2.3.3  : Fixed : Rare issue with Planner popup menu and ItemSelection.Button <> sbLeft
  // 3.2.3.4  : Fixed : Issue with OnDragOverItem
  // 3.2.3.5  : Improved : Link painting
  // 3.2.3.6  : Improved : Link painting
  // 3.2.3.7  : Fixed : Painting issue for background items in horiz. mode
  // 3.2.3.8  : Fixed : Issue with balloon destroy
  // 3.2.4.0  : New : OnHeaderGroupDrawProp event added
  // 3.2.4.1  : Improved : Behaviour with EditSelectedOnClick = false and DirectMove = true
  // 3.2.5.0  : New : Public property Planner.CheckConflicts added for faster handling in cases where no overlap can occur
  //          : Fixed : Issue with display in timeline mode of items shorter than time unit
  // 3.2.5.1  : Fixed : Issue with OnItemEndEdit when clicking on Planner header
  // 3.2.6.0  : New : Public method ClearImageCache added
  // 3.2.6.1  : Fixed : Item sizing issue with EditOnSelectedClick = false
  // 3.2.6.2  : Fixed : Rare issue with items with non solid brush patterns
  // 3.2.6.3  : Fixed : Issue with invisible sidebar at position spRight
  // 3.3.0.0  : New : PDF export added
  // 3.3.0.1  : Fixed : Initialization issue on design-time inserted items
  //          : Fixed : Painting issue with non solid rounded items
  // 3.3.0.2  : Improved : Painting background for rounded items
  //          : Fixed:  Header item painting issue when sidebar is right-positioned
  // 3.3.0.3  : Fixed : Issue with DirectMove = true with horiz. time-axis
  // 3.3.0.4  : Fixed : Issue with SelectionAlways = false and horiz. time-axis
  // 3.3.1.0  : New : Support for VCL styles
  //          : New : Events OnItemCut, OnItemCopy, OnItemPaste added
  //          : Fixed : Issue with footer printing
  // 3.3.1.1  : Fixed : Issue with item image transparency during printing
  // 3.3.2.0  : New : OnItemCompletionSettings event added for customization of item completion per item
  // 3.3.3.0  : New : Event OnItemHintTime added
  // 3.3.3.1  : Fixed : Issue with ColorActive use in plCustomList mode
  // 3.3.3.2  : Fixed : Issue with header wordwrap drawing
  // 3.3.3.3  : Fixed : Issue with position gap when sidebar position is spLeftRight
  //          : Fixed : Rare issue with specific recurrency pattern
  // 3.3.3.4  : Improved : Time-axis display for very small display scale values
  // 3.3.3.5  : Fixed : Issue with header item painting
  // 3.3.4.0  : New : Windows 10, Office 2016 styles added
  //          : New : Planner.Items.HasHeaderItem added
  //          : Fixed : Issue with current time indication in multiresource setup
  // 3.3.4.1  : Fixed : Issue with Metropolis VCL styles
  // 3.3.4.2  : Fixed : Issue with OnPlannerBkgProp event handler
  //          : Fixed : Issue with printing items with multiple imagelist images
  // 3.3.4.3  : Fixed : Time-slot text display control with Planner.Display.DisplayText in timeline mode
  // 3.3.5.0  : New : Planner.Mode.MultiResource: boolean public property added
  // 3.3.5.1  : Fixed : Issue with getting Planner.Mode.PeriodStartDate
  // 3.3.6.0  : New : Support for Office 2016 for auto theme adaption
  // 3.3.7.0  : New : RAD Studio 10 Seattle support
  // 3.3.7.1  : Fixed : Issue with OnHeaderClick when resizing the header
  // 3.3.7.2  : Fixed : Issue with OnItemPasting event and handling Allow parameter

  s_QuickConfig = 'Quick config';
  s_HTimeAxis = 'Horizontal time axis';
  s_VTimeAxis = 'Vertical time axis';
  s_ShowDesignItem = 'Show design item';
  s_HideDesignItem = 'Hide design item';

  s_Modes: array [0 .. 5] of string = ('Select day mode', 'Select month mode',
    'Select day period mode', 'Select half day period mode',
    'Select multimonth mode', 'Select timeline mode');


  TTI_NONE = 0;
{$EXTERNALSYM TTI_NONE}
  TTI_ERROR = 3;
{$EXTERNALSYM TTI_ERROR}
  TTI_INFO = 1;
{$EXTERNALSYM TTI_INFO}
  TTI_WARNING = 2;
{$EXTERNALSYM TTI_WARNING}
  TTI_EMPTY = 4;
{$EXTERNALSYM TTI_EMPTY}
  TTS_BALLOON = $40;
{$EXTERNALSYM TTS_BALLOON}

{$IFDEF DELPHI_UNICODE}
  TTM_SETTITLE = (WM_USER + 33);
{$ENDIF}
{$IFNDEF DELPHI_UNICODE}
  TTM_SETTITLE = (WM_USER + 32);
{$ENDIF}

{$EXTERNALSYM TTM_SETTITLE}

var
  CF_PLANNERITEM: Word;

const
  crZoomIn = 100;
  crZoomOut = 101;

  EDITOFFSET = 2;

  MININDAY = 1440;

  ARROW_SIZE = 5;

  // Values only applicable for Delphi 4, C++Builder 4
  MAX_COLS = 192; // previous value 512 caused problems to run on ActiveForm
  MAX_ROWS = 288; // previous value 512 caused problems to run on ActiveForm

  CORNER_EFFECT = 10;
{$IFDEF FREEWARE}
  COPYRIGHT = 'Printed by %s © 1998 - 2015 by TMS software';
{$ENDIF}

type
{$IFDEF DELPHI_UNICODE}
  THintInfo = Controls.THintInfo;
  PHintInfo = Controls.PHintInfo;
{$ENDIF}

  TCustomPlanner = class;

  TPlannerGrid = class;
  TPlannerItem = class;

  TPlannerBarItem = class;
  TPlannerBarItemList = class;
  TPlannerIntList = class;

  EPlannerError = class(Exception);

  TPlannerGradientDirection = (gdHorizontal, gdVertical);

  XPColorScheme = (xpNone, xpBlue, xpGreen, xpGray, xpNoTheme);

  TItemEvent = procedure(Sender: TObject; Item: TPlannerItem) of object;

  TItemGaugeEvent = procedure(Sender: TObject; Item: TPlannerItem; var GaugeSettings: TGaugeSettings) of object;

  TItemAllowEvent = procedure(Sender: TObject; Item: TPlannerItem; var Allow: boolean) of object;

  TAllowEvent = procedure(Sender: TObject; var Allow: boolean) of object;

  TPlannerAnchorEvent = procedure(Sender: TObject; X, Y: Integer; Anchor: string) of object;

  TItemControlEvent = procedure(Sender: TObject; X, Y: Integer;
    Item: TPlannerItem; ControlID, ControlType, ControlValue: string) of object;

  TItemComboControlEvent = procedure(Sender: TObject; X, Y: Integer;
    Item: TPlannerItem; ControlID, ControlValue: string; ComboIdx: Integer;
    ComboObject: TObject) of object;

  TItemControlListEvent = procedure(Sender: TObject; Item: TPlannerItem;
    ControlID, ControlValue: string; var Edit: Boolean; Values: TStringList;
    var Dropheight: Integer) of object;

  TItemAnchorEvent = procedure(Sender: TObject; Item: TPlannerItem;
    Anchor: string) of object;

  TItemImageEvent = procedure(Sender: TObject; Item: TPlannerItem;
    ImageIndex: Integer) of object;

  TItemHintEvent = procedure(Sender: TObject; Item: TPlannerItem;
    var Hint: string) of object;

  TItemLinkEvent = procedure(Sender: TObject; Item: TPlannerItem;
    Link: string; var AutoHandle: Boolean) of object;

  TItemMoveEvent = procedure(Sender: TObject; Item: TPlannerItem;
    FromBegin, FromEnd, FromPos, ToBegin, ToEnd, ToPos: Integer) of object;

  TItemMovingEvent = procedure(Sender: TObject; Item: TPlannerItem;
    DeltaBegin, DeltaPos: Integer; var Allow: Boolean) of object;

  TItemUpdateEvent = procedure(Sender: TObject; Item: TPlannerItem;
    var NewBegin, NewEnd, NewPos: Integer) of object;

  TItemSizingEvent = procedure(Sender: TObject; Item: TPlannerItem;
    DeltaBegin, DeltaEnd: Integer; var Allow: Boolean) of object;

  TItemDragEvent = procedure(Sender: TObject; Item: TPlannerItem;
    var Allow: Boolean) of object;

  TItemBalloonEvent = procedure(Sender: TObject; APlannerItem: TPlannerItem;
    var ATitle: string; var AText: string; var AIcon: Integer) of object;

  TPlannerBalloonEvent = procedure(Sender: TObject; X, Y: Integer;
    var ATitle: string; var AText: string; var AIcon: Integer) of object;

  TItemClipboardAction = (itCut, itCopy, itPaste);

  TItemClipboardEvent = procedure(Sender: TObject; Item: TPlannerItem;
    Action: TItemClipboardAction; var Text: string) of object;

  TItemPaintEvent = procedure(Sender: TObject; Item: TPlannerItem;
    ACanvas: TCanvas; ARect: TRect) of object;

  TItemSizeEvent = procedure(Sender: TObject; Item: TPlannerItem;
    Position, FromBegin, FromEnd, ToBegin, ToEnd: Integer) of object;

  TItemPopupPrepareEvent = procedure(Sender: TObject; PopupMenu: TPopupMenu;
    Item: TPlannerItem) of object;

  TPlannerEvent = procedure(Sender: TObject;
    Position, FromSel, FromSelPrecise, ToSel,
    ToSelPrecise: Integer) of object;

  TPlannerKeyEvent = procedure(Sender: TObject; var Key: Char;
    Position, FromSel, FromSelPrecis, ToSel, ToSelPrecis: Integer) of object;

  TPlannerKeyDownEvent = procedure(Sender: TObject; var Key: Word;
    Shift: TShiftState; Position, FromSel, FromSelPrecis, ToSel,
    ToSelPrecis: Integer) of object;

  TPlannerItemDraw = procedure(Sender: TObject; PlannerItem: TPlannerItem;
    Canvas: TCanvas; Rect: TRect; Selected: Boolean) of object;

  TPlannerItemText = procedure(Sender: TObject; PlannerItem: TPlannerItem;
    var Text: string) of object;

  TPlannerSideDraw = procedure(Sender: TObject; Canvas: TCanvas; Rect: TRect;
    Index: Integer) of object;

  TPlannerSideProp = procedure(Sender: TObject; Index: Integer;
    ABrush: TBrush; AFont: TFont; var ColorTo: TColor) of object;

  TPlannerBkgDraw = procedure(Sender: TObject; Canvas: TCanvas; Rect: TRect;
    Index, Position: Integer) of object;

  TPlannerBkgProp = procedure(Sender: TObject; Index, Position: Integer;
    ABrush: TBrush; APen: TPen) of object;

  TPlannerHeaderDraw = procedure(Sender: TObject; Canvas: TCanvas;
    Rect: TRect; Index: Integer; var DoDraw: Boolean) of object;

  TPlannerHeaderProp = procedure(Sender: TObject; ABrush: TBrush;
    var ColorTo: TColor; AFont: TFont; var AAlignment: TAlignment) of object;

  THeaderHeightChangeEvent = procedure(Sender: TObject;
    NewSize: Integer) of object;

  TPlannerCaptionDraw = procedure(Sender: TObject; Canvas: TCanvas;
    Rect: TRect; var DoDraw: Boolean) of object;

  TPlannerPlanTimeToStrings = procedure(Sender: TObject;
    MinutesValue: Cardinal; var HoursString, MinutesString,
    AmPmString: string) of object;

  TPlannerGetSideBarLines = procedure(Sender: TObject;
    Index, Position: Integer; var HourString, MinuteString,
    AmPmString: string) of object;

  TPlannerPrintEvent = procedure(Sender: TObject; Canvas: TCanvas) of object;

  TPlannerSelectCellEvent = procedure(Sender: TObject; Index, Pos: Integer;
    var CanSelect: Boolean) of object;

  TPlannerBottomLineEvent = procedure(Sender: TObject; Index, Pos: Integer;
    APen: TPen) of object;

  TGetCurrentTimeEvent = procedure(Sender: TObject;
    var CurrentTime: TDateTime) of object;

  TPlannerBtnEvent = procedure(Sender: TObject) of object;

  TSideBarPosition = (spLeft, spRight, spTop, spLeftRight);
  TSideBarOrientation = (soHorizontal, soVertical);

  TCustomEditEvent = procedure(Sender: TObject; R: TRect;
    Item: TPlannerItem) of object;

  TPlannerPositionToDay = procedure(Sender: TObject; Pos: Integer;
    var Day: TDateTime) of object;

  TPlannerPositionZoom = procedure(Sender: TObject; Pos: Integer;
    ZoomIn: Boolean) of object;

  TPlannerBeforePositionZoom = procedure(Sender: TObject; Pos: Integer;
    ZoomIn: Boolean; var Allow: Boolean) of object;

  TPlannerActiveEvent = procedure(Sender: TObject; Index, Position: Integer;
    var Active: Boolean) of object;

  TPlannerPrintHFEvent = procedure(Sender: TObject; ACanvas: TCanvas;
    DrawRect: TRect) of object;

  TPlannerHeaderSizeEvent = procedure(Sender: TObject;
    APosition, AWidth: Integer) of object;

  TCustomITEvent = procedure(Sender: TObject; Index: Integer;
    var DT: TDateTime) of object;
  TCustomTIEvent = procedure(Sender: TObject; DT: TDateTime;
    var Index: Integer) of object;

  TDragOverHeaderEvent = procedure(Sender: TObject; Source: TObject;
    Position: Integer; State: TDragState; var Accept: Boolean) of object;

  TDragDropHeaderEvent = procedure(Sender: TObject; Source: TObject;
    Position: Integer) of object;

  {TCompletion}
  TCompletion = class(TPersistent)
  private
    FStacked: Boolean;
    FShowBorder: Boolean;
    FShowGradient: Boolean;
    FCompletionSmooth: Boolean;
    FShowPercentage: Boolean;
    FLevel2Perc: Integer;
    FSteps: Integer;
    FLevel1Perc: Integer;
    FLevel0Color: TColor;
    FLevel1Color: TColor;
    FLevel3Color: TColor;
    FLevel3ColorTo: TColor;
    FLevel2ColorTo: TColor;
    FLevel2Color: TColor;
    FBorderColor: TColor;
    FLevel1ColorTo: TColor;
    FBackgroundColor: TColor;
    FLevel0ColorTo: TColor;
    FFont: TFont;
    FOnChange: TNotifyEvent;
    procedure SetBackGroundColor(const value: TColor);
    procedure SetBorderColor(const value: TColor);
    procedure SetCompletionSmooth(const value: Boolean);
    procedure SetFont(const value: TFont);
    procedure SetLevel0Color(const value: TColor);
    procedure SetLevel0ColorTo(const value: TColor);
    procedure SetLevel1Color(const value: TColor);
    procedure SetLevel1ColorTo(const value: TColor);
    procedure SetLevel1Perc(const value: Integer);
    procedure SetLevel2Color(const value: TColor);
    procedure SetLevel2ColorTo(const value: TColor);
    procedure SetLevel2Perc(const value: Integer);
    procedure SetLevel3Color(const value: TColor);
    procedure SetLevel3ColorTo(const value: TColor);
    procedure SetShowBorder(const value: Boolean);
    procedure SetShowGradient(const value: Boolean);
    procedure SetShowPercentage(const value: Boolean);
    procedure SetStacked(const value: Boolean);
    procedure SetSteps(const value: Integer);
  public
    constructor Create;
    destructor Destroy; override;
    procedure Assign(Source: TPersistent); override;
    procedure Changed;
  published
    property Level0Color: TColor read FLevel0Color write SetLevel0Color default clLime;
    property Level0ColorTo: TColor read FLevel0ColorTo write SetLevel0ColorTo default clWhite;
    property Level1Color: TColor read FLevel1Color write SetLevel1Color default clYellow;
    property Level1ColorTo: TColor read FLevel1ColorTo write SetLevel1ColorTo default clWhite;
    property Level2Color: TColor read FLevel2Color write SetLevel2Color default 50943;
    property Level2ColorTo: TColor read FLevel2ColorTo write SetLevel2ColorTo default clWhite;
    property Level3Color: TColor read FLevel3Color write SetLevel3Color default clRed;
    property Level3ColorTo: TColor read FLevel3ColorTo write SetLevel3ColorTo default clWhite;
    property Level1Perc: Integer read FLevel1Perc write SetLevel1Perc default 70;
    property Level2Perc: Integer read FLevel2Perc write SetLevel2Perc default 90;
    property BorderColor: TColor read FBorderColor write SetBorderColor default clGray;
    property ShowBorder: Boolean read FShowBorder write SetShowBorder default True;
    property Stacked: Boolean read FStacked write SetStacked default False;
    property ShowPercentage: Boolean read FShowPercentage write SetShowPercentage default True;
    property Font: TFont read FFont write SetFont;
    property CompletionSmooth: Boolean read FCompletionSmooth write SetCompletionSmooth default True;
    property ShowGradient: Boolean read FShowGradient write SetShowGradient default True;
    property Steps: Integer read FSteps write SetSteps default 8;
    property BackgroundColor: TColor read FBackgroundColor write SetBackGroundColor default clBtnFace;
    property OnChange: TNotifyEvent read FOnChange write FOnChange;
  end;

  {TBalloonSettings}
  TBalloonSettings = class(TPersistent)
  private
    FBackgroundColor: TColor;
    FTextColor: TColor;
    FReshowDelay: Integer;
    FInitialDelay: Integer;
    FAutoHideDelay: Integer;
    FTransparency: Byte;
    FEnable: Boolean;
    FOnEnableChange: TNotifyEvent;
    procedure SetEnable(const value: Boolean);
  public
    constructor Create;
  published
    property AutoHideDelay: Integer read FAutoHideDelay write FAutoHideDelay default -1;
    property BackgroundColor: TColor read FBackgroundColor write FBackgroundColor default clNone;
    property Enable: Boolean read FEnable write SetEnable default True;
    property InitialDelay: Integer read FInitialDelay write FInitialDelay default -1;
    property ReshowDelay: Integer read FReshowDelay write FReshowDelay default -1;
    property TextColor: TColor read FTextColor write FTextColor default clNone;
    property Transparency: Byte read FTransparency write FTransparency default 0;
    property OnEnableChange: TNotifyEvent read FOnEnableChange write FOnEnableChange;
  end;

  {$IFDEF TMSSKINS}

  {TPlannerSkin}
  TPlannerSkin = class(TPersistent)
  private
    FOwner: TCustomControl;
    FSkinTop: TBitmap;
    FSkinCenter: TBitmap;
    FSkinBottom: TBitmap;
    FSkinSelectTop: TBitmap;
    FSkinSelectCenter: TBitmap;
    FSkinSelectBottom: TBitmap;
    FSkinX: Integer;
    FSkinY: Integer;
    FSkinCaptionX: Integer;
    FSkinCaptionY: Integer;
    FOnChange: TNotifyEvent;
    procedure SetSkinTop(const AValue: TBitmap);
    procedure SetSkinCenter(const AValue: TBitmap);
    procedure SetSkinBottom(const AValue: TBitmap);
    procedure SetSkinSelectTop(const AValue: TBitmap);
    procedure SetSkinSelectCenter(const AValue: TBitmap);
    procedure SetSkinSelectBottom(const AValue: TBitmap);
  public
    constructor Create(AOwner: TCustomControl);
    destructor Destroy; override;
    procedure Assign(Source: TPersistent); override;
    procedure LoadFromFile(Filename: string);
    procedure ClearSkin;
  published
    property SkinTop: TBitmap read FSkinTop write SetSkinTop;
    property SkinCenter: TBitmap read FSkinCenter write SetSkinCenter;
    property SkinBottom: TBitmap read FSkinBottom write SetSkinBottom;
    property SkinSelectTop: TBitmap read FSkinSelectTop write SetSkinSelectTop;
    property SkinSelectCenter: TBitmap read FSkinSelectCenter write SetSkinSelectCenter;
    property SkinSelectBottom: TBitmap read FSkinSelectBottom write SetSkinSelectBottom;
    property SkinCaptionX: Integer read FSkinCaptionX write FSkinCaptionX default 0;
    property SkinCaptionY: Integer read FSkinCaptionY write FSkinCaptionY default 0;
    property SkinX: Integer read FSkinX write FSkinX default 0;
    property SkinY: Integer read FSkinY write FSkinY default 0;
    property OnChange: TNotifyEvent read FOnChange write FOnChange;
  end;
  {$ENDIF}

  {TBands}
  TBands = class(TPersistent)
  private
    FOwner: TCustomPlanner;
    FShow: Boolean;
    FActivePrimary: TColor;
    FActiveSecondary: TColor;
    FNonActivePrimary: TColor;
    FNonActiveSecondary: TColor;
    procedure SetActivePrimary(const value: TColor);
    procedure SetActiveSecondary(const value: TColor);
    procedure SetNonActivePrimary(const value: TColor);
    procedure SetNonActiveSecondary(const value: TColor);
    procedure SetShow(const value: Boolean);
  public
    constructor Create(AOwner: TCustomPlanner);
  published
    property Show: Boolean read FShow write SetShow default False;
    property ActivePrimary: TColor read FActivePrimary write SetActivePrimary default $00FEE7CB;
    property ActiveSecondary: TColor read FActiveSecondary write SetActiveSecondary default $00FAD9AF;
    property NonActivePrimary: TColor read FNonActivePrimary write SetNonActivePrimary default clSilver;
    property NonActiveSecondary: TColor read FNonActiveSecondary write SetNonActiveSecondary default $00A8A8A8;
  end;

  {TSyncPlanner}
  TSyncPlanner = class(TPersistent)
  private
    FOwner: TComponent;
    FScrollHorizontal: boolean;
    FPlanner: TCustomPlanner;
    FScrollVertical: boolean;
    FSelectionRow: boolean;
    FSelectionColumn: boolean;
    procedure SetPlanner(const Value: TCustomPlanner);
  public
    constructor Create(AOwner: TComponent);
    procedure Assign(Source: TPersistent); override;
  published
    property Planner: TCustomPlanner read FPlanner write SetPlanner;
    property ScrollVertical: boolean read FScrollVertical write FScrollVertical default false;
    property ScrollHorizontal: boolean read FScrollHorizontal write FScrollHorizontal default false;
    property SelectionColumn: boolean read FSelectionColumn write FSelectionColumn default false;
    property SelectionRow: boolean read FSelectionRow write FSelectionRow default false;
  end;

  TAMPMPos = (apUnderTime, apNextToTime, apNone);

  TTimeIndicatorType = (tiLine, tiGlyph, tiLineGlyph, tiFullLine);

  TArrowShape = (asNormal, asFilled);

  {TPlannerSideBar}
  TPlannerSideBar = class(TPersistent)
  private
    FAlignment: TAlignment;
    FBackGround: TColor;
    FBackGroundTo: TColor;
    FFont: TFont;
    FOwner: TCustomPlanner;
    FVisible: Boolean;
    FWidth: Integer;
    FColOffset: Integer;
    FRowOffset: Integer;
    FPosition: TSideBarPosition;
    FShowInPositionGap: Boolean;
    FShowOccupied: Boolean;
    FFlat: Boolean;
    FOccupied: TColor;
    FOccupiedTo: TColor;
    FOccupiedFontColor: TColor;
    FDateTimeFormat: string;
    FBorder: Boolean;
    FRotateOnTop: Boolean;
    FShowDayName: Boolean;
    FSeparatorLineColor: TColor;
    FAMPMPos: TAMPMPos;
    FActiveColor: TColor;
    FActiveColorTo: TColor;
    FLineColor: TColor;
    FTimeIndicator: Boolean;
    FTimeIndicatorColor: TColor;
    FHourFontRatio: double;
    FShowOtherTimeZone: Boolean;
    FTimeZoneOffset: Integer;
    FTimeIndicatorType: TTimeIndicatorType;
    FTimeIndicatorGlyph: TBitmap;
    FBorderColor: TColor;
    procedure SetAlignment(const value: TAlignment);
    procedure SetBackground(const value: TColor);
    procedure SetBackgroundTo(const value: TColor);
    procedure SetFont(const value: TFont);
    procedure FontChanged(Sender: TObject);
    procedure SetVisible(const value: Boolean);
    procedure SetWidth(const value: Integer);
    procedure SetPosition(const value: TSideBarPosition);
    function GetOrientation: TSideBarOrientation;
    procedure SetShowInPositionGap(const value: Boolean);
    procedure SetShowOccupied(const value: Boolean);
    procedure SetFlat(const value: Boolean);
    procedure SetOccupied(const value: TColor);
    procedure SetOccupiedTo(const value: TColor);
    procedure SetOccupiedFontColor(const value: TColor);
    procedure SetDateTimeFormat(const value: string);
    procedure SetBorder(const Value: Boolean);
    procedure SetBorderColor(const Value: TColor);
    procedure SetRotateOnTop(const Value: Boolean);
    procedure SetShowDayName(const Value: Boolean);
    procedure SetSeparatorLineColor(const value: TColor);
    procedure SetAMPMPos(const Value: TAMPMPos);
    procedure SetActiveColor(const Value: TColor);
    procedure SetActiveColorTo(const Value: TColor);
    procedure SetLineColor(const Value: TColor);
    procedure SetTimeIndicator(const Value: Boolean);
    procedure SetTimeIndicatorColor(const Value: TColor);
    procedure SetHourFontRatio(const Value: double);
    procedure SetShowOtherTimeZone(const Value: Boolean);
    procedure SetTimeZoneOffset(const Value: Integer);
    procedure SetTimeIndicatorGlyph(const Value: TBitmap);
    procedure SetTimeIndicatorType(const Value: TTimeIndicatorType);
  public
    constructor Create(AOwner: TCustomPlanner);
    destructor Destroy; override;
    procedure Assign(Source: TPersistent); override;
    property Orientation: TSideBarOrientation read GetOrientation;
  protected
    procedure UpdateGrid;
  published
    property ActiveColor: TColor read FActiveColor write SetActiveColor default clNone;
    property ActiveColorTo: TColor read FActiveColorTo write SetActiveColorTo default clNone;
    property Alignment: TAlignment read FAlignment write SetAlignment default taLeftJustify;
    property AMPMPos: TAMPMPos read FAMPMPos write SetAMPMPos default apUnderTime;
    property Background: TColor read FBackGround write SetBackground default clBtnFace;
    property BackgroundTo: TColor read FBackGroundTo write SetBackgroundTo default clWhite;
    property Border: Boolean read FBorder write SetBorder default True;
    property BorderColor: TColor read FBorderColor write SetBorderColor default clGray;
    property DateTimeFormat: string read FDateTimeFormat write SetDateTimeFormat;
    property Flat: Boolean read FFlat write SetFlat default True;
    property Font: TFont read FFont write SetFont;
    property HourFontRatio: double read FHourFontRatio write SetHourFontRatio;
    property LineColor: TColor read FLineColor write SetLineColor default clGray;
    property Occupied: TColor read FOccupied write SetOccupied default clBlue;
    property OccupiedTo: TColor read FOccupiedTo write SetOccupiedTo default clNone;
    property OccupiedFontColor: TColor read FOccupiedFontColor write SetOccupiedFontColor default clWhite;
    property Position: TSideBarPosition read FPosition write SetPosition default spLeft;
    property RotateOnTop: Boolean read FRotateOnTop write SetRotateOnTop default True;
    property SeparatorLineColor: TColor read FSeparatorLineColor write SetSeparatorLineColor default clGray;
    property ShowInPositionGap: Boolean read FShowInPositionGap write SetShowInPositionGap default False;
    property ShowOccupied: Boolean read FShowOccupied write SetShowOccupied default False;
    property ShowDayName: Boolean read FShowDayName write SetShowDayName default True;
    property ShowOtherTimeZone: Boolean read FShowOtherTimeZone write SetShowOtherTimeZone default False;
    property TimeIndicator: Boolean read FTimeIndicator write SetTimeIndicator default False;
    property TimeIndicatorColor: TColor read FTimeIndicatorColor write SetTimeIndicatorColor default clRed;
    property TimeIndicatorType: TTimeIndicatorType read FTimeIndicatorType write SetTimeIndicatorType default tiLine;
    property TimeIndicatorGlyph: TBitmap read FTimeIndicatorGlyph write SetTimeIndicatorGlyph;
    property TimeZoneMinDelta: Integer read FTimeZoneOffset write SetTimeZoneOffset default 0;
    property Visible: Boolean read FVisible write SetVisible default True;
    property Width: Integer read FWidth write SetWidth default 40;
  end;

  {TPlannerCaption}
  TPlannerCaption = class(TPersistent)
  private
    FTitle: string;
    FAlignment: TAlignment;
    FBackGround: TColor;
    FBackGroundTo: TColor;
    FFont: TFont;
    FOwner: TCustomPlanner;
    FHeight: Integer;
    FVisible: Boolean;
    FBackgroundSteps: Integer;
    FGradientDirection: TPlannerGradientDirection;
    procedure SetAlignment(const value: TAlignment);
    procedure SetBackground(const value: TColor);
    procedure SetFont(const value: TFont);
    procedure SetTitle(const value: string);
    procedure SetHeigth(const value: Integer);
    procedure FontChanged(Sender: TObject);
    procedure SetVisible(const value: Boolean);
    procedure SetBackgroundTo(const value: TColor);
    procedure SetBackgroundSteps(const value: Integer);
    procedure SetGradientDirection(const value: TPlannerGradientDirection);
  protected
    procedure UpdatePanel;
  public
    constructor Create(AOwner: TCustomPlanner);
    destructor Destroy; override;
    procedure Assign(Source: TPersistent); override;
  published
    property Title: string read FTitle write SetTitle;
    property Font: TFont read FFont write SetFont;
    property Alignment: TAlignment read FAlignment write SetAlignment default taLeftJustify;
    property Background: TColor read FBackGround write SetBackground default clGray;
    property BackgroundSteps: Integer read FBackgroundSteps write SetBackgroundSteps default 128;
    property BackgroundTo: TColor read FBackGroundTo write SetBackgroundTo default clWhite;
    property GradientDirection: TPlannerGradientDirection read FGradientDirection write SetGradientDirection default gdHorizontal;
    property Height: Integer read FHeight write SetHeigth default 32;
    property Visible: Boolean read FVisible write SetVisible default True;
  end;

  TPlannerType = (plDay, plWeek, plMonth, plDayPeriod, plHalfDayPeriod,
    plMultiMonth, plCustom, plTimeLine, plCustomList, plActiveDayPeriod);

  {TPlannerPanel}
  TPlannerPanel = class(TPanel)
  private
    FPlanner: TCustomPlanner;
    FOldAnchor: string;
    function IsAnchor(X, Y: Integer): string;
    procedure CMDesignHitTest(var Msg: TCMDesignHitTest); message CM_DESIGNHITTEST;
    procedure WMEraseBkGnd(var Message: TMessage); message WM_ERASEBKGND;
  protected
    procedure Paint; override;
    procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
    procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
  public
    constructor Create(AOwner: TComponent); override;
  end;

  {TPlannerMode}
  TPlannerMode = class(TPersistent)
  private
    FClip: Boolean;
    FOwner: TCustomPlanner;
    FPlannerType: TPlannerType;
    FWeekStart: Integer;
    FDay: integer;
    FYear: Integer;
    FMonth: Integer;
    FDateTimeFormat: string;
    FPeriodStartDay: Integer;
    FPeriodStartMonth: Integer;
    FPeriodStartYear: Integer;
    FPeriodEndDay: Integer;
    FPeriodEndMonth: Integer;
    FPeriodEndYear: Integer;
    FUpdateCount: Integer;
    FTimeLineStart: TDateTime;
    FTimeLineNVUBegin: Integer;
    FTimeLineNVUEnd: Integer;
    FFullHalfDay: Boolean;
    FMultiResource: Boolean;
    procedure SetMonth(const value: Integer);
    procedure SetPlannerType(const value: TPlannerType);
    procedure SetWeekStart(const value: Integer);
    procedure SetYear(const value: Integer);
    procedure SetDateTimeFormat(const value: string);
    procedure SetPeriodStartDay(const value: Integer);
    procedure SetPeriodStartMonth(const value: Integer);
    procedure SetPeriodStartYear(const value: Integer);
    procedure SetPeriodEndDay(const value: Integer);
    procedure SetPeriodEndMonth(const value: Integer);
    procedure SetPeriodEndYear(const value: Integer);
    function GetPeriodEndDate: TDateTime;
    function GetPeriodStartDate: TDateTime;
    function GetStartOfMonth: TDateTime;
    procedure UpdatePeriod;
    procedure SetPeriodEndDate(const value: TDateTime);
    procedure SetPeriodStartDate(const value: TDateTime);
    procedure SetTimeLineStart(const value: TDateTime);
    procedure SetTimeLineNVUBegin(const value: Integer);
    procedure SetTimeLineNVUEnd(const value: Integer);
    procedure SetDay(const Value: integer);
    procedure AutoCorrectPeriod;
    function GetDate: TDate;
    procedure SetDate(const Value: TDate);
  public
    constructor Create(AOwner: TCustomPlanner);
    destructor Destroy; override;
    property PeriodStartDate: TDateTime read GetPeriodStartDate write SetPeriodStartDate;
    property PeriodEndDate: TDateTime read GetPeriodEndDate write SetPeriodEndDate;
    property StartOfMonth: TDateTime read GetStartOfMonth;
    procedure BeginUpdate;
    procedure EndUpdate;
    procedure Assign(Source: TPersistent); override;
    property FullHalfDay: Boolean read FFullHalfDay write FFullHalfDay;
    property MultiResource: Boolean read FMultiResource write FMultiResource;
    property Date: TDate read GetDate write SetDate;
  published
    property Clip: Boolean read FClip write FClip default False;
    property DateTimeFormat: string read FDateTimeFormat write SetDateTimeFormat;
    property Month: Integer read FMonth write SetMonth;
    property PeriodStartDay: Integer read FPeriodStartDay write SetPeriodStartDay;
    property PeriodStartMonth: Integer read FPeriodStartMonth write SetPeriodStartMonth;
    property PeriodStartYear: Integer read FPeriodStartYear write SetPeriodStartYear;
    property PeriodEndDay: Integer read FPeriodEndDay write SetPeriodEndDay;
    property PeriodEndMonth: Integer read FPeriodEndMonth write SetPeriodEndMonth;
    property PeriodEndYear: Integer read FPeriodEndYear write SetPeriodEndYear;
    property PlannerType: TPlannerType read FPlannerType write SetPlannerType default plDay;
    property TimeLineStart: TDateTime read FTimeLineStart write SetTimeLineStart;
    property TimeLineNVUBegin: Integer read FTimeLineNVUBegin write SetTimeLineNVUBegin;
    property TimeLineNVUEnd: Integer read FTimeLineNVUEnd write SetTimeLineNVUEnd;
    property WeekStart: Integer read FWeekStart write SetWeekStart default 0;
    property Year: Integer read FYear write SetYear;
    property Day: integer read FDay write SetDay;
  end;

  TPlannerMaskEdit = class(TMaskEdit)
  private
    FPlannerItem: TPlannerItem;
    procedure WMPaste(var Msg: TMessage); message WM_PASTE;
    procedure WMCopy(var Msg: TMessage); message WM_COPY;
    procedure WMCut(var Msg: TMessage); message WM_CUT;
  protected
    procedure KeyDown(var Key: Word; Shift: TShiftState); override;
    procedure DoExit; override;
  public
    procedure StopEdit;
  published
    property PlannerItem: TPlannerItem read FPlannerItem write FPlannerItem;
  end;

  TPlannerMemo = class(TMemo)
  private
    FPlannerItem: TPlannerItem;
    FPlanner: TCustomPlanner;
    procedure WMPaste(var Msg: TMessage); message WM_PASTE;
    procedure WMCopy(var Msg: TMessage); message WM_COPY;
    procedure WMCut(var Msg: TMessage); message WM_CUT;
  protected
    procedure KeyDown(var Key: Word; Shift: TShiftState); override;
    procedure DoEnter; override;
    procedure DoExit; override;
    procedure DblClick; override;
  public
    procedure StopEdit;
  published
    property PlannerItem: TPlannerItem read FPlannerItem write FPlannerItem;
    property Planner: TCustomPlanner read FPlanner write FPlanner;
  end;
{$IFNDEF DELPHI_UNICODE}

  TPlannerUniMemo = class(TPlanUniMemo)
  private
    FPlannerItem: TPlannerItem;
    FPlanner: TCustomPlanner;
    procedure WMPaste(var Msg: TMessage); message WM_PASTE;
    procedure WMCopy(var Msg: TMessage); message WM_COPY;
    procedure WMCut(var Msg: TMessage); message WM_CUT;
  protected
    procedure KeyDown(var Key: Word; Shift: TShiftState); override;
    procedure DoEnter; override;
    procedure DoExit; override;
    procedure DblClick; override;
  public
  published
    property PlannerItem: TPlannerItem read FPlannerItem write FPlannerItem;
    property Planner: TCustomPlanner read FPlanner write FPlanner;
  end;
{$ENDIF}

  TPlannerRichEdit = class(TRichEdit)
  private
    FPlannerItem: TPlannerItem;
  protected
    procedure KeyDown(var Key: Word; Shift: TShiftState); override;
    procedure DoEnter; override;
    procedure DoExit; override;
  published
    property PlannerItem: TPlannerItem read FPlannerItem write FPlannerItem;
  end;

  TPlannerDisplay = class(TPersistent)
  private
    FOwner: TCustomPlanner;
    FDisplayStart: Integer;
    FDisplayScale: Integer;
    FDisplayEnd: Integer;
    FDisplayUnit: Integer;
    FActiveEnd: Integer;
    FActiveStart: Integer;
    FColorNonActive: TColor;
    FColorActive: TColor;
    FColorCurrent: TColor;
    FColorCurrentItem: TColor;
    FActiveStartPrecis: Integer;
    FActiveEndPrecis: Integer;
    FDisplayStartPrecis: Integer;
    FDisplayEndPrecis: Integer;
    FShowCurrent: Boolean;
    FShowCurrentItem: Boolean;
    FScaleToFit: Boolean;
    FOldScale: Integer;
    FDisplayOffset: Integer;
    FUpdateCount: Integer;
    FUpdateUnit: Boolean;
    FDisplayText: Integer;
    FCurrentPosFrom: Integer;
    FCurrentPosTo: Integer;
    FHourLineColor: TColor;
    FColorNonSelect: TColor;
    FBrushNonSelect: TBrushStyle;
    procedure SetDisplayStart(const value: Integer);
    procedure SetDisplayEnd(const value: Integer);
    procedure SetDisplayScale(const value: Integer);
    procedure SetDisplayUnit(const value: Integer);
    procedure SetDisplayOffset(const value: Integer);
    procedure UpdatePlanner;
    procedure SetActiveEnd(const value: Integer);
    procedure SetActiveStart(const value: Integer);
    procedure SetColorActive(const value: TColor);
    procedure SetColorNonActive(const value: TColor);
    procedure SetColorCurrent(const value: TColor);
    procedure SetShowCurrent(const value: Boolean);
    procedure SetColorCurrentItem(const value: TColor);
    procedure SetShowCurrentItem(const value: Boolean);
    procedure SetScaleToFit(const value: Boolean);
    procedure SetDisplayText(const value: Integer);
    procedure SetCurrentPosFrom(const value: Integer);
    procedure SetCurrentPosTo(const value: Integer);
    procedure SetHourLineColor(const value: TColor);
    procedure SetColorNonSelect(const Value: TColor);
    procedure SetBrushNonSelect(const Value: TBrushStyle);
  protected
    procedure InitPrecis;
    procedure AutoScale;
  public
    constructor Create(AOwner: TCustomPlanner);
    destructor Destroy; override;
    procedure Assign(Source: TPersistent); override;
    procedure BeginUpdate;
    procedure EndUpdate;
  published
    property ActiveStart: Integer read FActiveStart write SetActiveStart default 16;
    property ActiveEnd: Integer read FActiveEnd write SetActiveEnd default 47;
    property BrushNonSelect: TBrushStyle read FBrushNonSelect write SetBrushNonSelect default bsFDiagonal;
    property CurrentPosFrom: Integer read FCurrentPosFrom write SetCurrentPosFrom default -1;
    property CurrentPosTo: Integer read FCurrentPosTo write SetCurrentPosTo default -1;
    property DisplayStart: Integer read FDisplayStart write SetDisplayStart default 0;
    property DisplayEnd: Integer read FDisplayEnd write SetDisplayEnd default 47;
    property DisplayOffset: Integer read FDisplayOffset write SetDisplayOffset default 0;
    property DisplayScale: Integer read FDisplayScale write SetDisplayScale default 24;
    property DisplayUnit: Integer read FDisplayUnit write SetDisplayUnit default 30;
    property DisplayText: Integer read FDisplayText write SetDisplayText default 0;
    property ColorActive: TColor read FColorActive write SetColorActive default clWhite;
    property ColorNonActive: TColor read FColorNonActive write SetColorNonActive default $00DEDEDE;
    property ColorNonSelect: TColor read FColorNonSelect write SetColorNonSelect default clGray;
    property ColorCurrent: TColor read FColorCurrent write SetColorCurrent default clYellow;
    property ColorCurrentItem: TColor read FColorCurrentItem write SetColorCurrentItem default clLime;
    property HourLineColor: TColor read FHourLineColor write SetHourLineColor default clGray;
    property ScaleToFit: Boolean read FScaleToFit write SetScaleToFit default False;
    property ShowCurrent: Boolean read FShowCurrent write SetShowCurrent default False;
    property ShowCurrentItem: Boolean read FShowCurrentItem write SetShowCurrentItem default False;
  end;

  TNavigatorButtons = class(TPersistent)
  private
    FOwner: TCustomPlanner;
    FVisible: Boolean;
    FShowHint: Boolean;
    FNextHint: string;
    FPrevHint: string;
    FFlat: Boolean;
    procedure SetVisible(value: Boolean);
    procedure SetNextHint(const value: string);
    procedure SetPrevHint(const value: string);
    procedure SetShowHint(const value: Boolean);
    procedure SetFlat(const value: Boolean);
  public
    constructor Create(AOwner: TCustomPlanner);
  published
    property Flat: Boolean read FFlat write SetFlat default True;
    property Visible: Boolean read FVisible write SetVisible default True;
    property PrevHint: string read FPrevHint write SetPrevHint;
    property NextHint: string read FNextHint write SetNextHint;
    property ShowHint: Boolean read FShowHint write SetShowHint default False;
  end;

  TImagePosition = (ipLeft, ipRight);

  TCompletionType = (ctFullTime, ctActiveTime);

  TPlannerFooter = class(TPersistent)
  private
    FOwner: TCustomPlanner;
    FFlat: Boolean;
    FVisible: Boolean;
    FHeight: Integer;
    FAlignment: TAlignment;
    FColorTo: TColor;
    FLineColor: TColor;
    FColor: TColor;
    FFont: TFont;
    FImages: TImageList;
    FImagePosition: TImagePosition;
    FCaptions: TStringList;
    FVAlignment: TVAlignment;
    FShowCompletion: Boolean;
    FCompletion: TCompletion;
    FCustomCompletionValue: Boolean;
    FCompletionType: TCompletionType;
    FCompletionFormat: string;
    procedure SetAlignment(const value: TAlignment);
    procedure SetCaptions(const value: TStringList);
    procedure SetColor(const value: TColor);
    procedure SetColorTo(const value: TColor);
    procedure SetFlat(const value: Boolean);
    procedure SetFont(const value: TFont);
    procedure SetHeight(const value: Integer);
    procedure SetImagePosition(const value: TImagePosition);
    procedure SetImages(const value: TImageList);
    procedure SetLineColor(const value: TColor);
    procedure SetVAlignment(const value: TVAlignment);
    procedure SetVisible(const value: Boolean);
    procedure ItemsChanged(Sender: TObject);
    procedure SetShowCompletion(const value: Boolean);
    function GetCompletionValue(Index: Integer): Integer;
    procedure SetCompletionValue(Index: Integer; const value: Integer);
    procedure SetCustomCompletionValue(const value: Boolean);
    procedure SetCompletionType(const value: TCompletionType);
    procedure SetCompletionFormat(const value: string);
  public
    constructor Create(AOwner: TCustomPlanner);
    destructor Destroy; override;
    procedure Assign(Source: TPersistent); override;
    property CompletionValue[Index: Integer]: Integer read GetCompletionValue write SetCompletionValue;
  published
    property Alignment: TAlignment read FAlignment write SetAlignment default taLeftJustify;
    property Captions: TStringList read FCaptions write SetCaptions;
    property CompletionFormat: string read FCompletionFormat write SetCompletionFormat;
    property CompletionType: TCompletionType read FCompletionType write SetCompletionType default ctFullTime;
    property Color: TColor read FColor write SetColor default clBtnFace;
    property ColorTo: TColor read FColorTo write SetColorTo default clWhite;
    property Completion: TCompletion read FCompletion write FCompletion;
    property CustomCompletionValue: Boolean read FCustomCompletionValue write SetCustomCompletionValue default False;
    property Height: Integer read FHeight write SetHeight default 32;
    property Flat: Boolean read FFlat write SetFlat default False;
    property Font: TFont read FFont write SetFont;
    property Images: TImageList read FImages write SetImages;
    property ImagePosition: TImagePosition read FImagePosition write SetImagePosition default ipLeft;
    property LineColor: TColor read FLineColor write SetLineColor default clBlack;
    property ShowCompletion: Boolean read FShowCompletion write SetShowCompletion default False;
    property VAlignment: TVAlignment read FVAlignment write SetVAlignment default vtaCenter;
    property Visible: Boolean read FVisible write SetVisible default False;
  end;

  TGroupCollectionItem = class(TCollectionItem)
  private
    FTag: Integer;
    FImageIndex: Integer;
    FSpan: Integer;
    FCaption: string;
    FWideCaption: widestring;
    procedure SetCaption(const value: string);
    procedure SetImageIndex(const value: Integer);
    procedure SetSpan(const value: Integer);
    procedure SetWideCaption(const value: widestring);
  protected
  public
    constructor Create(Collection: TCollection); override;
    procedure Assign(Source: TPersistent); override;
  published
    property Caption: string read FCaption write SetCaption;
    property WideCaption: widestring read FWideCaption write SetWideCaption;
    property Span: Integer read FSpan write SetSpan default 1;
    property Tag: Integer read FTag write FTag default 0;
    property ImageIndex: Integer read FImageIndex write SetImageIndex default -1;
  end;

  TGroupCollection = class(TOwnedCollection)
  private
    FOwner: TPersistent;
    FOnChange: TNotifyEvent;
    function GetItem(Index: Integer): TGroupCollectionItem;
    procedure SetItem(Index: Integer; AItem: TGroupCollectionItem);
  protected
    procedure DoChanged; virtual;
  public
    constructor Create(AOwner: TPersistent; AItemClass: TCollectionItemClass);
    procedure Assign(Source: TPersistent); override;
    function Add: TGroupCollectionItem;
    function Insert(Index: Integer): TGroupCollectionItem;
    property Items[Index: Integer]: TGroupCollectionItem read GetItem write SetItem; default;
    property OnChange: TNotifyEvent read FOnChange write FOnChange;
  end;

  TPlannerStringList = class(TStringList)
  private
    function GetItem(Index: Integer): string;
    procedure SetItem(Index: Integer; const value: string);
  public
    property Strings[Index: Integer]: string read GetItem write SetItem; default;
  end;

  THeaderCustomColor = (ccAll, ccNone, ccGroup, ccItem);

  TPlannerHeader = class(TPersistent)
  private
    FOwner: TCustomPlanner;
    FCaptions: TPlannerStringList;
    FVisible: Boolean;
    FHeight: Integer;
    FFont: TFont;
    FGroupFont: TFont;
    FColor: TColor;
    FFlat: Boolean;
    FAlignment: TAlignment;
    FVAlignment: TVAlignment;
    FImages: TImageList;
    FImagePosition: TImagePosition;
    FReadOnly: Boolean;
    FItemHeight: Integer;
    FTextHeight: Integer;
    FAllowResize: Boolean;
    FAllowPositionResize: Boolean;
    FAutoSize: Boolean;
    FItemColor: TColor;
    FGroupHeight: Integer;
    FGroupCaptions: TPlannerStringList;
    FPopupMenu: TPopupMenu;
    FLineColor: TColor;
    FColorTo: TColor;
    FRotateOnLeft: Boolean;
    FRotateGroupOnLeft: Boolean;
    FRotateOnTop: Boolean;
    FResizeAll: Boolean;
    FShowHint: Boolean;
    FActiveColor: TColor;
    FActiveColorTo: TColor;
    FGroupSpan: TPlannerIntList;
    FCustomGroups: TGroupCollection;
    FWordWrap: Boolean;
    FAutoSizeGroupCaption: Boolean;
    FHeaderCustomColor: THeaderCustomColor;
    //FWideCaptions: TWideStrings;
    //FWideGroupCaptions: TWideStrings;
    //    FCursor: TCursor;
    procedure SetAlignment(const value: TAlignment);
    procedure SetCaptions(const value: TPlannerStringList);
    function GetDragDrop: Boolean;
    procedure SetDragDrop(const value: Boolean);
    procedure SetHeight(const value: Integer);
    procedure SetVisible(const value: Boolean);
    procedure SetColor(const value: TColor);
    procedure SetFont(const value: TFont);
    procedure SetGroupFont(const value: TFont);
    procedure FontChanged(Sender: TObject);
    procedure GroupFontChanged(Sender: TObject);
    procedure ItemsChanged(Sender: TObject);
    procedure SetImages(const value: TImageList);
    procedure SetImagePosition(const value: TImagePosition);
    procedure SetFlat(const value: Boolean);
    procedure SetVAlignment(const value: TVAlignment);
    procedure SetReadOnly(const value: Boolean);
    procedure SetItemHeight(const value: Integer);
    procedure SetTextHeight(const value: Integer);
    procedure SetAllowResize(const value: Boolean);
    procedure SetAllowPositionResize(const value: Boolean);
    procedure SetAutoSize(const value: Boolean);
    procedure SetItemColor(const value: TColor);
    procedure SetGroupCaptions(const value: TPlannerStringList);
    procedure SetGroupHeight(const value: Integer);
    procedure SetLineColor(const value: TColor);
    procedure UpdateHeights;
    procedure SetColorTo(const value: TColor);
    procedure SetActiveColor(const value: TColor);
    procedure SetActiveColorTo(const value: TColor);
    //    procedure SetCursor(const Value: TCursor);
    procedure SetRotateOnLeft(const value: Boolean);
    procedure SetRotateGroupOnLeft(const value: Boolean);
    procedure SetRotateOnTop(const value: Boolean);
    procedure SetCustomGroups(const value: TGroupCollection);
    procedure CustomGroupChange(Sender: TObject);
    procedure SetWordWrap(const value: Boolean);
    procedure SetAutoSizeGroupCaption(const value: Boolean);
    //procedure SetWideCaptions(const Value: TWideStrings);
    //procedure SetWideGroupCaptions(const Value: TWideStrings);
  protected
    function GetOwner: TPersistent; override;
  public
    constructor Create(AOwner: TCustomPlanner);
    destructor Destroy; override;
    procedure Assign(Source: TPersistent); override;
    procedure MergeHeader(FromSection, ToSection: Integer);
    procedure UnMergeHeader(FromSection, ToSection: Integer);
    property GroupSpan: TPlannerIntList read FGroupSpan write FGroupSpan;
    function GroupSplit(Pos: Integer): Integer;
    function GetGroupCaption(Pos: Integer): string;
    property HeaderCustomColor: THeaderCustomColor read FHeaderCustomColor write FHeaderCustomColor;
    //property WideCaptions: TWideStrings read FWideCaptions write SetWideCaptions;
    //property WideGroupCaptions: TWideStrings read FWideGroupCaptions write SetWideGroupCaptions;
  published
    property ActiveColor: TColor read FActiveColor write SetActiveColor default clNone;
    property ActiveColorTo: TColor read FActiveColorTo write SetActiveColorTo default clNone;
    property Alignment: TAlignment read FAlignment write SetAlignment default taLeftJustify;
    property AllowResize: Boolean read FAllowResize write SetAllowResize default False;
    property AllowPositionResize: Boolean read FAllowPositionResize write SetAllowPositionResize default False;
    property AutoSize: Boolean read FAutoSize write SetAutoSize default False;
    property AutoSizeGroupCaption: Boolean read FAutoSizeGroupCaption write SetAutoSizeGroupCaption default False;
    property Captions: TPlannerStringList read FCaptions write SetCaptions;
    property Color: TColor read FColor write SetColor default clBtnFace;
    property ColorTo: TColor read FColorTo write SetColorTo default clWhite;
    property CustomGroups: TGroupCollection read FCustomGroups write SetCustomGroups;
    //    property Cursor: TCursor read FCursor write SetCursor default crDefault;
    property DragDrop: Boolean read GetDragDrop write SetDragDrop default False;
    property Height: Integer read FHeight write SetHeight default 32;
    property Flat: Boolean read FFlat write SetFlat default False;
    property Font: TFont read FFont write SetFont;
    property GroupHeight: Integer read FGroupHeight write SetGroupHeight;
    property GroupFont: TFont read FGroupFont write SetGroupFont;
    property GroupCaptions: TPlannerStringList read FGroupCaptions write SetGroupCaptions;
    property Images: TImageList read FImages write SetImages;
    property ImagePosition: TImagePosition read FImagePosition write SetImagePosition default ipLeft;
    property ItemColor: TColor read FItemColor write SetItemColor default clGray;
    property ItemHeight: Integer read FItemHeight write SetItemHeight default 32;
    property LineColor: TColor read FLineColor write SetLineColor default clGray;
    property PopupMenu: TPopupMenu read FPopupMenu write FPopupMenu;
    property ReadOnly: Boolean read FReadOnly write SetReadOnly default True;
    property ResizeAll: Boolean read FResizeAll write FResizeAll default True;
    property RotateOnLeft: Boolean read FRotateOnLeft write SetRotateOnLeft default False;
    property RotateGroupOnLeft: Boolean read FRotateGroupOnLeft write SetRotateGroupOnLeft default False;
    property RotateOnTop: Boolean read FRotateOnTop write SetRotateOnTop default False;
    property ShowHint: Boolean read FShowHint write FShowHint default False;
    property TextHeight: Integer read FTextHeight write SetTextHeight default 32;
    property VAlignment: TVAlignment read FVAlignment write SetVAlignment default vtaCenter;
    property Visible: Boolean read FVisible write SetVisible default True;
    property WordWrap: Boolean read FWordWrap write SetWordWrap default False;
  end;

  TCaptionType = (ctNone, ctText, ctTime, ctTimeText);

  TImageChangeEvent = procedure(Sender: TObject) of object;

  TPlannerIntList = class(TList)
  private
    FOnChange: TImageChangeEvent;
    FPlannerItem: TPlannerItem;
    procedure SetInteger(Index: Integer; value: Integer);
    function GetInteger(Index: Integer): Integer;
  public
    constructor Create(value: TPlannerItem);
    property Items[Index: Integer]: Integer read GetInteger write SetInteger;
    default;
    function Add(value: Integer): integer;
    procedure Delete(Index: Integer);
    procedure Clear; override;
    property OnChange: TImageChangeEvent read FOnChange write FOnChange;
  end;

  TPlannerItemEdit = (peMemo, peEdit, peMaskEdit, peRichText, peCustom
    , peForm
    , peUniMemo
  );

  TPlannerLinkType = (ltLinkFull, ltLinkBeginEnd, ltLinkEndBegin, ltLinkEndEnd, ltLinkBeginBegin, ltLinkNone);

  TPlannerShape = (psRect, psRounded, psHexagon, psTool
{$IFDEF TMSSKINS}
    , psSkin
{$ENDIF}
  );

  TFindTextParameter = (fnMatchCase, fnMatchFull, fnMatchRegular, fnMatchStart,
    fnAutoGoto, fnIgnoreHTMLTags, fnBackward, fnCaptionText, fnText);

  TFindTextParams = set of TFindTextParameter;

  TAlarmNotifyType = (anCaption, anNotes, anMessage);

  TCompletionDisplay = (cdNone, cdVertical, cdHorizontal);

  TPlannerBarItem = class(TPersistent)
  private
    FBegin: Integer;
    FEnd: Integer;
    FColor: TColor;
    FStyle: TBrushStyle;
    FOnDestroy: TNotifyEvent;
    FOwner: TPlannerBarItemList;
    function GetEndTime: TDateTime;
    function GetStartTime: TDateTime;
    procedure SetEndTime(const pEndTime: TDateTime);
    procedure SetStartTime(const pStartTime: TDateTime);
    function CheckOwners: Boolean;
  public
    constructor Create(pOwner: TPlannerBarItemList);
    destructor Destroy; override;
  published
    property BarColor: TColor read FColor write FColor;
    property BarBegin: Integer read FBegin write FBegin;
    property BarEnd: Integer read FEnd write FEnd;
    property BarStyle: TBrushStyle read FStyle write FStyle;
    property Owner: TPlannerBarItemList read FOwner;
    property EndTime: TDateTime read GetEndTime write SetEndTime;
    property StartTime: TDateTime read GetStartTime write SetStartTime;
    property OnDestroy: TNotifyEvent read FOnDestroy write FOnDestroy;
  end;

  TPlannerBarItemList = class(TList)
  private
    FOwner: TPlannerItem;
    function GetItem(Index: Integer): TPlannerBarItem;
  public
    function AddItem(pStart, pEnd: TDateTime; pColor: TColor;
      pStyle: TBrushStyle): Integer;
    constructor Create(AOwner: TPlannerItem);
    destructor Destroy; override;
    property Items[Index: Integer]: TPlannerBarItem read GetItem; default;
    property Owner: TPlannerItem read FOwner write FOwner;
  end;

  TPlannerAlarmHandler = class(TComponent)
  public
    function HandleAlarm(Address, Message: string; Tag, ID: Integer;
      Item: TPlannerItem): Boolean; virtual;
  end;

  {$IFDEF DELPHIXE2_LVL}
  [ComponentPlatformsAttribute(pidWin32 or pidWin64)]
  {$ENDIF}
  TAlarmMessage = class(TPlannerAlarmHandler)
  public
    function HandleAlarm(Address, Message: string; Tag, ID: Integer;
      Item: TPlannerItem): Boolean; override;
  end;

  TAlarmTime = (atBefore, atAfter, atBoth);

  TPlannerAlarm = class(TPersistent)
  private
    FActive: Boolean;
    FTag: Integer;
    FID: Integer;
    FAddress: string;
    FMessage: string;
    FNotifyType: TAlarmNotifyType;
    FTimeBefore: TDateTime;
    FTimeAfter: TDateTime;
    FHandler: TPlannerAlarmHandler;
    FTime: TAlarmTime;
  protected
  public
    procedure Assign(Source: TPersistent); override;
  published
    property Active: Boolean read FActive write FActive default False;
    property Address: string read FAddress write FAddress;
    property Handler: TPlannerAlarmHandler read FHandler write FHandler;
    property ID: Integer read FID write FID default 0;
    property Message: string read FMessage write FMessage;
    property NotifyType: TAlarmNotifyType read FNotifyType write FNotifyType default anCaption;
    property Tag: Integer read FTag write FTag default 0;
    property Time: TAlarmTime read FTime write FTime default atBefore;
    property TimeBefore: TDateTime read FTimeBefore write FTimeBefore;
    property TimeAfter: TDateTime read FTimeAfter write FTimeAfter;
  end;

  TItemRelationShip = (irParent, irChild);

  TEditorUse = (euAlways, euDblClick);

  TEditDoneEvent = procedure(Sender: TObject; ModalResult: TModalResult) of object;
  TEditShowEvent = procedure(Sender: TObject; APlannerItem: TPlannerItem) of object;

  TCustomItemEditor = class(TComponent)
  private
    //FEditItem: TPlannerItem;
    FPlanner: TCustomPlanner;
    FCaption: string;
    FEditorUse: TEditorUse;
    FOnEditDone: TEditDoneEvent;
    FModalResult: TModalResult;
    FOnBeforeEditShow: TEditShowEvent;
  protected
  public
    procedure Edit(APlanner: TCustomPlanner; APlannerItem: TPlannerItem);
    function QueryEdit(APlannerItem: TPlannerItem): Boolean; virtual;
    procedure CreateEditor(AOwner: TComponent); virtual;
    procedure DestroyEditor; virtual;
    function Execute: Integer; virtual;
    procedure PlannerItemToEdit(APlannerItem: TPlannerItem); virtual;
    procedure EditToPlannerItem(APlannerItem: TPlannerItem); virtual;
    property Planner: TCustomPlanner read FPlanner;
    property ModalResult: TModalResult read FModalResult write FModalResult;
  published
    property Caption: string read FCaption write FCaption;
    property EditorUse: TEditorUse read FEditorUse write FEditorUse;
    property OnBeforeEditShow: TEditShowEvent read FOnBeforeEditShow write FOnBeforeEditShow;
    property OnEditDone: TEditDoneEvent read FOnEditDone write FOnEditDone;
  end;

  TCustomItemDrawTool = class(TComponent)
  private
  public
    procedure DrawItem(PlannerItem: TPlannerItem; Canvas: TCanvas; Rect: TRect;
      Selected, Print: Boolean); virtual;
  end;

  TSelectButton = (sbLeft, sbRight, sbBoth);

  TPlannerItemSelection = class(TPersistent)
  private
    FAutoUnSelect: Boolean;
    FAutoSelectOnAutoInsert: Boolean;
    FAutoEditOnAutoInsert: Boolean;
    FButton: TSelectButton;
  public
    constructor Create;
    procedure Assign(Source: TPersistent); override;
  published
    property AutoEditOnAutoInsert: Boolean read FAutoEditOnAutoInsert write FAutoEditOnAutoInsert default False;
    property AutoSelectOnAutoInsert: Boolean read FAutoSelectOnAutoInsert write FAutoSelectOnAutoInsert default True;
    property AutoUnSelect: Boolean read FAutoUnSelect write FAutoUnSelect default True;
    property Button: TSelectButton read FButton write FButton default sbLeft;
  end;

  TPlannerSelection = class(TCollectionItem)
  private
    FSelBegin: Integer;
    FSelEnd: Integer;
    FSelPos: Integer;
  public
    procedure Update;
  published
    property SelBegin: Integer read FSelBegin write FSelBegin;
    property SelEnd: Integer read FSelEnd write FSelEnd;
    property SelPos: Integer read FSelPos write FSelPos;
  end;

  TPlannerSelections = class(TCollection)
  private
    FOwner: TCustomPlanner;
    function GetItem(Index: Integer): TPlannerSelection;
    procedure SetItem(Index: Integer; const value: TPlannerSelection);
  public
    constructor Create(AOwner: TCustomPlanner);
    procedure Clear;
    function Add: TPlannerSelection;
    function Insert(Index: Integer): TPlannerSelection;
    property Items[Index: Integer]: TPlannerSelection read GetItem write SetItem; default;
  end;

  TPlannerTimePointer = class(TCollectionItem)
  private
    FDateTime: TDateTime;
    FWidth: integer;
    FColor: TColor;
    FStyle: TPenStyle;
  public
    constructor Create(Collection: TCollection); override;
  published
    property Color: TColor read FColor write FColor;
    property DateTime: TDateTime read FDateTime write FDateTime;
    property Style: TPenStyle read FStyle write FStyle;
    property Width: integer read FWidth write FWidth;
  end;

  TPlannerTimePointers = class(TCollection)
  private
    FOwner: TCustomPlanner;
    function GetItem(Index: Integer): TPlannerTimePointer;
    procedure SetItem(Index: Integer; const Value: TPlannerTimePointer);
  public
    constructor Create(AOwner: TCustomPlanner);
    function Add: TPlannerTimePointer;
    function Insert(Index: Integer): TPlannerTimePointer;
    property Items[Index: Integer]: TPlannerTimePointer read GetItem write SetItem; default;

  end;

  TItemImagePosition = (ipHorizontal, ipVertical);

  TLinkArrow = (laNone, laFromTo, laToFrom, laBoth);

  { TPlannerItem }

  TPlannerItem = class(TCollectionItem)
  private
    FAlarm: TPlannerAlarm;
    FBarItems: TPlannerBarItemList;
    FTag: Integer;
    FID: Integer;
    FObject: TObject;
    FAlignment: TAlignment;
    FAttachement: string;
    FCaptionType: TCaptionType;
    FCaptionText: string;
    FEditMask: string;
    FText: TStringList;
    FInplaceEdit: TPlannerItemEdit;
    FItemBegin: Integer;
    FItemEnd: Integer;
    FItemBeginPrecis: Integer;
    FItemEndPrecis: Integer;
    FItemFullBegin: Integer;
    FImageID: Integer;
    FInHeader: Boolean;
    FColor: TColor;
    FColorTo: TColor;
    FBorderColor: TColor;
    FFixedPos: Boolean;
    FFixedSize: Boolean;
    FFixedPosition: Boolean;
    FReadOnly: Boolean;
    FPlanner: TCustomPlanner;
    FItemPos: Integer;
    FConflicts: Integer;
    FConflictPos: Integer;
    FVisible: Boolean;
    FFocus: Boolean;
    FName: string;
    FOnEditModal: TNotifyEvent;
    FLayer: Integer;
    FTrackColor: TColor;
    FTrackSelectColor: TColor;
    FTrackLinkColor: TColor;
    FTrackVisible: Boolean;
    FHint: string;
    FImageIndexList: TPlannerIntList;
    FImagePosition: TItemImagePosition;
    FItemStartTime: TDateTime;
    FItemEndTime: TDateTime;
    FItemRealStartTime: TDateTime;
    FItemRealEndTime: TDateTime;
    FAllowOverlap: Boolean;
    FBackGround: Boolean;
    FFont: TFont;
    FLinkedItem: TPlannerItem;
    FLinkType: TPlannerLinkType;
    FIsCurrent: Boolean;
    FBrushStyle: TBrushStyle;
    FCaptionAlign: TAlignment;
    FCaptionBkg: TColor;
    FCaptionBkgTo: TColor;
    FCaptionFont: TFont;
    FCaptionHeight: Integer;
    FSelected: Boolean;
    FSelectColor: TColor;
    FSelectColorTo: TColor;
    FShowSelection: Boolean;
    FShowDeleteButton: Boolean;
    FOwnsItemObject: Boolean;
    FRepainted: Boolean;
    FShape: TPlannerShape;
    FBeginExt: Integer;
    FEndExt: Integer;
    FPopupMenu: TPopupMenu;
    FDBTag: Integer;
    FDBKey: string;
    FLinkedDBKey: string;
    FSynched: Boolean;
    FWordWrap: Boolean;
    FURL: string;
    FEndOffset: Integer;
    FBeginOffset: Integer;
    FChanged: Boolean;
    FDoExport: Boolean;
    FRealTime: Boolean;
    FFlashOn: Boolean;
    FFlashing: Boolean;
    FUniformBkg: Boolean;
    FParentIndex: Integer;
    FCursor: TCursor;
    FClipped: Boolean;
    FRelationShip: TItemRelationShip;
    FNonDBItem: Boolean;
    FShadow: Boolean;
    FTransparent: Boolean;
    FSelectFontColor: TColor;
    FEditor: TCustomItemEditor;
    FPopupEdit: Boolean;
    FDrawTool: TCustomItemDrawTool;
    FCompletion: Integer;
    FCompletionDisplay: TCompletionDisplay;
    FFixedTime: Boolean;
    FRecurrency: string;
    FRecurrent: Boolean;
    FRecurrentStart: TDateTime;
    FRecurrentEnd: TDateTime;
    FRecurrentOrigStart: TDateTime;
    FRecurrentOrigEnd: TDateTime;
    FLinkUpdating: Boolean;
    FShowLinks: Boolean;
    FLinkSelect: Boolean;
    FDesignChange: TNotifyEvent;
    FPreview: Boolean;
    FHTMLTemplate: TStrings;
    FCanSelect: boolean;
    FCaptionBkgDirection: TPlannerGradientDirection;
    FColorDirection: TPlannerGradientDirection;
    FTrackBrushStyle: TBrushStyle;
    FLinkColor: TColor;
    FLinkArrow: TLinkArrow;
    FHintIndicator: boolean;
    FHintIndicatorColor: TColor;
    FSelectCaptionBkg: TColor;
    FSelectCaptionBkgTo: TColor;
    FWideCaption: widestring;
    FWideText: widestring;
    FUnicode: Boolean;
    FCaptionDivider: boolean;
    FDrawTag: string;
    FVMargin: integer;
    procedure SetColor(const value: TColor);
    procedure SetColorTo(const value: TColor);
    procedure SetBorderColor(const value: TColor);
    procedure SetTrackColor(const value: TColor);
    procedure SetTrackSelectColor(const value: TColor);
    procedure SetLayer(const value: Integer);
    procedure SetItemEnd(const value: Integer);
    procedure SetItemBegin(const value: Integer);
    procedure SetText(const value: TStringList);
    procedure SetAlignment(const value: TAlignment);
    procedure SetAllowOverlap(const value: Boolean);
    procedure SetCaptionType(const value: TCaptionType);
    procedure SetCaptionText(const value: string);
    procedure SetImageID(const value: Integer);
    procedure SetImagePosition(const value: TItemImagePosition);
    procedure SetIsCurrent(const value: Boolean);
    procedure SetItemPos(const value: Integer);
    procedure SetVisible(const value: Boolean);
    function GetVisible: Boolean;
    procedure SetFocus(const value: Boolean);
    procedure SetFont(const value: TFont);
    procedure SetBackground(const value: Boolean);
    procedure ReOrganize;
    procedure FontChange(Sender: TObject);
    procedure ImageChange(Sender: TObject);
    procedure TextChange(Sender: TObject);
    procedure SetItemRealEndTime(const value: TDateTime);
    procedure SetItemRealStartTime(const value: TDateTime);
    procedure SetBrusStyle(const value: TBrushStyle);
    procedure SetCaptionAlign(const value: TAlignment);
    procedure SetCaptionBkg(const value: TColor);
    procedure SetCaptionBkgTo(const value: TColor);
    procedure SetCaptionFont(const value: TFont);
    procedure SetSelectColor(const value: TColor);
    procedure SetSelectColorTo(const value: TColor);
    procedure SetSelected(const value: Boolean);
    procedure SetShadow(const value: Boolean);
    procedure SetObject(const value: TObject);
    procedure SetInHeader(const value: Boolean);
    procedure SetItemBeginPrecis(const value: Integer);
    procedure SetItemEndPrecis(const value: Integer);
    procedure SetTrackVisible(const value: Boolean);
    procedure SetShape(const value: TPlannerShape);
    procedure SetPopupMenu(const value: TPopupMenu);
    procedure SetShowSelection(const value: Boolean);
    procedure SetShowDeleteButton(const value: Boolean);
    procedure SetTimeTag;
    procedure GetTimeTag;
    function GetItemText: string;
    procedure SetWordWrap(const value: Boolean);
    procedure SetAttachement(const value: string);
    function GetItemRealEndTime: TDateTime;
    function GetItemRealStartTime: TDateTime;
    procedure SetURL(const value: string);
    procedure SetAlarm(const value: TPlannerAlarm);
    function GetStrippedItemText: string;
    procedure SetFlashing(const value: Boolean);
    function GetParentItem: TPlannerItem;
    function GetCanEdit: Boolean;
    procedure SetSelectFontColor(const value: TColor);
    procedure SetDrawTool(const value: TCustomItemDrawTool);
    procedure SetLinkSelect(const value: Boolean);
    procedure SetCompletion(const value: Integer);
    procedure SetCompletionDisplay(const value: TCompletionDisplay);
    procedure CompletionAdapt(var R: TRect);
    procedure ImageListAdapt(var R: TRect);
    function GetNotes: string;
    procedure SetCaptionBkgDirection(const Value: TPlannerGradientDirection);
    procedure SetColorDirection(const Value: TPlannerGradientDirection);
    procedure SetTrackBrushStyle(const Value: TBrushStyle);
    procedure SetLinkColor(const Value: TColor);
    procedure SetHintIndicator(const Value: boolean);
    procedure SetHintIndicatorColor(const Value: TColor);
    procedure SetSelectCaptionBkg(const Value: TColor);
    procedure SetSelectCaptionBkgTo(const Value: TColor);
    procedure SetWideText(const value: widestring);
    procedure SetWideCaption(const value: widestring);
    procedure SetUnicode(const value: Boolean);
    procedure SetCaptionDivider(const Value: boolean);
  protected
{$IFNDEF VER90}
    function GetDisplayName: string; override;
{$ENDIF}
    procedure Repaint; virtual;
    procedure SetItemEndTime(const value: TDateTime); virtual;
    procedure SetItemStartTime(const value: TDateTime); virtual;
    function GetItemEndTime: TDateTime; virtual;
    function GetItemStartTime: TDateTime; virtual;
    function GetItemEndTimeStr: string; virtual;
    function GetItemStartTimeStr: string; virtual;
    function GetItemSpanTimeStr: string; virtual;
    function IsSelectable: boolean; virtual;
    procedure UpdateWnd;
    procedure CalcConflictRect(var Rect: TRect; Width, Height: Integer; Position: Boolean);
    property IsCurrent: Boolean read FIsCurrent write SetIsCurrent;
    function GetCaptionHeight: Integer;
    function GetGridRect: TRect;
    function GetItemRect: TRect;
    function GetItemPaintRect: TRect;
    function GetVisibleSpan: Integer;
    {NEW INTERFACES FOR DESCENDENT CLASSES}
    procedure SetClipped(value: Boolean);
    procedure SetConflicts(value: Integer);
    procedure SetConflictPos(value: Integer);
    procedure SetHTMLTemplate(const value: TStrings);
    property BeginExt: Integer read FBeginExt write FBeginExt;
    property EndExt: Integer read FEndExt write FEndExt;
    property CaptionHeight: Integer read FCaptionHeight write FCaptionHeight;
    property IsPopupEdit: Boolean read FPopupEdit;
    {END OF NEW INTERFACES FOR DESCENDENT CLASSES}
    property LinkUpdating: Boolean read FLinkUpdating write FLinkUpdating;
    procedure SetControlVal(ID, AValue: string);
    function GetControlVal(ID: string): string;
    property LinkSelect: Boolean read FLinkSelect write SetLinkSelect;
    property OnDesignChange: TNotifyEvent read FDesignChange write FDesignChange;
  public
    constructor Create(Collection: TCollection); override;
    destructor Destroy; override;
    procedure Assign(Source: TPersistent); override;
    procedure AssignEx(Source: TPersistent);
    function Planner: TCustomPlanner; virtual;
    procedure Changed; virtual;
    procedure ScrollInView;
    procedure EnsureFullVisibility;
    procedure Edit;
    procedure PopupEdit;
    procedure MoveItem(NewBegin, NewEnd, NewPos: Integer; var NewOffset: Integer);
    procedure SizeItem(NewBegin, NewEnd: Integer);
    procedure DefOrganize;
    procedure Update; virtual;
    procedure ChangeCrossing;
    function SetValue(ID, value: string): Boolean;
    function GetValue(ID: string; var value: string): Boolean;
    function GetCaptionTimeString: string; virtual;
    function GetCaptionString: string;
    function GetWideCaptionString: widestring;
    property ItemObject: TObject read FObject write SetObject;
    property ID: Integer read FID write FID;
    property BeginOffset: Integer read FBeginOffset write FBeginOffset;
    property EndOffset: Integer read FEndOffset write FEndOffset;
    property Clipped: Boolean read FClipped;
    property Conflicts: Integer read FConflicts;
    property ConflictPos: Integer read FConflictPos;
    property ControlValue[index: string]: string read GetControlVal write SetControlVal;
    property Preview: Boolean read FPreview write FPreview;
    property Focus: Boolean read FFocus write SetFocus;
    property ImageIndexList: TPlannerIntList read FImageIndexList write FImageIndexList;
    property ItemBeginPrecis: Integer read FItemBeginPrecis write SetItemBeginPrecis;
    property ItemEndPrecis: Integer read FItemEndPrecis write SetItemEndPrecis;
    property ItemStartTime: TDateTime read GetItemStartTime write SetItemStartTime;
    property ItemEndTime: TDateTime read GetItemEndTime write SetItemEndTime;
    property ItemRealStartTime: TDateTime read GetItemRealStartTime write SetItemRealStartTime;
    property ItemRealEndTime: TDateTime read GetItemRealEndTime write SetItemRealEndTime;
    property ItemStartTimeStr: string read GetItemStartTimeStr;
    property ItemEndTimeStr: string read GetItemEndTimeStr;
    property ItemSpanTimeStr: string read GetItemSpanTimeStr;
    property ItemText: string read GetItemText;
    property StrippedItemText: string read GetStrippedItemText;
    property LinkedItem: TPlannerItem read FLinkedItem write FLinkedItem;
    property LinkType: TPlannerLinkType read FLinkType write FLinkType default ltLinkNone;
    property LinkColor: TColor read FLinkColor write SetLinkColor default clNavy;
    property LinkArrow: TLinkArrow read FLinkArrow write FLinkArrow default laNone;
    property Owner: TCustomPlanner read FPlanner;
    property Repainted: Boolean read FRepainted write FRepainted;
    property DBKey: string read FDBKey write FDBKey;
    property LinkedDBKey: string read FLinkedDBKey write FLinkedDBKey;
    property Synched: Boolean read FSynched write FSynched;
    property DoExport: Boolean read FDoExport write FDoExport;
    property RealTime: Boolean read FRealTime write FRealTime;
    property Flashing: Boolean read FFlashing write SetFlashing;
    property FlashOn: Boolean read FFlashOn write FFlashOn;
    property ParentItem: TPlannerItem read GetParentItem;
    property ParentIndex: Integer read FParentIndex write FParentIndex;
    property RelationShip: TItemRelationShip read FRelationShip write FRelationShip;
    property BarItems: TPlannerBarItemList read FBarItems write FBarItems;
    property NotEditable: Boolean read GetCanEdit;
    property NonDBItem: Boolean read FNonDBItem write FNonDBItem;
    property Transparent: Boolean read FTransparent write FTransparent;
    property ItemRect: TRect read GetItemRect;
    property NotesText: string read GetNotes;
    property Recurrency: string read FRecurrency write FRecurrency;
    property Recurrent: Boolean read FRecurrent write FRecurrent;
    property RecurrentEnd: TDateTime read FRecurrentEnd write FRecurrentEnd;
    property RecurrentStart: TDateTime read FRecurrentStart write FRecurrentStart;
    property RecurrentOrigEnd: TDateTime read FRecurrentOrigEnd write FRecurrentOrigEnd;
    property RecurrentOrigStart: TDateTime read FRecurrentOrigStart write FRecurrentOrigStart;
    property VMargin: integer read FVMargin write FVMargin;
  published
    property Alarm: TPlannerAlarm read FAlarm write SetAlarm;
    property Alignment: TAlignment read FAlignment write SetAlignment default taLeftJustify;
    property AllowOverlap: Boolean read FAllowOverlap write SetAllowOverlap default True;
    property Attachement: string read FAttachement write SetAttachement;
    property Background: Boolean read FBackGround write SetBackground default False;
    property BorderColor: TColor read FBorderColor write SetBorderColor default clSilver;
    property BrushStyle: TBrushStyle read FBrushStyle write SetBrusStyle default bsSolid;
    property CanSelect: Boolean read FCanSelect write FCanSelect default true;
    property CaptionAlign: TAlignment read FCaptionAlign write SetCaptionAlign default taLeftJustify;
    property CaptionBkg: TColor read FCaptionBkg write SetCaptionBkg default clWhite;
    property CaptionBkgTo: TColor read FCaptionBkgTo write SetCaptionBkgTo default clNone;
    property CaptionBkgDirection: TPlannerGradientDirection read FCaptionBkgDirection write SetCaptionBkgDirection default gdHorizontal;
    property CaptionDivider: boolean read FCaptionDivider write SetCaptionDivider default true;
    property CaptionFont: TFont read FCaptionFont write SetCaptionFont;
    property CaptionType: TCaptionType read FCaptionType write SetCaptionType default ctNone;
    property CaptionText: string read FCaptionText write SetCaptionText;
    property Color: TColor read FColor write SetColor default clWhite;
    property ColorTo: TColor read FColorTo write SetColorTo default clBtnFace;
    property ColorDirection: TPlannerGradientDirection read FColorDirection write SetColorDirection default gdVertical;
    property Completion: Integer read FCompletion write SetCompletion default 0;
    property CompletionDisplay: TCompletionDisplay read FCompletionDisplay write SetCompletionDisplay default cdNone;
    property Cursor: TCursor read FCursor write FCursor;
    property DBTag: Integer read FDBTag write FDBTag default 0;
    property DrawTool: TCustomItemDrawTool read FDrawTool write SetDrawTool;
    property DrawTag: string read FDrawTag write FDrawTag;
    property EditMask: string read FEditMask write FEditMask;
    property Editor: TCustomItemEditor read FEditor write FEditor;
    property FixedPos: Boolean read FFixedPos write FFixedPos default False;
    property FixedPosition: Boolean read FFixedPosition write FFixedPosition default False;
    property FixedSize: Boolean read FFixedSize write FFixedSize default False;
    property FixedTime: Boolean read FFixedTime write FFixedTime default False;
    property Font: TFont read FFont write SetFont;
    property Hint: string read FHint write FHint;
    property HintIndicator: boolean read FHintIndicator write SetHintIndicator default False;
    property HintIndicatorColor: TColor read FHintIndicatorColor write SetHintIndicatorColor default clRed;
    property HTMLTemplate: TStrings read FHTMLTemplate write SetHTMLTemplate;
    property ImageID: Integer read FImageID write SetImageID default -1;
    property ImagePosition: TItemImagePosition read FImagePosition write SetImagePosition default ipHorizontal;
    property InHeader: Boolean read FInHeader write SetInHeader default False;
    property InplaceEdit: TPlannerItemEdit read FInplaceEdit write FInplaceEdit default peMemo;
    property ItemBegin: Integer read FItemBegin write SetItemBegin;
    property ItemEnd: Integer read FItemEnd write SetItemEnd;
    property ItemPos: Integer read FItemPos write SetItemPos;
    property Layer: Integer read FLayer write SetLayer default 0;
    property Name: string read FName write FName;
    property OnEditModal: TNotifyEvent read FOnEditModal write FOnEditModal;
    property OwnsItemObject: Boolean read FOwnsItemObject write FOwnsItemObject default False;
    property PopupMenu: TPopupMenu read FPopupMenu write SetPopupMenu;
    property ReadOnly: Boolean read FReadOnly write FReadOnly default False;
    property Shape: TPlannerShape read FShape write SetShape default psRect;
    property ShowSelection: Boolean read FShowSelection write SetShowSelection default True;
    property ShowDeleteButton: Boolean read FShowDeleteButton write SetShowDeleteButton default False;
    property SelectColor: TColor read FSelectColor write SetSelectColor default clInfoBk;
    property SelectColorTo: TColor read FSelectColorTo write SetSelectColorTo default clNone;
    property SelectCaptionBkg: TColor read FSelectCaptionBkg write SetSelectCaptionBkg default clNone;
    property SelectCaptionBkgTo: TColor read FSelectCaptionBkgTo write SetSelectCaptionBkgTo default clNone;
    property SelectFontColor: TColor read FSelectFontColor write SetSelectFontColor default clRed;
    property Selected: Boolean read FSelected write SetSelected default False;
    property Shadow: Boolean read FShadow write SetShadow;
    property ShowLinks: Boolean read FShowLinks write FShowLinks default False;
    property Tag: Integer read FTag write FTag default 0;
    property Text: TStringList read FText write SetText;
    property TrackColor: TColor read FTrackColor write SetTrackColor default clBlue;
    property TrackBrushStyle: TBrushStyle read FTrackBrushStyle write SetTrackBrushStyle default bsSolid;
    property TrackLinkColor: TColor read FTrackLinkColor write FTrackLinkColor default clRed;
    property TrackSelectColor: TColor read FTrackSelectColor write SetTrackSelectColor default clBlue;
    property TrackVisible: Boolean read FTrackVisible write SetTrackVisible default True;
    property UniformBkg: Boolean read FUniformBkg write FUniformBkg default True;
    property URL: string read FURL write SetURL;
    property Visible: Boolean read GetVisible write SetVisible default True;
    property WideCaption: widestring read FWideCaption write SetWideCaption;
    property WideText: widestring read FWideText write SetWideText;
    property Unicode: Boolean read FUnicode write SetUnicode default False;
    property WordWrap: Boolean read FWordWrap write SetWordWrap default True;
  end;

  TPlannerItemArray = array of TPlannerItem;

  { TPlannerItems }

  TPlannerItems = class(TCollection)
  private
    FOwner: TCustomPlanner;
    FSelected: TPlannerItem;
    FDBItem: TPlannerItem;
    FUpdateCount: Integer;
    FFindIndex: Integer;
    FChanging: Boolean;
    function GetItem(Index: Integer): TPlannerItem;
    procedure SetItem(Index: Integer; value: TPlannerItem);
    function NumConflicts(var ItemBegin, ItemEnd: Integer; ItemPos: Integer): Integer;
    function GetSelCount: Integer;
  protected
{$IFNDEF VER90}
    function GetOwner: TPersistent; override;
{$ENDIF}
    procedure ClearSelectedRepaints(ItemBegin, ItemPos: Integer);
    function NumItem(ItemBegin, ItemEnd, ItemPos: Integer): TPoint;
    function NumItemPos(ItemBegin, ItemEnd, ItemPos: Integer): TPoint;
    function NumItemPosStart(ItemBegin, ItemPos: Integer): Integer;
    function FindItem(ItemBegin, ItemPos: Integer): TPlannerItem;
    function FindItemIdx(ItemBegin: Integer): TPlannerItem;
    function FindItemPos(ItemBegin, ItemPos, ItemSubPos: Integer): TPlannerItem;
    function FindBkgPos(ItemBegin, ItemPos, ItemSubPos: Integer): TPlannerItem;
    function FindItemPosIdx(ItemBegin, ItemPos, ItemSubPos: Integer): TPlannerItem;
    function FindItemIndex(ItemBegin, ItemPos, ItemSubIdx: Integer): TPlannerItem;
    function FindBackground(ItemBegin, ItemPos: Integer): TPlannerItem;
    function QueryItem(Item: TPlannerItem; ItemBegin, ItemPos: Integer): TPlannerItem;
    function FocusItem(ItemBegin, ItemPos, ItemSubPos: Integer; Control: Boolean): TPlannerItem;
    function FocusBkg(ItemBegin, ItemPos, ItemSubPos: Integer; Control: Boolean): TPlannerItem;
    procedure SetCurrent(ItemCurrent: Integer);
    function PasteItem(Position: Boolean; Size: Boolean): TPlannerItem;
    procedure ClearRepaints;
    procedure SetTimeTags;
    procedure GetTimeTags;
    function MatchItem(Item: TPlannerItem; s: string; Param: TFindTextParams): Boolean;
    function MaxItemsInPos(Position: Integer): Integer;
    procedure MoveLinks(APlannerItem: TPlannerItem);
    procedure SizeLinks(APlannerItem: TPlannerItem);
    procedure UpdateLinks(APlannerItem: TPlannerItem);
    procedure ClearLinks;
    function HasItemInt(ItemBegin, ItemEnd, ItemPos: Integer): Boolean;
  public
    function GetItemClass: TCollectionItemClass; virtual;
    constructor Create(AOwner: TCustomPlanner);
    function CheckItems: Boolean;
    function CheckPosition(Position: Integer): Boolean;
    function CheckLayer(Layer: Integer): Boolean;
    function CheckItem(Item: TPlannerItem): Boolean;
    function HasItem(ItemBegin, ItemEnd, ItemPos: Integer): Boolean;
    function HasHeaderItem(ItemPos: Integer): Boolean;
    function FindFirst(ItemBegin, ItemEnd, ItemPos: Integer): TPlannerItem;
    function FindNext(ItemBegin, ItemEnd, ItemPos: Integer): TPlannerItem;
    function FindKey(DBKey: string): TPlannerItem;
    function HeaderFirst(ItemPos: Integer): TPlannerItem;
    function HeaderNext(ItemPos: Integer): TPlannerItem;
    function FindText(StartItem: TPlannerItem; s: string; Param: TFindTextParams): TPlannerItem;
    function Add: TPlannerItem;
    function Insert(Index: Integer): TPlannerItem;
    property Items[Index: Integer]: TPlannerItem read GetItem write SetItem; default;
    function SelectNext: TPlannerItem;
    function SelectPrev: TPlannerItem;
    procedure UnSelect;
    procedure UnSelectAll;
    procedure Select(Item: TPlannerItem);
    property Selected: TPlannerItem read FSelected write FSelected;
    property DBItem: TPlannerItem read FDBItem write FDBItem;
    function InVisibleLayer(Layer: Integer): Boolean;
    procedure ClearConflicts;
    procedure SetConflicts; virtual;
    procedure ItemChanged(Item: TPlannerItem);
    function ItemsAtPosition(Pos: Integer): Integer;
    function ItemsAtIndex(Idx: Integer): Integer;
    function ItemsAtCell(ItemBegin, ItemEnd, ItemPos: Integer): Integer;
    function FindBkgItem(ItemBegin,ItemEnd,ItemPos: integer): TPlannerItem;
    procedure ResolveLinks; virtual;
    procedure BeginUpdate; override;
    procedure EndUpdate; override;
    procedure ResetUpdate;
    procedure ClearPosition(Position: Integer);
    procedure ClearLayer(Layer: Integer);
    procedure ClearAll;
    procedure ClearDB;
    procedure CopyToClipboard;
    procedure CutToClipboard;
    procedure PasteFromClipboard;
    procedure PasteFromClipboardAtPos;
    function PasteFromClipboardAtXY: TPlannerItem;
    procedure OffsetItems(Offset: Integer);
    procedure MoveAll(DeltaPos, DeltaBegin: Integer);
    procedure MoveSelected(DeltaPos, DeltaBegin: Integer);
    procedure SizeAll(DeltaStart, DeltaEnd: Integer);
    procedure SizeSelected(DeltaStart, DeltaEnd: Integer);
    property Changing: Boolean read FChanging write FChanging;
  published
    property SelCount: Integer read GetSelCount;
    property UpdateCount: Integer read FUpdateCount;
  end;

  { TPositionProp }

  TPositionProp = class(TCollectionItem)
  private
    FActiveStart: Integer;
    FActiveEnd: Integer;
    FColorNonActive: TColor;
    FColorActive: TColor;
    FMinSelection: Integer;
    FMaxSelection: Integer;
    FBrushNoSelect: TBrushStyle;
    FColorNoSelect: TColor;
    FBackGround: TBitmap;
    FUse: Boolean;
    FShowGap: Boolean;
    procedure SetActiveEnd(const value: Integer);
    procedure SetActiveStart(const value: Integer);
    procedure SetColorActive(const value: TColor);
    procedure SetColorNonActive(const value: TColor);
    procedure SetMaxSelection(const value: Integer);
    procedure SetMinSelection(const value: Integer);
    procedure SetBrushNoSelect(const value: TBrushStyle);
    procedure SetColorNoSelect(const value: TColor);
    procedure SetBackground(const value: TBitmap);
    procedure SetUse(const value: Boolean);
    procedure BackgroundChanged(Sender: TObject);
    procedure SetShowGap(const value: Boolean);
  public
    constructor Create(Collection: TCollection); override;
    destructor Destroy; override;
    procedure Assign(Source: TPersistent); override;
  published
    property ActiveStart: Integer read FActiveStart write SetActiveStart;
    property ActiveEnd: Integer read FActiveEnd write SetActiveEnd;
    property Background: TBitmap read FBackGround write SetBackground;
    property ColorActive: TColor read FColorActive write SetColorActive;
    property ColorNonActive: TColor read FColorNonActive write SetColorNonActive;
    property MinSelection: Integer read FMinSelection write SetMinSelection;
    property MaxSelection: Integer read FMaxSelection write SetMaxSelection;
    property ColorNoSelect: TColor read FColorNoSelect write SetColorNoSelect;
    property BrushNoSelect: TBrushStyle read FBrushNoSelect write SetBrushNoSelect;
    property Use: Boolean read FUse write SetUse default True;
    property ShowGap: Boolean read FShowGap write SetShowGap default True;
  end;

  TPositionProps = class(TCollection)
  private
    FOwner: TCustomPlanner;
    function GetItem(Index: Integer): TPositionProp;
    procedure SetItem(Index: Integer; const value: TPositionProp);
  protected
{$IFNDEF VER90}
    function GetOwner: TPersistent; override;
{$ENDIF}
  public
    constructor Create(AOwner: TCustomPlanner);
    function Add: TPositionProp;
    function Insert(Index: Integer): TPositionProp;
    property Items[Index: Integer]: TPositionProp read GetItem write SetItem; default;
  end;

  TPlannerScrollStyle = (ssNormal, ssFlat, ssEncarta);

  TPlannerScrollBar = class(TPersistent)
  private
    FOwner: TCustomPlanner;
    FFlat: Boolean;
    FWidth: Integer;
    FColor: TColor;
    FStyle: TPlannerScrollStyle;
    procedure SetColor(const value: TColor);
    procedure SetFlat(const value: Boolean);
    procedure SetStyle(const value: TPlannerScrollStyle);
    procedure SetWidth(const value: Integer);
  public
    constructor Create(AOwner: TCustomPlanner);
    procedure UpdateProps;
  published
    property Color: TColor read FColor write SetColor default clNone;
    property Flat: Boolean read FFlat write SetFlat default False;
    property Style: TPlannerScrollStyle read FStyle write SetStyle default ssNormal;
    property Width: Integer read FWidth write SetWidth default 16;
  end;

  TBackgroundDisplay = (bdTile, bdFixed);

  TBackground = class(TPersistent)
  private
    FPlanner: TCustomPlanner;
    FTop: Integer;
    FLeft: Integer;
    FDisplay: TBackgroundDisplay;
    procedure SetBitmap(value: TBitmap);
    procedure SetTop(value: Integer);
    procedure SetLeft(value: Integer);
    procedure SetDisplay(value: TBackgroundDisplay);
    procedure BackgroundChanged(Sender: TObject);
  private
    FBitmap: TBitmap;
  public
    constructor Create(APlanner: TCustomPlanner);
    destructor Destroy; override;
    property Display: TBackgroundDisplay read FDisplay write SetDisplay;
    property Top: Integer read FTop write SetTop;
    property Left: Integer read FLeft write SetLeft;
  published
    property Bitmap: TBitmap read FBitmap write SetBitmap;
  end;

  TActiveCellShow = (assNone, assCol, assRow);

  TPlannerGrid = class(TCustomGrid)
  private
    { Private declarations }
    FActiveCellShow: TActiveCellShow;
    FLastHintPos: TPoint;
    FLastHintItem: TPlannerItem;
    FToolTipPos: TPoint;
    FLastDesignChoice: Integer;
    FUpdateCount: Integer;
    FPlanner: TCustomPlanner;
{$IFNDEF DELPHI_UNICODE}
    FUniMemo: TPlannerUniMemo;
{$ENDIF}
    FMemo: TPlannerMemo;
    FMaskEdit: TPlannerMaskEdit;
    FMouseDown: Boolean;
    FMouseUnSelect: Boolean;
    FMouseDownMove: Boolean;
    FMouseDownSizeUp: Boolean;
    FMouseDownSizeDown: Boolean;
    FMouseDownMoveFirst: Boolean;
    FMouseStart: Boolean;
    FMouseXY: TPoint;
    FMouseRCD, FMouseRC: TGridCoord;
    FColorList: TPlannerColorArrayList;
    FScrollHintWindow: THintWindow;
    FItemXY: TPoint;
    FItemXYS: TRect;
    FEraseBkGnd: Boolean;
    FSelItem: TPlannerItem;
    FOldSelection, FHiddenSelection: TGridRect;
    FOldTopRow: Integer;
    FOldLeftCol: Integer;
    FScrolling: Boolean;
    FMouseRelease: Boolean;
    FAutoFocus: Boolean;
    FMoveForm: TForm;
    FScrollTime: Cardinal;
    FCurrCtrlR: TRect;
    FCurrCtrlID: string;
    FCurrCtrlItem: TPlannerItem;
    FCurrCtrlEdit: string;
    FPosResizing: Boolean;
    FInplaceEdit: TEdit;
    FInplaceCombo: TPlanCombobox;
    FHToolTip: THandle;
    FToolTipBuffer: array [0 .. 4096] of Char;
    procedure WMPaint(var Message: TWMPaint); message WM_PAINT;
    procedure WMNotify(var Message: TWMNotify); message WM_NOTIFY;
    procedure WMVScroll(var WMScroll: TWMScroll); message WM_VSCROLL;
    procedure WMHScroll(var WMScroll: TWMScroll); message WM_HSCROLL;
    procedure WMLButtonDblClk(var Message: TWMLButtonDblClk); message WM_LBUTTONDBLCLK;
    procedure WMRButtonDown(var Msg:TWMLButtonDown); message WM_RBUTTONDOWN;
    procedure WMLButtonDown(var Message: TWMLButtonDown); message WM_LBUTTONDOWN;
    procedure WMEraseBkGnd(var Message: TWMEraseBkgnd); message WM_ERASEBKGND;
    procedure WMMouseMove(var Message: TWMMouseMove); message WM_MOUSEMOVE;
    procedure WMSetCursor(var Msg: TWMSetCursor); message WM_SETCURSOR;
    procedure CMDesignHitTest(var Msg: TCMDesignHitTest); message CM_DESIGNHITTEST;
    procedure CMHintShow(var Message: TMessage); message CM_HINTSHOW;
    procedure CNKeyDown(var Message: TWMKeydown); message CN_KEYDOWN;
    procedure RTFPaint(ACanvas: TCanvas; ARect: TRect; const rtf: string; Background: TColor);
    procedure UpdatePositions;
    procedure StartEditCol(ARect: TRect; APlannerItem: TPlannerItem; X, Y: Integer);
    procedure StartEditRow(ARect: TRect; APlannerItem: TPlannerItem; X, Y: Integer);
    procedure PaintItemCol(Canvas: TCanvas; ARect: TRect; APlannerItem: TPlannerItem; Print, SelColor: Boolean); virtual;
    procedure PaintItemRow(Canvas: TCanvas; ARect: TRect; APlannerItem: TPlannerItem; Print, SelColor: Boolean);
    procedure PaintSideCol(Canvas: TCanvas; ARect: TRect; ARow, APos, Offs: Integer; Occupied, Print: Boolean); virtual;
    procedure PaintSideRow(Canvas: TCanvas; ARect: TRect; AColumn, APos: Integer; Occupied, Print: Boolean; DefColWidth: Integer);
    procedure PaintLinks;
    procedure GetSideBarLines(Index, Position: Integer; var Line1, Line2, Line3: string; var HS: Boolean);
    procedure DrawWallPaperFixed(CRect: TRect; xcorr, ycorr: Integer; BKColor: TColor);
    procedure DrawWallPaperTile(ACol, ARow: Integer; CRect: TRect; xcorr, ycorr: Integer; BKColor: TColor);
    procedure DrawCellCol(AColumn, ARow: LongInt; ARect: TRect; AState: TGridDrawState);
    procedure DrawCellRow(AColumn, ARow: LongInt; ARect: TRect; AState: TGridDrawState);
    procedure SetEditDirectSelection(ARect: TRect; X, Y: Integer);
    function CellRectEx(X, Y: Integer): TRect;
    function ColWidthEx(ItemPos: Integer): Integer;
    function RowHeightEx(ItemPos: Integer): Integer;
    procedure SetActiveCellShow(AValue: TActiveCellShow);
    procedure UpdateNVI;
    function MouseOverDesignChoice(X, Y: Integer): Integer;
    function GetRowEx: Integer;
    procedure SetRowEx(const Value: Integer);
    function GetColEx: Integer;
    procedure SetColEx(const Value: Integer);
  protected
    { Protected declarations }
    procedure DrawCell(AColumn, ARow: LongInt; ARect: TRect; AState: TGridDrawState); override;
    procedure HintShowXY(X, Y: Integer; AItem: TPlannerItem; Caption: TCaption);
    procedure HintHide;
    procedure Loaded; override;
    procedure Resize; override;
    procedure DestroyWnd; override;
    procedure KeyPress(var Key: Char); override;
    procedure KeyDown(var Key: Word; ShiftState: TShiftState); override;
    procedure KeyUp(var Key: Word; ShiftState: TShiftState); override;
    procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
    procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
    procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
    procedure TopLeftChanged; override;
    function GetHScrollSize: Integer;
    function GetVScrollSize: Integer;
    procedure DoEnter; override;
    procedure DoExit; override;
    property ColorList: TPlannerColorArrayList read FColorList write FColorList;
    procedure DragOver(Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean); override;
    procedure RepaintSelection(ASelection: TGridRect);
    procedure RepaintRect(R: TRect);
    procedure SelChanged;
    function SelectCell(AColumn, ARow: LongInt): Boolean; override;
    procedure MouseToCell(X, Y: Integer; var ACol, ARow: LongInt);
    procedure InvalidateCellRect(R: TRect);
    procedure ChangeSelection(X, Y, dx, dy: Integer);
    procedure CorrectSelection; virtual;
    procedure UpdateVScrollBar;
    procedure UpdateHScrollBar;
    procedure SyncPlanner;
    procedure FlatSetScrollInfo(Code: Integer; var ScrollInfo: TScrollInfo; FRedraw: Bool);
    procedure FlatSetScrollProp(Index, NewValue: Integer; FRedraw: Bool);
    procedure FlatShowScrollBar(Code: Integer; Show: Bool);
    procedure FlatScrollInit;
    procedure FlatScrollDone;
    procedure FormHandle(Item: TPlannerItem; ControlRect: TRect; ControlID, ControlType, ControlValue: string);
    procedure FormExit(Sender: TObject);
    function DoMouseWheelDown(Shift: TShiftState; MousePos: TPoint): Boolean; override;
    function DoMouseWheelUp(Shift: TShiftState; MousePos: TPoint): Boolean; override;
    procedure Paint; override;
    procedure WndProc(var Msg: TMessage); override;
  public
    { Public declarations }
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    procedure CreateWnd; override;
    procedure CreateToolTip;
    procedure AddToolTip(IconType: Integer; Text, Title: string);
    procedure DestroyToolTip;
    procedure DragDrop(Source: TObject; X, Y: Integer); override;
    procedure HideSelection;
    procedure UnHideSelection;
    procedure BeginUpdate;
    procedure EndUpdate;
    property AutoFocus: Boolean read FAutoFocus write FAutoFocus;
    property Canvas;
    property Ctl3D;
    property EditorMode;
    property GridHeight;
    property GridWidth;
    property LeftCol;
    property Selection;
    property TabStops;
    property TopRow;
    property Row: Integer read GetRowEx write SetRowEx;
    property Col: Integer read GetColEx write SetColEx;
    property Options;
    property RowCount;
    property ColCount;
    property ColWidths;
    property RowHeights;
    property FixedRows;
    property FixedCols;
    property VisibleColCount;
    property VisibleRowCount;
    property BorderStyle;
    property DefaultRowHeight;
    property DefaultColWidth;
    property MouseRelease: Boolean read FMouseRelease write FMouseRelease;
    property HToolTip: THandle read FHToolTip write FHToolTip;
    procedure UpdateScrollBars;
  published
    { Published declarations }
    property ActiveCellShow: TActiveCellShow read FActiveCellShow write
      SetActiveCellShow;
    property ScrollBars;
    property OnMouseMove;
    property OnMouseDown;
    property OnMouseUp;
    {$IFDEF DELPHI2006_LVL}
    property OnMouseLeave;
    property OnMouseEnter;
    {$ENDIF}
    property OnKeyDown;
    property OnKeyUp;
    property OnKeyPress;
  end;

  THourType = (ht24hrs, ht12hrs, htAMPM0, htAMPM1, htAMPMOnce);

  TInplaceEditType = (ieAlways, ieNever);

  THeaderOrientation = (hoHorizontal, hoVertical);

  THeaderClickEvent = procedure(Sender: TObject; SectionIndex: Integer) of object;

  THeaderAnchorEvent = procedure(Sender: TObject; SectionIndex: Integer; Anchor: string) of object;

  THeaderHintEvent = procedure(Sender: TObject; SectionIndex: Integer; var AHint: string) of object;

  THeaderDrawPropEvent = procedure(Sender: TObject; SectionIndex: Integer;
    var AColor, AColorTo: TColor; AFont: TFont) of object;

  THeaderDrawEvent = procedure(Sender: TObject; SectionIndex: Integer;
    ACanvas: TCanvas; ARect: TRect) of object;

  TSidebarHintEvent = procedure(Sender: TObject; Index: Integer; var AHint: string) of object;

  TSidebarClickEvent = procedure(Sender: TObject; Index: Integer) of object;

  THeaderDragDropEvent = procedure(Sender: TObject; FromSection, ToSection: Integer) of object;

  THeaderEditEvent = procedure(Sender: TObject; SectionIndex: Integer; var Text: string) of object;

  TAdvHeader = class(THeader)
  private
    FOffset: Integer;
    FLeftPos: Integer;
    FAlignment: TAlignment;
    FAllowSizing: Boolean;
    FVAlignment: TVAlignment;
    FColor: TColor;
    FLineColor: TColor;
    FFlat: Boolean;
    FImageList: TImageList;
    FInplaceEdit: TMemo;
    FImagePosition: TImagePosition;
    FOnClick: THeaderClickEvent;
    FOnRightClick: THeaderClickEvent;
    FOnDragDrop: THeaderDragDropEvent;
    FOrientation: THeaderOrientation;
    FSectionDragDrop: Boolean;
    FDragging: Boolean;
    FDragStart: Integer;
    FEditSection: Integer;
    FEditWidth: Integer;
    FOnSectionEditEnd: THeaderClickEvent;
    FOnSectionEditStart: THeaderClickEvent;
    FSectionEdit: Boolean;
    FItemHeight: Integer;
    FTextHeight: Integer;
    FOnDblClick: THeaderClickEvent;
    FShowFixed: Boolean;
    FFixedHeight: Integer;
    FFixedColor: TColor;
    FZoomCol: Integer;
    FZoom: Boolean;
    FLastHintPos: TPoint;
    FColorTo: TColor;
    FRotate: Boolean;
    FSizing: Boolean;
    FHitTest: TPoint;
    FCanResize: Boolean;
    FResizeSection: Integer;
    FMouseOffset: Integer;
    FMouseDownMove: Boolean;
    FDragItem: TPlannerItem;
    FOldAnchor: string;
    FHeaderAnchor: string;
    FAnchorItem: TPlannerItem;
    FHToolTip: THandle;
    FBalloonItem: TPlannerItem;
    FOnHeaderHint: THeaderHintEvent;
    FToolTipBuffer: array [0 .. 4096] of Char;
    procedure SetAlignment(const value: TAlignment);
    procedure SetColor(const value: TColor);
    procedure SetImageList(const value: TImageList);
    procedure SetImagePosition(const value: TImagePosition);
    procedure CMHintShow(var Message: TMessage); message CM_HINTSHOW;
    procedure WMLButtonDown(var Msg: TWMLButtonDown); message WM_LBUTTONDOWN;
    procedure WMLButtonDblClk(var Message: TWMLButtonDblClk); message WM_LBUTTONDBLCLK;
    procedure WMSize(var Msg: TWMSize); message WM_SIZE;
    procedure WMNCHitTest(var Msg: TWMNCHitTest); message WM_NCHITTEST;
    procedure WMSetCursor(var Msg: TWMSetCursor); message WM_SETCURSOR;
    procedure WMNotify(var Message: TWMNotify); message WM_NOTIFY;
    procedure SetOrientation(const value: THeaderOrientation);
    procedure SetFlat(const value: Boolean);
    procedure SetLineColor(const value: TColor);
    procedure SetVAlignment(const value: TVAlignment);
    procedure InplaceExit(Sender: TObject);
    procedure SetItemHeight(const value: Integer);
    procedure SetTextHeight(const value: Integer);
    procedure SetFixedColor(const value: TColor);
    procedure SetFixedHeight(const value: Integer);
    procedure SetShowFixed(const value: Boolean);
    procedure SetColorTo(const value: TColor);
    procedure SetRotate(const value: Boolean);
    //    function IsAnchor(x,y: Integer): string;
  protected
    function XYToSection(X, Y: Integer): Integer; virtual;
    function GetSectionRect(X: Integer): TRect; virtual;
    function GetSectionIdx(X: Integer): Integer; virtual;
    procedure StartEdit(ARect: TRect; APlannerItem: TPlannerItem; X, Y: Integer); virtual;
    procedure StopEdit;
    procedure Paint; override;
    procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
    procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
    procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
    procedure DragOver(Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean); override;
    procedure CreateToolTip;
    procedure AddToolTip(IconType: Integer; Text, Title: string);
    procedure DestroyToolTip;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    function ItemAtXY(X, Y: Integer; var ARect: TRect): TPlannerItem;
    procedure DragDrop(Source: TObject; X, Y: Integer); override;
  published
    property Alignment: TAlignment read FAlignment write SetAlignment;
    property AllowSizing: Boolean read FAllowSizing write FAllowSizing;
    property Color: TColor read FColor write SetColor;
    property ColorTo: TColor read FColorTo write SetColorTo;
    property Flat: Boolean read FFlat write SetFlat;
    property FixedColor: TColor read FFixedColor write SetFixedColor;
    property FixedHeight: Integer read FFixedHeight write SetFixedHeight;
    property ShowFixed: Boolean read FShowFixed write SetShowFixed;
    property Images: TImageList read FImageList write SetImageList;
    property ImagePosition: TImagePosition read FImagePosition write SetImagePosition;
    property ItemHeight: Integer read FItemHeight write SetItemHeight;
    property TextHeight: Integer read FTextHeight write SetTextHeight;
    property LineColor: TColor read FLineColor write SetLineColor default clGray;
    property SectionDragDrop: Boolean read FSectionDragDrop write FSectionDragDrop;
    property SectionEdit: Boolean read FSectionEdit write FSectionEdit;
    property VAlignment: TVAlignment read FVAlignment write SetVAlignment;
    property Rotate: Boolean read FRotate write SetRotate;
    property Zoom: Boolean read FZoom write FZoom;
    property ZoomCol: Integer read FZoomCol write FZoomCol;
    property Orientation: THeaderOrientation read FOrientation write SetOrientation default hoHorizontal;
    property OnClick: THeaderClickEvent read FOnClick write FOnClick;
    property OnRightClick: THeaderClickEvent read FOnRightClick write FOnRightClick;
    property OnDblClick: THeaderClickEvent read FOnDblClick write FOnDblClick;
    property OnDragDrop: THeaderDragDropEvent read FOnDragDrop write FOnDragDrop;
    property OnSectionEditStart: THeaderClickEvent read FOnSectionEditStart write FOnSectionEditStart;
    property OnSectionEditEnd: THeaderClickEvent read FOnSectionEditEnd write FOnSectionEditEnd;
    property OnHeaderHint: THeaderHintEvent read FOnHeaderHint write FOnHeaderHint;
    property OnMouseMove;
    property OnMouseDown;
    property OnMouseUp;
  end;

  TAdvFooter = class(TAdvHeader)
  private
    FUpdateCount: Integer;
  protected
    procedure Paint; override;
  public
    constructor Create(AOwner: TComponent); override;
    procedure BeginUpdate;
    procedure EndUpdate;
  end;

  TPlannerPrintOptions = class(TPersistent)
  private
    FFooterSize: Integer;
    FLeftMargin: Integer;
    FRightMargin: Integer;
    FTopMargin: Integer;
    FHeaderSize: Integer;
    FHeaderFont: TFont;
    FFooterFont: TFont;
    FOrientation: TPrinterOrientation;
    FFooter: TStrings;
    FHeader: TStrings;
    FHeaderAlignment: TAlignment;
    FFooterAlignment: TAlignment;
    FFitToPage: Boolean;
    FJobname: string;
    FCellHeight: Integer;
    FCellWidth: Integer;
    FSidebarWidth: Integer;
    FLineWidth: Integer;
    procedure SetFooter(const value: TStrings);
    procedure SetFooterFont(const value: TFont);
    procedure SetHeader(const value: TStrings);
    procedure SetHeaderFont(const value: TFont);
  public
    constructor Create;
    destructor Destroy; override;
    procedure Assign(Source: TPersistent); override;
  published
    property CellHeight: Integer read FCellHeight write FCellHeight default 0;
    property CellWidth: Integer read FCellWidth write FCellWidth default 0;
    property LineWidth: Integer read FLineWidth write FLineWidth default 1;
    property FitToPage: Boolean read FFitToPage write FFitToPage default True;
    property Footer: TStrings read FFooter write SetFooter;
    property FooterAlignment: TAlignment read FFooterAlignment write FFooterAlignment default taLeftJustify;
    property FooterFont: TFont read FFooterFont write SetFooterFont;
    property FooterSize: Integer read FFooterSize write FFooterSize default 0;
    property Header: TStrings read FHeader write SetHeader;
    property HeaderAlignment: TAlignment read FHeaderAlignment write FHeaderAlignment default taLeftJustify;
    property HeaderFont: TFont read FHeaderFont write SetHeaderFont;
    property HeaderSize: Integer read FHeaderSize write FHeaderSize default 0;
    property JobName: string read FJobname write FJobname;
    property LeftMargin: Integer read FLeftMargin write FLeftMargin default 0;
    property Orientation: TPrinterOrientation read FOrientation write FOrientation default poPortrait;
    property RightMargin: Integer read FRightMargin write FRightMargin default 0;
    property TopMargin: Integer read FTopMargin write FTopMargin default 0;
    property SidebarWidth: Integer read FSidebarWidth write FSidebarWidth default 0;
  end;

  TPlannerHTMLOptions = class(TPersistent)
  private
    FFooterFile: string;
    FHeaderFile: string;
    FBorderSize: Integer;
    FCellSpacing: Integer;
    FTableStyle: string;
    FPrefixTag: string;
    FSuffixTag: string;
    FWidth: Integer;
    FSidebarFontTag: string;
    FHeaderFontTag: string;
    FCellFontTag: string;
    FCellFontStyle: TFontStyles;
    FHeaderFontStyle: TFontStyles;
    FSidebarFontStyle: TFontStyles;
    FShowCaption: Boolean;
  public
    constructor Create;
  published
    property BorderSize: Integer read FBorderSize write FBorderSize default 1;
    property CellSpacing: Integer read FCellSpacing write FCellSpacing default 0;
    property FooterFile: string read FFooterFile write FFooterFile;
    property HeaderFile: string read FHeaderFile write FHeaderFile;
    property TableStyle: string read FTableStyle write FTableStyle;
    property PrefixTag: string read FPrefixTag write FPrefixTag;
    property SuffixTag: string read FSuffixTag write FSuffixTag;
    property Width: Integer read FWidth write FWidth default 100;
    property CellFontTag: string read FCellFontTag write FCellFontTag;
    property CellFontStyle: TFontStyles read FCellFontStyle write FCellFontStyle;
    property HeaderFontTag: string read FHeaderFontTag write FHeaderFontTag;
    property HeaderFontStyle: TFontStyles read FHeaderFontStyle write FHeaderFontStyle;
    property SidebarFontTag: string read FSidebarFontTag write FSidebarFontTag;
    property SidebarFontStyle: TFontStyles read FSidebarFontStyle write FSidebarFontStyle;
    property ShowCaption: Boolean read FShowCaption write FShowCaption default False;
  end;

  TDragOverItemEvent = procedure(Sender, Source: TObject; X, Y: Integer;
    APlannerItem: TPlannerItem; State: TDragState; var Accept: Boolean) of object;

  TDragDropItemEvent = procedure(Sender, Source: TObject; X, Y: Integer;
    PlannerItem: TPlannerItem) of object;

  TWeekDays = class(TPersistent)
  private
    FSat: Boolean;
    FSun: Boolean;
    FMon: Boolean;
    FTue: Boolean;
    FWed: Boolean;
    FThu: Boolean;
    FFri: Boolean;
    FChanged: TNotifyEvent;
    procedure SetSat(const value: Boolean);
    procedure SetSun(const value: Boolean);
    procedure SetMon(const value: Boolean);
    procedure SetTue(const value: Boolean);
    procedure SetWed(const value: Boolean);
    procedure SetThu(const value: Boolean);
    procedure SetFri(const value: Boolean);
    procedure Changed;
  public
    constructor Create;
  published
    property Sat: Boolean read FSat write SetSat default True;
    property Sun: Boolean read FSun write SetSun default True;
    property Mon: Boolean read FMon write SetMon default False;
    property Tue: Boolean read FTue write SetTue default False;
    property Wed: Boolean read FWed write SetWed default False;
    property Thu: Boolean read FThu write SetThu default False;
    property Fri: Boolean read FFri write SetFri default False;
    property OnChanged: TNotifyEvent read FChanged write FChanged;
  end;

  TByteSet = set of Byte;

  TButtonDirection = (bdLeft, bdRight);

  TAdvSpeedButton = class(TSpeedButton)
  private
    FButtonDirection: TButtonDirection;
    FIsWinXP: Boolean;
    procedure CMMouseLeave(var Message: TMessage); message CM_MOUSELEAVE;
    procedure CMMouseEnter(var Message: TMessage); message CM_MOUSEENTER;
  protected
    procedure Paint; override;
  public
    constructor Create(AOwner: TComponent); override;
  published
    property Direction: TButtonDirection read FButtonDirection write
      FButtonDirection;
  end;

  TPlannerExChange = class(TComponent)
  private
    FPlanner: TCustomPlanner;
  protected
    procedure Notification(AComponent: TComponent; AOperation: TOperation); override;
  public
    function NumItemsForExport: Integer;
    procedure DoExport; virtual;
    procedure DoImport; virtual;
  published
    property Planner: TCustomPlanner read FPlanner write FPlanner;
  end;

  TPlannerUserMode = (puNormal, puReadOnly, puViewOnly);

  TPlannerWheelAction = (pwaSelect, pwaScroll);

  TCellBrush = record
    Color: TColor;
    BrushStyle: TBrushStyle;
  end;

  TCustomPlanner = class(TCustomControl, ITMSStyle)
  private
    { Private declarations }
    FTMSStyle: TTMSStyle;
    FDesignTime: Boolean;
    FHTMLFactor: Double;
    FRichEdit: TPlannerRichEdit;
    FBalloon: TBalloonSettings;
    FDownOnItem: Boolean;
    FActiveDisplay: Boolean;
    FBands: TBands;
    FOverlap: Boolean;
    FColor: TColor;
    FLayer: Integer;
    FEditRTF: Boolean;
    FEditDirect: Boolean;
    FEditOnSelectedClick: Boolean;
    FEditScroll: TScrollStyle;
    FTrackColor: TColor;
    FTrackOnly: Boolean;
    FTrackProportional: Boolean;
    FTrackWidth: Integer;
    FFont: TFont;
    FGrid: TPlannerGrid;
    FGridPopup: TPopupMenu;
    FGridLineColor: TColor;
    FItemPopup: TPopupMenu;
    FPopupPlannerItem: TPlannerItem;
    FHeader: TAdvHeader;
    FFooter: TAdvFooter;
    FHintOnItemChange: Boolean;
    FHintColor: TColor;
    FHintPause: Integer;
    FItemGap: Integer;
    FNext: TAdvSpeedButton;
    FPrev: TAdvSpeedButton;
    FMode: TPlannerMode;
    FCaption: TPlannerCaption;
    FSidebar: TPlannerSideBar;
    FDisplay: TPlannerDisplay;
    FDayNames: TStringList;
    FHourType: THourType;
    FPlannerHeader: TPlannerHeader;
    FPlannerFooter: TPlannerFooter;
    FPlannerItems: TPlannerItems;
    FPlannerImages: TImageList;
    FContainer: TPictureContainer;
    FImageCache: THTMLPictureCache;
    FTimerActiveCells: Integer;
    FTimerIdxCell: Integer;
    FPlanChecker: TPlannerCheck;
    FPanel: TPlannerPanel;
    FPositions: Integer;
    FPositionGap: Integer;
    FPositionGapColor: TColor;
    FShowOccupiedInPositionGap: Boolean;
    FPositionWidth: Integer;
    FPositionZoomWidth: Integer;
    FPositionProps: TPositionProps;
    FPrintOptions: TPlannerPrintOptions;
    FHTMLOptions: TPlannerHTMLOptions;
    FInactiveDays: TWeekDays;
    FInactive: TByteSet;
    FLinkUpdate: Boolean;
    FLinkCancel: Boolean;
    FLinkArrowShape: TArrowShape;
    FLinkArrowSize: integer;
    FPrinterDriverFix: Boolean;
    FScrollSynch: Boolean;
    FDirectMove: Boolean;
    FDirectDrag: Boolean;
    FTimerID: Integer;
    FLoadLeftCol: Integer;
    FSelections: TPlannerSelections;
    FUserMode: TPlannerUserMode;
    FSelectRange: Boolean;
    FSelectOnRightClick: boolean;
    FSyncPlanner: TSyncPlanner;
    FDragImage: TDragImageList;
    FOldOfficeTheme: TOfficeTheme;
    FNavigatorButtons: TNavigatorButtons;
    FOnItemAnchorClick: TItemAnchorEvent;
    FOnItemAnchorEnter: TItemAnchorEvent;
    FOnItemAnchorExit: TItemAnchorEvent;
    FOnItemRightClick: TItemEvent;
    FOnItemDblClick: TItemEvent;
    FOnItemImageClick: TItemImageEvent;
    FOnItemLeftClick: TItemEvent;
    FOnItemMove: TItemMoveEvent;
    FOnItemSize: TItemSizeEvent;
    FOnItemAfterPaint: TItemPaintEvent;
    FOnItemDelete: TItemEvent;
    FOnItemDeleted: TItemEvent;
    FOnItemInsert: TPlannerEvent;
    FOnItemCreated: TItemEvent;
    FOnItemCompletionSettings: TItemGaugeEvent;
    FOnItemStartEdit: TItemEvent;
    FOnItemEndEdit: TItemEvent;
    FOnItemSelect: TItemEvent;
    FONitemCanSelect: TItemDragEvent;
    FOnItemUnSelect: TItemEvent;
    FOnItemEnter: TItemEvent;
    FOnItemExit: TItemEvent;
    FOnItemHint: TItemHintEvent;
    FOnItemHintTime: TItemHintEvent;
    FOnItemBalloon: TItemBalloonEvent;
    FOnItemClipboardAction: TItemClipboardEvent;
    FOnItemSelChange: TItemEvent;
    FOnItemActivate: TItemEvent;
    FOnItemDeActivate: TItemEvent;
    FOnItemCut: TNotifyEvent;
    FOnItemCutting: TItemAllowEvent;
    FOnItemCopied: TItemEvent;
    FOnItemCopying: TItemAllowEvent;
    FOnItemPasting: TAllowEvent;
    FOnItemPasted: TItemEvent;
    FOnItemPopupPrepare: TItemPopupPrepareEvent;
    FOnItemPlaceUpdate: TItemUpdateEvent;
    FOnPlannerLeftClick: TPlannerEvent;
    FOnPlannerRightClick: TPlannerEvent;
    FOnPlannerDblClick: TPlannerEvent;
    FOnPlannerBeforeKeyDown: TKeyEvent;
    FOnPlannerKeypress: TPlannerKeyEvent;
    FOnPlannerKeyDown: TPlannerKeyDownEvent;
    FOnPlannerKeyUp: TPlannerKeyDownEvent;
    FOnPlannerItemDraw: TPlannerItemDraw;
    FOnPlannerIsActive: TPlannerActiveEvent;
    FOnPlannerSideDraw: TPlannerSideDraw;
    FOnPlannerSideDrawAfter: TPlannerSideDraw;
    FOnPlannerSideProp: TPlannerSideProp;
    FOnPlannerGetSideBarLines: TPlannerGetSideBarLines;
    FOnPlannerBkgDraw: TPlannerBkgDraw;
    FOnPlannerHeaderDraw: TPlannerHeaderDraw;
    FOnPlannerFooterDraw: TPlannerHeaderDraw;
    FOnPlannerCaptionDraw: TPlannerCaptionDraw;
    FOnPlannerNext: TPlannerBtnEvent;
    FOnPlannerPrev: TPlannerBtnEvent;
    FOnPlannerNextPosition: TPlannerBtnEvent;
    FOnPlannerPrevPosition: TPlannerBtnEvent;
    FOnPlannerMouseMove: TMouseMoveEvent;
    FOnPlannerMouseUp: TMouseEvent;
    FOnPlannerMouseDown: TMouseEvent;
    FOnPlannerMouseLeave: TNotifyEvent;
    FOnPlannerMouseEnter: TNotifyEvent;
    FOnSideBarClick: TSidebarClickEvent;
    FOnSideBarRightClick: TSidebarClickEvent;
    FOnSideBarDblClick: TSidebarClickEvent;
    FOnPrintHeader: TPlannerPrintHFEvent;
    FOnPrintFooter: TPlannerPrintHFEvent;
    FOnAfterPaint: TNotifyEvent;
    FOnPlannerBalloon: TPlannerBalloonEvent;
    FOnCaptionAnchorEnter: TPlannerAnchorEvent;
    FOnCaptionAnchorExit: TPlannerAnchorEvent;
    FOnCaptionAnchorClick: TPlannerAnchorEvent;
    FOnCustomEdit: TCustomEditEvent;
    FOnCustomITEvent: TCustomITEvent;
    FOnCustomTIEvent: TCustomTIEvent;
    FOnHeaderClick: THeaderClickEvent;
    FOnHeaderHint: THeaderHintEvent;
    FOnHeaderDrawProp: THeaderDrawPropEvent;
    FOnHeaderGroupDrawProp: THeaderDrawPropEvent;
    FOnHeaderDraw: THeaderDrawEvent;
    FOnFooterHint: THeaderHintEvent;
    FOnSideBarHint: TSidebarHintEvent;
    FOnHeaderHeightChange: THeaderHeightChangeEvent;
    FOnHeaderSized: TPlannerHeaderSizeEvent;
    FOnHeaderRightClick: THeaderClickEvent;
    FOnHeaderStartEdit: THeaderEditEvent;
    FOnHeaderEndEdit: THeaderEditEvent;
    FOnPrintStart: TPlannerPrintEvent;
    FOnTopLeftChanged: TPlannerBtnEvent;
    FOnDragOver: TDragOverEvent;
    FOnDragOverCell: TDragOverEvent;
    FOnDragOverItem: TDragOverItemEvent;
    FOnDragOverHeader: TDragOverHeaderEvent;
    FOnDragDrop: TDragDropEvent;
    FOnDragDropCell: TDragDropEvent;
    FONDragDropHeader: TDragDropHeaderEvent;
    FOnDragDropItem: TDragDropItemEvent;
    FOnPlannerSelChange: TPlannerEvent;
    FOnPlannerSelectCell: TPlannerSelectCellEvent;
    FOnItemMoving: TItemMovingEvent;
    FOnItemSizing: TItemSizingEvent;
    FOnItemText: TPlannerItemText;
    FOnGetCurrentTime: TGetCurrentTimeEvent;
    FOnPlanTimeToStrings: TPlannerPlanTimeToStrings;
    FOnExit: TNotifyEvent;
    FOnEnter: TNotifyEvent;
    FMultiSelect: Boolean;
    FDisjunctSelect: Boolean;
    FDefaultItem: TPlannerItem;
    FDefaultItems: TPlannerItems;
    FSelectColor: TColor;
    FShowSelection: Boolean;
    FDisjunctSelectColor: TColor;
    FFlat: Boolean;
    FLoading: Boolean;
    FOnPlannerBottomLine: TPlannerBottomLineEvent;
    FOnPlannerRightLine: TPlannerBottomLineEvent;
    FStreamPersistentTime: Boolean;
    FHTMLHint: Boolean;
    FOnHeaderDragDrop: THeaderDragDropEvent;
    FURLColor: TColor;
    FURLGlyph: TBitmap;
    FDeleteGlyph: TBitmap;
    FAttachementGlyph: TBitmap;
    FOnItemURLClick: TItemLinkEvent;
    FOnItemAttachementClick: TItemLinkEvent;
    FScrollBarStyle: TPlannerScrollBar;
    FBackGround: TBackground;
    FPaintMarginTY: Integer;
    FPaintMarginLX: Integer;
    FPaintMarginBY: Integer;
    FPaintMarginRX: Integer;
    FEnableAlarms: Boolean;
    FEnableFlashing: Boolean;
    FEnableKeyboard: Boolean;
    FIndicateNonVisibleItems: Boolean;
    FHandlingAlarm: Boolean;
    FWheelDelta: Integer;
    FWheelAction: TPlannerWheelAction;
    FScrollDelay: Cardinal;
    FContinuousSelect: boolean;
    FOnHeaderDblClick: THeaderClickEvent;
    FOnHeaderAnchorEnter: THeaderAnchorEvent;
    FOnHeaderAnchorLeave: THeaderAnchorEvent;
    FOnHeaderAnchorClick: THeaderAnchorEvent;
    FAutoItemScroll: Boolean;
    FOnPositionToDay: TPlannerPositionToDay;
    FSelectionAlways: Boolean;
    FFlashColor: TColor;
    FOnItemAlarm: TItemEvent;
    FFlashFontColor: TColor;
    FDragItem: Boolean;
    FDragItemAlways: Boolean;
    FDragItemImage: Boolean;
    FCtrlDragCopy: Boolean;
    FOnItemDrag: TItemDragEvent;
    FScrollSmooth: Boolean;
    FPositionGroup: Integer;
    FTrackBump: Boolean;
    FOnPlannerPositionZoom: TPlannerPositionZoom;
    FOnPlannerBeforePositionZoom: TPlannerBeforePositionZoom;
    FOnPlannerUpdateCompletion: TNotifyEvent;
    FSelectBlend: Integer;
    FSelectBackground: Boolean;
    FInsertAlways: Boolean;
    FShowHint: Boolean;
    FUseVCLStyles: Boolean;
    FTopIndicator: Boolean;
    FBottomIndicator: Boolean;
    FShadowColor: TColor;
    FInplaceEdit: TInplaceEditType;
    FGradientSteps: Integer;
    FGradientHorizontal: Boolean;
    FCompletionColor1: TColor;
    FCompletionColor2: TColor;
    FCheckConflicts: Boolean;
    FItemSelection: TPlannerItemSelection;
    FDTList: TDateTimeList;
    FDrawPrecise: Boolean;
    FRoundTime: Boolean;
    FAutoInsDel: Boolean;
    FAutoPositionPrevNext: Boolean;
    FAutoSelectLinkedItems: Boolean;
    FAutoDeleteLinkedItems: Boolean;
    FAutoCreateOnSelect: Boolean;
    FAllowClipboardShortCuts: Boolean;
    FAutoThemeAdapt: Boolean;
    FStickySelect: Boolean;
    FImageOffsetX: Integer;
    FImageOffsetY: Integer;
    FGroupGapOnly: Boolean;
    FMaxHintWidth: Integer;
    FShowDesignHelper: Boolean;
    FNoPositionSize: Boolean;
    FOnConflictUpdate: TNotifyEvent;
    FOnItemUpdate: TNotifyEvent;
    FEditMode: Boolean;
    FPositionAutoSize: Boolean;
    FNotesMaxLength: Integer;
    FScrollBars: TScrollStyle;
    FTimePointers: TPlannerTimePointers;
    FOnItemControlClick: TItemControlEvent;
    FOnItemControlEditStart: TItemControlEvent;
    FOnItemControlEditDone: TItemControlEvent;
    FOnItemControlComboList: TItemControlListEvent;
    FOnItemControlComboSelect: TItemComboControlEvent;
    {$IFDEF DELPHIXE_LVL}
    FOnGesture: TGestureEvent;
    {$ENDIF}
    {$IFDEF TMSSKINS}
    FSkin: TPlannerSkin;
    FOnTimer: TNotifyEvent;
    FShowLinks: Boolean;
    FAllowBackgroundItemSelection: boolean;
    FOnPlannerBkgProp: TPlannerBkgProp;
    procedure SetPlannerSkin(AValue: TPlannerSkin);
    {$ENDIF}
    {$IFDEF DELPHIXE2_LVL}
    procedure CMStyleChanged(var Message: TMessage); message CM_STYLECHANGED;
    {$ENDIF}
    procedure WMTimer(var Message: TWMTimer); message WM_TIMER;
    procedure WMEraseBkGnd(var Message: TWMEraseBkgnd); message WM_ERASEBKGND;
    procedure WMMoving(var Message: TMessage); message WM_MOVING;
    procedure InactiveChanged(Sender: TObject);
    procedure SetCaption(const value: TPlannerCaption);
    procedure SetSideBar(const value: TPlannerSideBar);
    procedure SetDisplay(const value: TPlannerDisplay);
    procedure SetDayNames(const value: TStringList);
    procedure SetHeader(const value: TPlannerHeader);
    procedure SetFooter(const value: TPlannerFooter);
    procedure SetMode(const value: TPlannerMode);
    procedure SetPlannerItems(const value: TPlannerItems);
    procedure SetImages(const value: TImageList);
    procedure SetLayer(const value: LongInt);
    procedure SetDrawPrecise(const value: Boolean);
    procedure SetHourType(const value: THourType);
    procedure SetPositions(const value: Integer);
    procedure SetPositionWidth(const value: Integer);
    procedure SetPositionAutoSize(const value: Boolean);
    procedure SetGridTopRow(const value: Integer);
    procedure SetGridLeftCol(const value: Integer);
    function GetGridTopRow: Integer;
    function GetGridLeftCol: Integer;
    procedure SetFont(value: TFont);
    procedure SetTrackColor(const value: TColor);
    procedure SetTrackOnly(const value: Boolean);
    procedure SetTrackProportional(const value: Boolean);
    procedure SetActiveDisplay(const value: Boolean);
    procedure PlanFontChanged(Sender: TObject);
    procedure UpdateTimer;
    function GetSelItemEnd: Integer;
    function GetSelItemBegin: Integer;
    function GetSelPosition: Integer;
    function GetCellTime(i, j: Integer): TDateTime;
    procedure SetSelItemEnd(const value: Integer);
    procedure SetSelItemBegin(const value: Integer);
    procedure SetSelPosition(value: Integer);
    procedure SetShadowColor(const value: TColor);
    procedure SetGradientSteps(const value: Integer);
    procedure SetGradientHorizontal(const value: Boolean);
    procedure SelChange(Sender: TObject);
    procedure SetGridLineColor(const value: TColor);
    procedure SetColor(const value: TColor);
    function GetBackGroundColor(ACol, ARow: Integer): TColor;
    procedure SetBackGroundColor(ACol, ARow: Integer; const value: TColor);
    function GetSelected(ACol, ARow: Integer): Boolean;
    procedure SetSelected(ACol, ARow: Integer; const value: Boolean);
    procedure SetItemGap(const value: Integer);
    procedure SaveToHTMLCol(Filename: string; Unicode: Boolean = False);
    procedure SaveToHTMLRow(Filename: string; Unicode: Boolean = False);
    function GetMemo: TMemo;
    function GetMaskEdit: TMaskEdit;
    procedure SetDefaultItem(const value: TPlannerItem);
    procedure SetSelectColor(const value: TColor);
    procedure SetFlat(const value: Boolean);
    procedure SetPositionGap(const value: Integer);
    procedure SetPositionGapColor(const value: TColor);
    procedure SetTrackWidth(const value: Integer);
    procedure SetURLColor(const value: TColor);
    procedure SetURLGlyph(const value: TBitmap);
    procedure SetDeleteGlyph(const value: TBitmap);
    procedure SetAttachementGlyph(const value: TBitmap);
    procedure SetEnableAlarms(const value: Boolean);
    procedure SetPositionProps(const value: TPositionProps);
    procedure SetEnableFlashing(const value: Boolean);
    procedure SetFlashColor(const value: TColor);
    procedure SetFlashFontColor(const value: TColor);
    function GetDragCopy: Boolean;
    function GetDragMove: Boolean;
    procedure SetPositionGroup(const value: Integer);
    procedure SetTrackBump(const value: Boolean);
    function GetPositionWidths(Position: Integer): Integer;
    procedure SetPositionWidths(Position: Integer; const value: Integer);
    procedure SetPositionZoomWidth(const value: Integer);
    procedure SetSelectBlend(const value: Integer);
    procedure SetShowHint(const value: Boolean);
    procedure SetShowSelection(const value: Boolean);
    procedure SetItemSelection(AValue: TPlannerItemSelection);
    procedure SetSelectRange(const value: Boolean);
    procedure ItemDesignChange(Sender: TObject);
    procedure UpdateCompletion;
    procedure SetShowDesignHelper(const value: Boolean);
    function GapAtColumn(ACol: Integer): Boolean;
    procedure SetGroupGapOnly(AValue: Boolean);
    function GetEditColor(AItem: TPlannerItem; Sel: Boolean): TColor;
    procedure SetVersion(const value: string);
    function GetVersion: string;
    procedure BalloonInit;
    procedure BalloonDone;
    procedure BalloonChange(Sender: TObject);
    procedure SetShowLinks(const Value: Boolean);
    procedure SetScrollBars(const Value: TScrollStyle);
    procedure SetSyncPlanner(const Value: TSyncPlanner);
    procedure SetDragItemImage(const Value: Boolean);
    procedure SetAutoThemeAdapt(const Value: Boolean);
    procedure SetLinkArrowShape(const Value: TArrowShape);
    procedure SetLinkArrowSize(const Value: integer);
  protected
    { Protected declarations }
    procedure Loaded; override;
    procedure Resize; override;
    procedure UpdateSizes;
    procedure ReadTMSStyle(Reader: TReader);
    procedure WriteTMSStyle(Writer: TWriter);
    procedure DefineProperties(Filer: TFiler); override;
    procedure CreateParams(var Params: TCreateParams); override;
    procedure DestroyWnd; override;
    procedure WndProc(var Message: TMessage); override;
    procedure CreateWnd; override;
    procedure Paint; override;
    procedure InitVCLStyle(init: boolean);
    function GetDayName(WeekDay: Integer): string; virtual;
    function HasActiveDays: boolean;
    function AddActiveDays(ADate: TDateTime; Days: integer): TDateTime;
    function DiffActiveDays(ADate1, ADate2: TDateTime): integer;
    procedure PrintCol(ACanvas: TCanvas; FromPos, ToPos, FromRow, ToRow: Integer);
    procedure PrintRow(ACanvas: TCanvas; FromPos, ToPos, FromCol, ToCol: Integer);
    procedure GetCellBrush(Pos, Index: Integer; ABrush: TBrush);
    function GetCellColorCol(Pos, Index: Integer; var UseColor: Boolean): TCellBrush;
    procedure NextClick(Sender: TObject); virtual;
    procedure PrevClick(Sender: TObject); virtual;
    procedure PrevPosition(Sender: TObject); virtual;
    procedure NextPosition(Sender: TObject); virtual;
    procedure ItemMoved(APlannerItem: TPlannerItem; FromBegin, FromEnd, FromPos, ToBegin, ToEnd, ToPos: Integer); virtual;
    procedure ItemSized(APlannerItem: TPlannerItem; FromBegin, FromEnd, ToBegin, ToEnd: Integer); virtual;
    procedure ItemEdited(Item: TPlannerItem); virtual;
    procedure ItemUnSelected(Item: TPlannerItem); virtual;
    procedure ItemSelected(Item: TPlannerItem); virtual;
    procedure Notification(AComponent: TComponent; AOperation: TOperation); override;
    function CreateItems: TPlannerItems; virtual;
    function GetSelMinMax(Pos: Integer; var SelMin, SelMax: Integer): Boolean;
    function ItemInSel(ItemBegin, ItemEnd, ItemPos: integer): boolean;
    procedure MapItemTimeOnPlanner(APlannerItem: TPlannerItem); virtual;
    procedure MoveResource(FromPos, ToPos: Integer); virtual;
    function GetVersionNr: Integer; virtual;
    function GetVersionString: string; virtual;
    procedure HeaderHeightChange(ASize: Integer); virtual;
    property Selected[ACol, ARow: Integer]: Boolean read GetSelected write SetSelected;
    procedure UpdateSelection(SelBegin, SelEnd, SelPos: Integer; Active: Boolean);
    procedure HeaderAnchorEnter(Sender: TObject; SectionIndex: Integer; Anchor: string); virtual;
    procedure HeaderAnchorClick(Sender: TObject; SectionIndex: Integer; Anchor: string); virtual;
    procedure HeaderAnchorLeave(Sender: TObject; SectionIndex: Integer; Anchor: string); virtual;
    procedure HeaderClick(Sender: TObject; SectionIndex: Integer); virtual;
    procedure HeaderRightClick(Sender: TObject; SectionIndex: Integer); virtual;
    procedure HeaderDblClick(Sender: TObject; SectionIndex: Integer); virtual;
    procedure HeaderDragDrop(Sender: TObject; FromSection, ToSection: Integer); virtual;
    procedure HeaderDraw(Sender: TObject; SectionIndex: Integer; ACanvas: TCanvas; ARect: TRect); virtual;
    procedure HeaderDrawProp(Sender: TObject; SectionIndex: Integer; var AColor, AColorTo: TColor; AFont: TFont); virtual;
    procedure HeaderGroupDrawProp(Sender: TObject; SectionIndex: Integer; var AColor, AColorTo: TColor; AFont: TFont); virtual;
    procedure HeaderSized(Sender: TObject; ASection, AWidth: Integer); virtual;
    procedure DoAfterPaint; virtual;
    procedure DoHeaderHint(Sender: TObject; Index: Integer; var HintStr: string);
    procedure DoFooterHint(Sender: TObject; Index: Integer; var HintStr: string);
    procedure DoMouseLeave(Sender: TObject); virtual;
    procedure DoMouseEnter(Sender: TObject); virtual;
    procedure DoMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); virtual;
    procedure DoMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); virtual;
    procedure DoSideBarClick(Sender: TObject; Index: Integer); virtual;
    procedure DoSideBarRightClick(Sender: TObject; Index: Integer); virtual;
    procedure DoSideBarDblClick(Sender: TObject; Index: Integer); virtual;
    procedure DoPositionAutoSize; virtual;
    procedure DoItemAfterPaint(APlannerItem: TPlannerItem; ACanvas: TCanvas; ARect: TRect); virtual;
    procedure DoItemGaugeSettings(APlannerItem: TPlannerItem; var GaugeSettings: TGaugeSettings); virtual;
    procedure DoStartDrag(var DragObject: TDragObject); override;
    procedure DoEndDrag(Target: TObject; X, Y: Integer); override;
    procedure CreateDragImage(APlannerItem: TPlannerItem);
    function GetDragImages: TDragImageList; override;
    function IsDBAware: Boolean; virtual;
    property LinkUpdate: Boolean read FLinkUpdate write FLinkUpdate;
    function HTMLDBReplace(APlannerItem: TPlannerItem; Data: TObject): string; virtual;
{$IFDEF DELPHIXE_LVL}
    function GetTouch: TTouchManager;
    procedure SetTouch(AValue: TTouchManager);
    procedure GridGesture(Sender: TObject; const EventInfo: TGestureEventInfo; var Handled: Boolean);
{$ENDIF}
  public
    { Public declarations }
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    procedure Assign(Source: TPersistent); override;
    procedure AutoSizeHeader;
    procedure ClearImageCache;
    procedure SaveToHTML(Filename: string; Unicode: Boolean = False);
    procedure SaveToBMP(Filename: string; Size: TSize);
    procedure SaveToStream(Stream: TStream);
    procedure LoadFromStream(Stream: TStream);
    procedure InsertFromStream(Stream: TStream);
    procedure SavePositionToStream(Stream: TStream; Position: Integer);
    procedure LoadPositionFromStream(Stream: TStream; Position: Integer);
    procedure SaveLayerToStream(Stream: TStream; Layer: Integer);
    procedure LoadLayerFromStream(Stream: TStream; Layer: Integer);
    procedure SaveToFile(Filename: string);
    procedure LoadFromFile(Filename: string);
    procedure InsertFromFile(Filename: string);
    procedure SavePositionToFile(Filename: string; Position: Integer);
    procedure LoadPositionFromFile(Filename: string; Position: Integer);
    procedure SaveLayerToFile(Filename: string; Layer: Integer);
    procedure LoadLayerFromFile(Filename: string; Layer: Integer);
    procedure Print;
    procedure PrintPages(NrOfPages: Integer);
    procedure PrintSelection(FromPos, ToPos: Integer);
    procedure PrintRange(FromPos, ToPos, FromItem, ToItem: Integer);
    procedure PrintTo(ACanvas: TCanvas);
    procedure PrintSelectionTo(ACanvas: TCanvas; FromPos, ToPos: Integer);
    procedure PrintRangeTo(ACanvas: TCanvas; FromPos, ToPos, FromItem, ToItem: Integer);
    procedure Invalidate; override;
    procedure ThemeAdapt;
    procedure TextToRich(const RtfText: string);
    function RichToText: string;
    procedure PreviewPaint(APlannerItem: TPlannerItem; Canvas: TCanvas; R: TRect; Direction, Print: Boolean);
    procedure SelectGrid;
    procedure SelectCells(SelBegin, SelEnd, SelPos: Integer);
    procedure ScrollToTime(ATime: TDateTime);
    procedure ScrollToIndex(Index: integer);
    procedure ScrollToPosition(Pos: integer);
    property AllowBackgroundItemSelection: boolean read FAllowBackgroundItemSelection write FAllowBackgroundItemSelection;
    property CompletionColor1: TColor read FCompletionColor1 write FCompletionColor1;
    property CompletionColor2: TColor read FCompletionColor2 write FCompletionColor2;
    property ContinuousSelect: boolean read FContinuousSelect write FContinuousSelect;
    property SelPosition: Integer read GetSelPosition write SetSelPosition;
    property SelItemBegin: Integer read GetSelItemBegin write SetSelItemBegin;
    property SelItemEnd: Integer read GetSelItemEnd write SetSelItemEnd;
    property Selections: TPlannerSelections read FSelections;
    property DateTimeList: TDateTimeList read FDTList write FDTList;
    property GradientSteps: Integer read FGradientSteps write SetGradientSteps;
    property GradientHorizontal: Boolean read FGradientHorizontal write SetGradientHorizontal default False;
    property RichEdit: TPlannerRichEdit read FRichEdit write FRichEdit;
    property MemoEdit: TMemo read GetMemo;
    property MaskEdit: TMaskEdit read GetMaskEdit;
    property EditMode: Boolean read FEditMode;
    property BackgroundColor[ACol, ARow: Integer]: TColor read GetBackGroundColor write SetBackGroundColor;
    property CheckConflicts: boolean read FCheckConflicts write FCheckConflicts;
    procedure ClearBackgroundColors;
    property PrinterDriverFix: Boolean read FPrinterDriverFix write FPrinterDriverFix;
    function PlanTimeToStr(MinutesValue: Integer): string;
    procedure PlanTimeToStrings(MinutesValue: Integer; var HoursString, MinutesString, AmPmString: string);
    function IsSelected(AIndex, APosition: Integer): Boolean;
    function IsActive(AIndex, APosition: Integer): Boolean;
    function IsCurPos(APosition: Integer): Boolean;
    function XYToSelection(X, Y: Integer): TPoint;
    function XYToCell(X, Y: Integer): TPoint;
    function XYToItem(X, Y: Integer): TPlannerItem;
    function CellToItem(X, Y: Integer): TPlannerItem;
    function CellToItemNum(X, Y: Integer): Integer;
    function CellToItemIdx(X, Y, Index: Integer): TPlannerItem;
    function CellInCurrTime(X, Y: Integer): Boolean;
    function CellToTime(X, Y: Integer): TDateTime;
    function CellRect(X, Y: Integer): TRect;
    function PosToDay(Pos: Integer): TDateTime; virtual;
    function IndexToTime(Index: Integer): TDateTime; virtual;
    function TimeToIndex(DT: TDateTime): Integer; virtual;
    procedure CellToAbsTime(X: Integer; var dtStart, dtEnd: TDateTime);
    procedure SelectionToAbsTime(var dtStart, dtEnd: TDateTime);
    function AbsTimeToCell(DateTime: TDateTime): Integer;
    function GetPositionCompletion(Position: Integer; Active: Boolean): Integer;
    function IsVisibleCell(X,Y: integer): boolean;
    procedure HideSelection;
    procedure UnHideSelection;
    procedure MovePosition(FromPos, ToPos: Integer);
    procedure DeletePosition(Position: Integer);
    procedure InsertPosition(Position: Integer);
    function CreateItem: TPlannerItem; virtual;
    function CloneItem(Item: TPlannerItem): TPlannerItem; virtual;
    procedure LinkItems(Items: TPlannerItemArray; Circular: boolean = false; LinkType: TPlannerLinkType = ltLinkNone);
    procedure UnlinkItems(Items: TPlannerItemArray);
    procedure SelectLinkedItems(Item: TPlannerItem);
    function FindItemLinkedTo(Item: TPlannerItem): TPlannerItem;
    procedure RemoveClones(Item: TPlannerItem);
    function CreateItemAtSelection: TPlannerItem; virtual;
    function CloneItemAtSelection(Item: TPlannerItem): TPlannerItem; virtual;
    procedure StopEditing;
    procedure UpdateItem(APlannerItem: TPlannerItem); virtual;
    procedure RefreshItem(APlannerItem: TPlannerItem); virtual;
    procedure FreeItem(APlannerItem: TPlannerItem); virtual;
    procedure Refresh; virtual;
    procedure MarkInItem(APlannerItem: TPlannerItem; AText: string; DoCase: Boolean);
    procedure MarkInPositon(Pos: Integer; AText: string; DoCase: Boolean);
    procedure MarkInItems(AText: string; DoCase: Boolean);
    procedure UnMarkInItem(APlannerItem: TPlannerItem);
    procedure UnMarkInPositon(Pos: Integer);
    procedure UnMarkInItems;
    procedure HilightInItem(APlannerItem: TPlannerItem; AText: string; DoCase: Boolean);
    procedure HilightInPositon(Pos: Integer; AText: string; DoCase: Boolean);
    procedure HilightInItems(AText: string; DoCase: Boolean);
    procedure UnHilightInItem(APlannerItem: TPlannerItem);
    procedure UnHilightInPositon(Pos: Integer);
    procedure UnHilightInItems;
    procedure ExportItem(APlannerItem: TPlannerItem);
    procedure ExportPosition(Pos: Integer);
    procedure ExportItems;
    procedure ExportLayer(Layer: Integer);
    procedure ExportClear;
    procedure UpdateNVI;
    procedure SetStyle(StyleIndex: Integer);
    procedure AdaptItemsStyle;
    procedure SetComponentStyle(AStyle: TTMSStyle);
    function GetComponentStyle: TTMSStyle;
    procedure ZoomPosition(Pos: Integer);
    procedure UnZoomPosition(Pos: Integer);
    property VersionNr: Integer read GetVersionNr;
    property VersionString: string read GetVersionString;
    property PopupPlannerItem: TPlannerItem read FPopupPlannerItem write FPopupPlannerItem;
    property StreamPersistentTime: Boolean read FStreamPersistentTime write FStreamPersistentTime;
    property PaintMarginTY: Integer read FPaintMarginTY write FPaintMarginTY;
    property PaintMarginLX: Integer read FPaintMarginLX write FPaintMarginLX;
    property PaintMarginBY: Integer read FPaintMarginBY write FPaintMarginBY;
    property PaintMarginRX: Integer read FPaintMarginRX write FPaintMarginRX;
    property MaxHintWidth: Integer read FMaxHintWidth write FMaxHintWidth;
    property AutoItemScroll: Boolean read FAutoItemScroll write FAutoItemScroll;
    property DragCopy: Boolean read GetDragCopy;
    property DragMove: Boolean read GetDragMove;
    property PositionWidths[Position: Integer]: Integer read GetPositionWidths write SetPositionWidths;
    property ScrollDelay: Cardinal read FScrollDelay write FScrollDelay;
    property HeaderControl: TAdvHeader read FHeader;
    property FooterControl: TAdvFooter read FFooter;
    property CaptionControl: TPlannerPanel read FPanel;
    property PrevControl: TAdvSpeedButton read FPrev;
    property NextControl: TAdvSpeedButton read FNext;
    property GridControl: TPlannerGrid read FGrid;
    { Normal published declarations }
    property ActiveDisplay: Boolean read FActiveDisplay write SetActiveDisplay default False;
    property AllowClipboardShortCuts: Boolean read FAllowClipboardShortCuts write FAllowClipboardShortCuts default False;
    property AutoCreateOnSelect: Boolean read FAutoCreateOnSelect write FAutoCreateOnSelect default False;
    property AutoInsDel: Boolean read FAutoInsDel write FAutoInsDel default False;
    property AutoPositionPrevNext: Boolean read FAutoPositionPrevNext write FAutoPositionPrevNext default False;
    property AutoSelectLinkedItems: Boolean read FAutoSelectLinkedItems write FAutoSelectLinkedItems default False;
    property AutoDeleteLinkedItems: Boolean read FAutoDeleteLinkedItems write FAutoDeleteLinkedItems default False;
    property AutoThemeAdapt: Boolean read FAutoThemeAdapt write SetAutoThemeAdapt default False;
    property Align;
    property AttachementGlyph: TBitmap read FAttachementGlyph write SetAttachementGlyph;
    property Background: TBackground read FBackGround write FBackGround;
    property Balloon: TBalloonSettings read FBalloon write FBalloon;
    property Bands: TBands read FBands write FBands;
    property Anchors;
    property BiDiMode;
    property Constraints;
    property Caption: TPlannerCaption read FCaption write SetCaption;
    property Color: TColor read FColor write SetColor default clWindow;
    property CtrlDragCopy: Boolean read FCtrlDragCopy write FCtrlDragCopy default False;
    property DayNames: TStringList read FDayNames write SetDayNames;
    property DefaultItem: TPlannerItem read FDefaultItem write SetDefaultItem;
    property DeleteGlyph: TBitmap read FDeleteGlyph write SetDeleteGlyph;
    property DirectMove: Boolean read FDirectMove write FDirectMove default False;
    property DirectDrag: Boolean read FDirectDrag write FDirectDrag;
    property DisjunctSelect: Boolean read FDisjunctSelect write FDisjunctSelect default False;
    property DisjunctSelectColor: TColor read FDisjunctSelectColor write FDisjunctSelectColor default clHighlight;
    property Display: TPlannerDisplay read FDisplay write SetDisplay;
    property DragItem: Boolean read FDragItem write FDragItem default False;
    property DragItemAlways: Boolean read FDragItemAlways write FDragItemAlways default False;
    property DragItemImage: Boolean read FDragItemImage write SetDragItemImage default False;
    property DrawPrecise: Boolean read FDrawPrecise write SetDrawPrecise;
    property RoundTime: Boolean read FRoundTime write FRoundTime;
    property EditRTF: Boolean read FEditRTF write FEditRTF default False;
    property EditDirect: Boolean read FEditDirect write FEditDirect default False;
    property EditOnSelectedClick: Boolean read FEditOnSelectedClick write FEditOnSelectedClick default True;
    property EditScroll: TScrollStyle read FEditScroll write FEditScroll default ssNone;
    property EnableAlarms: Boolean read FEnableAlarms write SetEnableAlarms default False;
    property EnableFlashing: Boolean read FEnableFlashing write SetEnableFlashing default False;
    property EnableKeyboard: Boolean read FEnableKeyboard write FEnableKeyboard default True;
    property FlashColor: TColor read FFlashColor write SetFlashColor default clRed;
    property FlashFontColor: TColor read FFlashFontColor write SetFlashFontColor default clWhite;
    property Flat: Boolean read FFlat write SetFlat default True;
    property Font: TFont read FFont write SetFont;
    property Footer: TPlannerFooter read FPlannerFooter write SetFooter;
    property GridPopup: TPopupMenu read FGridPopup write FGridPopup;
    property GridLeftCol: Integer read GetGridLeftCol write SetGridLeftCol;
    property GridLineColor: TColor read FGridLineColor write SetGridLineColor default $00CECECE;
    property GridTopRow: Integer read GetGridTopRow write SetGridTopRow;
    property GroupGapOnly: Boolean read FGroupGapOnly write SetGroupGapOnly default False;
    property Header: TPlannerHeader read FPlannerHeader write SetHeader;
    property HintColor: TColor read FHintColor write FHintColor default clInfoBk;
    property HintPause: Integer read FHintPause write FHintPause;
    property HintOnItemChange: Boolean read FHintOnItemChange write FHintOnItemChange default True;
    property HourType: THourType read FHourType write SetHourType default ht24hrs;
    property HTMLHint: Boolean read FHTMLHint write FHTMLHint default False;
    property HTMLOptions: TPlannerHTMLOptions read FHTMLOptions write FHTMLOptions;
    property InActiveDays: TWeekDays read FInactiveDays write FInactiveDays;
    property InActive: TByteSet read FInactive;
    property IndicateNonVisibleItems: Boolean read FIndicateNonVisibleItems write FIndicateNonVisibleItems default False;
    property InplaceEdit: TInplaceEditType read FInplaceEdit write FInplaceEdit default ieAlways;
    property InsertAlways: Boolean read FInsertAlways write FInsertAlways default True;
    property ItemChecker: TPlannerCheck read FPlanChecker write FPlanChecker;
    property ItemGap: Integer read FItemGap write SetItemGap default 11;
    property ItemPopup: TPopupMenu read FItemPopup write FItemPopup;
    property Items: TPlannerItems read FPlannerItems write SetPlannerItems;
    property ItemSelection: TPlannerItemSelection read FItemSelection write SetItemSelection;
    property Layer: LongInt read FLayer write SetLayer default 0;
    property LinkArrowShape: TArrowShape read FLinkArrowShape write SetLinkArrowShape default asNormal;
    property LinkArrowSize: integer read FLinkArrowSize write SetLinkArrowSize default ARROW_SIZE;
    property Mode: TPlannerMode read FMode write SetMode;
    property MultiSelect: Boolean read FMultiSelect write FMultiSelect default False;
    property NavigatorButtons: TNavigatorButtons read FNavigatorButtons write FNavigatorButtons;
    property NotesMaxLength: Integer read FNotesMaxLength write FNotesMaxLength default 0;
    property ScrollBars: TScrollStyle read FScrollbars write SetScrollBars default ssBoth;
    property SelectionAlways: Boolean read FSelectionAlways write FSelectionAlways default True;
    property SelectOnRightClick: Boolean read FSelectOnRightClick write FSelectOnRightClick default False;
    property SelectRange: Boolean read FSelectRange write SetSelectRange default True;
    property ShadowColor: TColor read FShadowColor write SetShadowColor default clGray;
    property ShowHint: Boolean read FShowHint write SetShowHint default False;
    property ShowLinks: Boolean read FShowLinks write SetShowLinks default False;
    property ShowDesignHelper: Boolean read FShowDesignHelper write SetShowDesignHelper default True;
    property ShowSelection: Boolean read FShowSelection write SetShowSelection default True;
    property Sidebar: TPlannerSideBar read FSidebar write SetSideBar;
{$IFDEF TMSSKINS}
    property Skin: TPlannerSkin read FSkin write SetPlannerSkin;
{$ENDIF}
    property SyncPlanner: TSyncPlanner read FSyncPlanner write SetSyncPlanner;
{$IFDEF DELPHIXE_LVL}
    property Touch: TTouchManager read GetTouch write SetTouch;
    property OnGesture: TGestureEvent read FOnGesture write FOnGesture;
{$ENDIF}
    property Overlap: Boolean read FOverlap write FOverlap default True;
    property PictureContainer: TPictureContainer read FContainer write FContainer;
    property PlannerImages: TImageList read FPlannerImages write SetImages;
    property Positions: Integer read FPositions write SetPositions default 3;
    property PositionAutoSize: Boolean read FPositionAutoSize write SetPositionAutoSize default False;
    property PositionGap: Integer read FPositionGap write SetPositionGap default 0;
    property PositionGapColor: TColor read FPositionGapColor write SetPositionGapColor default clWhite;
    property PositionGroup: Integer read FPositionGroup write SetPositionGroup default 0;
    property PositionProps: TPositionProps read FPositionProps write SetPositionProps;
    property PositionWidth: Integer read FPositionWidth write SetPositionWidth default 0;
    property PositionZoomWidth: Integer read FPositionZoomWidth write SetPositionZoomWidth default 0;
    property PrintOptions: TPlannerPrintOptions read FPrintOptions write FPrintOptions;
    property ScrollSmooth: Boolean read FScrollSmooth write FScrollSmooth default False;
    property ScrollSynch: Boolean read FScrollSynch write FScrollSynch default False;
    property ScrollBarStyle: TPlannerScrollBar read FScrollBarStyle write FScrollBarStyle;
    property SelectBackground: Boolean read FSelectBackground write FSelectBackground default False;
    property SelectBlend: Integer read FSelectBlend write SetSelectBlend default 90;
    property SelectColor: TColor read FSelectColor write SetSelectColor default clHighlight;
    property ShowOccupiedInPositionGap: Boolean read FShowOccupiedInPositionGap write FShowOccupiedInPositionGap default True;
    property StickySelect: Boolean read FStickySelect write FStickySelect default False;
    property TimePointers: TPlannerTimePointers read FTimePointers;
    property TrackBump: Boolean read FTrackBump write SetTrackBump default False;
    property TrackColor: TColor read FTrackColor write SetTrackColor default clBlue;
    property TrackOnly: Boolean read FTrackOnly write SetTrackOnly default False;
    property TrackProportional: Boolean read FTrackProportional write SetTrackProportional default False;
    property TrackWidth: Integer read FTrackWidth write SetTrackWidth default 4;
    property URLColor: TColor read FURLColor write SetURLColor default clBlue;
    property URLGlyph: TBitmap read FURLGlyph write SetURLGlyph;
    property UserMode: TPlannerUserMode read FUserMode write FUserMode default puNormal;
    property ImageOffsetX: Integer read FImageOffsetX write FImageOffsetX;
    property ImageOffsetY: Integer read FImageOffsetY write FImageOffsetY;
    property Version: string read GetVersion write SetVersion;
    property Visible;
    property WheelDelta: Integer read FWheelDelta write FWheelDelta default 1;
    property WheelAction: TPlannerWheelAction read FWheelAction write FWheelAction default pwaSelect;
    property OnStartDrag;
    property OnEndDrag;
    property OnAfterPaint: TNotifyEvent read FOnAfterPaint write FOnAfterPaint;
    property OnCaptionAnchorEnter: TPlannerAnchorEvent read FOnCaptionAnchorEnter write FOnCaptionAnchorEnter;
    property OnCaptionAnchorExit: TPlannerAnchorEvent read FOnCaptionAnchorExit write FOnCaptionAnchorExit;
    property OnCaptionAnchorClick: TPlannerAnchorEvent read FOnCaptionAnchorClick write FOnCaptionAnchorClick;
    property OnConflictUpdate: TNotifyEvent read FOnConflictUpdate write FOnConflictUpdate;
    property OnItemUpdate: TNotifyEvent read FOnItemUpdate write FOnItemUpdate;
    property OnCustomEdit: TCustomEditEvent read FOnCustomEdit write FOnCustomEdit;
    property OnEnter: TNotifyEvent read FOnEnter write FOnEnter;
    property OnExit: TNotifyEvent read FOnExit write FOnExit;
    property OnItemAnchorClick: TItemAnchorEvent read FOnItemAnchorClick write FOnItemAnchorClick;
    property OnItemAnchorEnter: TItemAnchorEvent read FOnItemAnchorEnter write FOnItemAnchorEnter;
    property OnItemAnchorExit: TItemAnchorEvent read FOnItemAnchorExit write FOnItemAnchorExit;
    property OnItemControlEditStart: TItemControlEvent read FOnItemControlEditStart write FOnItemControlEditStart;
    property OnItemControlEditDone: TItemControlEvent read FOnItemControlEditDone write FOnItemControlEditDone;
    property OnItemControlComboList: TItemControlListEvent read FOnItemControlComboList write FOnItemControlComboList;
    property OnItemControlClick: TItemControlEvent read FOnItemControlClick write FOnItemControlClick;
    property OnItemControlComboSelect: TItemComboControlEvent read FOnItemControlComboSelect write FOnItemControlComboSelect;
    property OnItemClipboardAction: TItemClipboardEvent read FOnItemClipboardAction write FOnItemClipboardAction;
    property OnItemLeftClick: TItemEvent read FOnItemLeftClick write FOnItemLeftClick;
    property OnItemRightClick: TItemEvent read FOnItemRightClick write FOnItemRightClick;
    property OnItemDblClick: TItemEvent read FOnItemDblClick write FOnItemDblClick;
    property OnItemDrag: TItemDragEvent read FOnItemDrag write FOnItemDrag;
    property OnItemImageClick: TItemImageEvent read FOnItemImageClick write FOnItemImageClick;
    property OnItemURLClick: TItemLinkEvent read FOnItemURLClick write FOnItemURLClick;
    property OnItemAfterPaint: TItemPaintEvent read FOnItemAfterPaint write FOnItemAfterPaint;
    property OnItemAlarm: TItemEvent read FOnItemAlarm write FOnItemAlarm;
    property OnItemAttachementClick: TItemLinkEvent read FOnItemAttachementClick write FOnItemAttachementClick;
    property OnItemBalloon: TItemBalloonEvent read FOnItemBalloon write FOnItemBalloon;
    property OnItemSize: TItemSizeEvent read FOnItemSize write FOnItemSize;
    property OnItemMove: TItemMoveEvent read FOnItemMove write FOnItemMove;
    property OnItemSizing: TItemSizingEvent read FOnItemSizing write FOnItemSizing;
    property OnItemMoving: TItemMovingEvent read FOnItemMoving write FOnItemMoving;
    property OnItemDelete: TItemEvent read FOnItemDelete write FOnItemDelete;
    property OnItemDeleted: TItemEvent read FOnItemDeleted write FOnItemDeleted;
    property OnItemInsert: TPlannerEvent read FOnItemInsert write FOnItemInsert;
    property OnItemCreated: TItemEvent read FOnItemCreated write FOnItemCreated;
    property OnItemStartEdit: TItemEvent read FOnItemStartEdit write FOnItemStartEdit;
    property OnItemEndEdit: TItemEvent read FOnItemEndEdit write FOnItemEndEdit;
    property OnItemCanSelect: TItemDragEvent read FOnItemCanSelect write FOnItemCanSelect;
    property OnItemCompletionSettings: TItemGaugeEvent read FOnItemCompletionSettings write FOnItemCompletionSettings;
    property OnItemSelect: TItemEvent read FOnItemSelect write FOnItemSelect;
    property OnItemUnSelect: TItemEvent read FOnItemUnSelect write FOnItemUnSelect;
    property OnItemEnter: TItemEvent read FOnItemEnter write FOnItemEnter;
    property OnItemExit: TItemEvent read FOnItemExit write FOnItemExit;
    property OnItemHint: TItemHintEvent read FOnItemHint write FOnItemHint;
    property OnItemHintTime: TItemHintEvent read FOnItemHintTime write FOnItemHintTime;
    property OnItemSelChange: TItemEvent read FOnItemSelChange write FOnItemSelChange;
    property OnItemActivate: TItemEvent read FOnItemActivate write FOnItemActivate;
    property OnItemCut: TNotifyEvent read FOnItemCut write FOnItemCut;
    property OnItemCutting: TItemAllowEvent read FOnItemCutting write FOnItemCutting;
    property OnItemCopying: TItemAllowEvent read FOnItemCopying write FOnItemCopying;
    property OnItemCopied: TItemEvent read FOnItemCopied write FOnItemCopied;
    property OnItemPasting: TAllowEvent read FOnItemPasting write FOnItemPasting;
    property OnItemPasted: TItemEvent read FOnItemPasted write FOnItemPasted;
    property OnItemDeActivate: TItemEvent read FOnItemDeActivate write FOnItemDeActivate;
    property OnItemPlaceUpdate: TItemUpdateEvent read FOnItemPlaceUpdate write FOnItemPlaceUpdate;
    property OnItemPopupPrepare: TItemPopupPrepareEvent read FOnItemPopupPrepare write FOnItemPopupPrepare;
    property OnItemText: TPlannerItemText read FOnItemText write FOnItemText;
    property OnPlannerLeftClick: TPlannerEvent read FOnPlannerLeftClick write FOnPlannerLeftClick;
    property OnPlannerRightClick: TPlannerEvent read FOnPlannerRightClick write FOnPlannerRightClick;
    property OnPlannerDblClick: TPlannerEvent read FOnPlannerDblClick write FOnPlannerDblClick;
    property OnPlannerBeforeKeyDown: TKeyEvent read FOnPlannerBeforeKeyDown write FOnPlannerBeforeKeyDown;
    property OnPlannerKeyPress: TPlannerKeyEvent read FOnPlannerKeypress write FOnPlannerKeypress;
    property OnPlannerKeyDown: TPlannerKeyDownEvent read FOnPlannerKeyDown write FOnPlannerKeyDown;
    property OnPlannerKeyUp: TPlannerKeyDownEvent read FOnPlannerKeyUp write FOnPlannerKeyUp;
    property OnPlannerItemDraw: TPlannerItemDraw read FOnPlannerItemDraw write FOnPlannerItemDraw;
    property OnPlannerIsActive: TPlannerActiveEvent read FOnPlannerIsActive write FOnPlannerIsActive;
    property OnPlannerBottomLine: TPlannerBottomLineEvent read FOnPlannerBottomLine write FOnPlannerBottomLine;
    property OnPlannerRightLine: TPlannerBottomLineEvent read FOnPlannerRightLine write FOnPlannerRightLine;
    property OnPlannerSideDraw: TPlannerSideDraw read FOnPlannerSideDraw write FOnPlannerSideDraw;
    property OnPlannerSideDrawAfter: TPlannerSideDraw read FOnPlannerSideDrawAfter write FOnPlannerSideDrawAfter;
    property OnPlannerSideProp: TPlannerSideProp read FOnPlannerSideProp write FOnPlannerSideProp;
    property OnPlannerGetSideBarLines: TPlannerGetSideBarLines read FOnPlannerGetSideBarLines write FOnPlannerGetSideBarLines;
    property OnPlannerBkgDraw: TPlannerBkgDraw read FOnPlannerBkgDraw write FOnPlannerBkgDraw;
    property OnPlannerBkgProp: TPlannerBkgProp read FOnPlannerBkgProp write FOnPlannerBkgProp;
    property OnPlannerHeaderDraw: TPlannerHeaderDraw read FOnPlannerHeaderDraw write FOnPlannerHeaderDraw;
    property OnPlannerFooterDraw: TPlannerHeaderDraw read FOnPlannerFooterDraw write FOnPlannerFooterDraw;
    property OnPlannerCaptionDraw: TPlannerCaptionDraw read FOnPlannerCaptionDraw write FOnPlannerCaptionDraw;
    property OnPlannerNext: TPlannerBtnEvent read FOnPlannerNext write FOnPlannerNext;
    property OnPlannerPrev: TPlannerBtnEvent read FOnPlannerPrev write FOnPlannerPrev;
    property OnPlannerNextPosition: TPlannerBtnEvent read FOnPlannerNextPosition write FOnPlannerNextPosition;
    property OnPlannerPrevPosition: TPlannerBtnEvent read FOnPlannerPrevPosition write FOnPlannerPrevPosition;
    property OnPlannerSelChange: TPlannerEvent read FOnPlannerSelChange write FOnPlannerSelChange;
    property OnPlannerSelectCell: TPlannerSelectCellEvent read FOnPlannerSelectCell write FOnPlannerSelectCell;
    property OnPlannerMouseMove: TMouseMoveEvent read FOnPlannerMouseMove write FOnPlannerMouseMove;
    property OnPlannerMouseUp: TMouseEvent read FOnPlannerMouseUp write FOnPlannerMouseUp;
    property OnPlannerMouseDown: TMouseEvent read FOnPlannerMouseDown write FOnPlannerMouseDown;
    property OnPlannerMouseLeave: TNotifyEvent read FOnPlannerMouseLeave write FOnPlannerMouseLeave;
    property OnPlannerMouseEnter: TNotifyEvent read FOnPlannerMouseEnter write FOnPlannerMouseEnter;
    property OnPlannerPositionZoom: TPlannerPositionZoom read FOnPlannerPositionZoom write FOnPlannerPositionZoom;
    property OnPlannerBeforePositionZoom: TPlannerBeforePositionZoom read FOnPlannerBeforePositionZoom write FOnPlannerBeforePositionZoom;
    property OnPlannerUpdateCompletion: TNotifyEvent read FOnPlannerUpdateCompletion write FOnPlannerUpdateCompletion;
    property OnPlannerBalloon: TPlannerBalloonEvent read FOnPlannerBalloon write FOnPlannerBalloon;
    property OnFooterHint: THeaderHintEvent read FOnFooterHint write FOnFooterHint;
    property OnHeaderAnchorEnter: THeaderAnchorEvent read FOnHeaderAnchorEnter write FOnHeaderAnchorEnter;
    property OnHeaderAnchorLeave: THeaderAnchorEvent read FOnHeaderAnchorLeave write FOnHeaderAnchorLeave;
    property OnHeaderAnchorClick: THeaderAnchorEvent read FOnHeaderAnchorClick write FOnHeaderAnchorClick;
    property OnHeaderClick: THeaderClickEvent read FOnHeaderClick write FOnHeaderClick;
    property OnHeaderHeightChange: THeaderHeightChangeEvent read FOnHeaderHeightChange write FOnHeaderHeightChange;
    property OnHeaderHint: THeaderHintEvent read FOnHeaderHint write FOnHeaderHint;
    property OnHeaderRightClick: THeaderClickEvent read FOnHeaderRightClick write FOnHeaderRightClick;
    property OnHeaderDblClick: THeaderClickEvent read FOnHeaderDblClick write FOnHeaderDblClick;
    property OnHeaderDragDrop: THeaderDragDropEvent read FOnHeaderDragDrop write FOnHeaderDragDrop;
    property OnHeaderDraw: THeaderDrawEvent read FOnHeaderDraw write FOnHeaderDraw;
    property OnHeaderDrawProp: THeaderDrawPropEvent read FOnHeaderDrawProp write FOnHeaderDrawProp;
    property OnHeaderGroupDrawProp: THeaderDrawPropEvent read FOnHeaderGroupDrawProp write FOnHeaderGroupDrawProp;
    property OnHeaderStartEdit: THeaderEditEvent read FOnHeaderStartEdit write FOnHeaderStartEdit;
    property OnHeaderEndEdit: THeaderEditEvent read FOnHeaderEndEdit write FOnHeaderEndEdit;
    property OnHeaderSized: TPlannerHeaderSizeEvent read FOnHeaderSized write FOnHeaderSized;
    property OnPlanTimeToStrings: TPlannerPlanTimeToStrings read FOnPlanTimeToStrings write FOnPlanTimeToStrings;
    property OnPositionToDay: TPlannerPositionToDay read FOnPositionToDay write FOnPositionToDay;
    property OnSideBarClick: TSidebarClickEvent read FOnSideBarClick write FOnSideBarClick;
    property OnSideBarRightClick: TSidebarClickEvent read FOnSideBarRightClick write FOnSideBarRightClick;
    property OnSideBarDblClick: TSidebarClickEvent read FOnSideBarDblClick write FOnSideBarDblClick;
    property OnSideBarHint: TSidebarHintEvent read FOnSideBarHint write FOnSideBarHint;
    property OnTimer: TNotifyEvent read FOnTimer write FOnTimer;
    property OnTopLeftChanged: TPlannerBtnEvent read FOnTopLeftChanged write FOnTopLeftChanged;
    property OnPrintStart: TPlannerPrintEvent read FOnPrintStart write FOnPrintStart;
    property OnPrintHeader: TPlannerPrintHFEvent read FOnPrintHeader write FOnPrintHeader;
    property OnPrintFooter: TPlannerPrintHFEvent read FOnPrintFooter write FOnPrintFooter;
    property OnDragOver: TDragOverEvent read FOnDragOver write FOnDragOver;
    property OnDragOverCell: TDragOverEvent read FOnDragOverCell write FOnDragOverCell;
    property OnDragOverHeader: TDragOverHeaderEvent read FOnDragOverHeader write FOnDragOverHeader;
    property OnDragOverItem: TDragOverItemEvent read FOnDragOverItem write FOnDragOverItem;
    property OnDragDrop: TDragDropEvent read FOnDragDrop write FOnDragDrop;
    property OnDragDropCell: TDragDropEvent read FOnDragDropCell write FOnDragDropCell;
    property OnDragDropHeader: TDragDropHeaderEvent read FOnDragDropHeader write FOnDragDropHeader;
    property OnDragDropItem: TDragDropItemEvent read FOnDragDropItem write FOnDragDropItem;
    property OnGetCurrentTime: TGetCurrentTimeEvent read FOnGetCurrentTime write FOnGetCurrentTime;
    property OnCustomIndexToTime: TCustomITEvent read FOnCustomITEvent write FOnCustomITEvent;
    property OnCustomTimeToIndex: TCustomTIEvent read FOnCustomTIEvent write FOnCustomTIEvent;
  end;

  {$IFDEF DELPHIXE2_LVL}
  [ComponentPlatformsAttribute(pidWin32 or pidWin64)]
  {$ENDIF}
  TPlanner = class(TCustomPlanner)
  published
    { Published declarations }
    property ActiveDisplay;
    property Align;
    property AllowClipboardShortCuts;
    property AttachementGlyph;
    property AutoCreateOnSelect;
    property AutoPositionPrevNext;
    property AutoDeleteLinkedItems;
    property AutoSelectLinkedItems;
    property AutoInsDel;
    property Background;
    property AutoThemeAdapt;
    property Balloon;
    property Bands;
    property Anchors;
    property BiDiMode;
    property Constraints;
    property Caption;
    property Color;
    property CtrlDragCopy;
    property DayNames;
    property DefaultItem;
    property DeleteGlyph;
    property DirectMove;
    property DisjunctSelect;
    property DisjunctSelectColor;
    property Display;
    property DragItem;
    property DragItemAlways;
    property DragItemImage;
    property EditRTF;
    property EditDirect;
    property EditOnSelectedClick;
    property EditScroll;
    property EnableAlarms;
    property EnableFlashing;
    property EnableKeyboard;
    property FlashColor;
    property FlashFontColor;
    property Flat;
    property Font;
    property Footer;
    property GradientHorizontal;
    property GridPopup;
    property GridLeftCol;
    property GridLineColor;
    property GridTopRow;
    property GroupGapOnly;
    property Header;
    property HintColor;
    property HintPause;
    property HintOnItemChange;
    property HourType;
    property HTMLHint;
    property HTMLOptions;
    property InActiveDays;
    property IndicateNonVisibleItems;
    property InplaceEdit;
    property InsertAlways;
    property ItemChecker;
    property ItemGap;
    property ItemPopup;
    property Items;
    property ItemSelection;
    property Layer;
    property Mode;
    property MultiSelect;
    property NavigatorButtons;
    property NotesMaxLength;
    property SelectionAlways;
    property ShadowColor;
    property ShowHint;
    property Sidebar;
    property Overlap;
    property PictureContainer;
    property PlannerImages;
    property Positions;
    property PositionAutoSize;
    property PositionGap;
    property PositionGapColor;
    property PositionGroup;
    property PositionProps;
    property PositionWidth;
    property PositionZoomWidth;
    property PrintOptions;
    property ScrollBars;
    property ScrollSmooth;
    property ScrollSynch;
    property ScrollBarStyle;
    property SelectBackground;
    property SelectBlend;
    property SelectColor;
    property SelectOnRightClick;
    property SelectRange;
    property ShowDesignHelper;
    property ShowLinks;
    property ShowOccupiedInPositionGap;
    property ShowSelection;
    property StickySelect;
    property SyncPlanner;
{$IFDEF DELPHIXE_LVL}
    property Touch;
    property OnGesture;
{$ENDIF}
    property TrackBump;
    property TrackColor;
    property TrackOnly;
    property TrackProportional;
    property TrackWidth;
    property URLColor;
    property URLGlyph;
    property UserMode;
    property Version;
    property Visible;
    property WheelDelta;
    property WheelAction;
    property OnStartDrag;
    property OnEndDrag;
    property OnAfterPaint;
    property OnCaptionAnchorEnter;
    property OnCaptionAnchorExit;
    property OnCaptionAnchorClick;
    property OnCustomEdit;
    property OnCustomIndexToTime;
    property OnCustomTimeToIndex;
    property OnEnter;
    property OnExit;
    property OnItemAfterPaint;
    property OnItemAnchorClick;
    property OnItemAnchorEnter;
    property OnItemAnchorExit;
    property OnItemCut;
    property OnItemCutting;
    property OnItemCopied;
    property OnItemCopying;
    property OnItemPasted;
    property OnItemPasting;
    property OnItemControlEditStart;
    property OnItemControlEditDone;
    property OnItemControlComboList;
    property OnItemControlClick;
    property OnItemControlComboSelect;
    property OnItemClipboardAction;
    property OnItemLeftClick;
    property OnItemRightClick;
    property OnItemDblClick;
    property OnItemDrag;
    property OnItemImageClick;
    property OnItemURLClick;
    property OnItemAlarm;
    property OnItemAttachementClick;
    property OnItemBalloon;
    property OnItemCompletionSettings;
    property OnItemSize;
    property OnItemMove;
    property OnItemSizing;
    property OnItemMoving;
    property OnItemDelete;
    property OnItemDeleted;
    property OnItemInsert;
    property OnItemCreated;
    property OnItemStartEdit;
    property OnItemEndEdit;
    property OnItemCanSelect;
    property OnItemSelect;
    property OnItemEnter;
    property OnItemExit;
    property OnItemHint;
    property OnItemHintTime;
    property OnItemSelChange;
    property OnItemActivate;
    property OnItemDeActivate;
    property OnItemPlaceUpdate;
    property OnItemPopupPrepare;
    property OnItemText;
    property OnItemUnSelect;
    property OnPlannerLeftClick;
    property OnPlannerRightClick;
    property OnPlannerDblClick;
    property OnPlannerBeforeKeyDown;
    property OnPlannerKeyPress;
    property OnPlannerKeyDown;
    property OnPlannerKeyUp;
    property OnPlannerItemDraw;
    property OnPlannerBottomLine;
    property OnPlannerRightLine;
    property OnPlannerSideDraw;
    property OnPlannerSideDrawAfter;
    property OnPlannerSideProp;
    property OnPlannerGetSideBarLines;
    property OnPlannerBkgDraw;
    property OnPlannerBkgProp;
    property OnPlannerFooterDraw;
    property OnPlannerHeaderDraw;
    property OnPlannerCaptionDraw;
    property OnPlannerNext;
    property OnPlannerPrev;
    property OnPlannerNextPosition;
    property OnPlannerPrevPosition;
    property OnPlannerSelChange;
    property OnPlannerSelectCell;
    property OnPlannerMouseMove;
    property OnPlannerMouseUp;
    property OnPlannerMouseDown;
    property OnPlannerMouseLeave;
    property OnPlannerMouseEnter;
    property OnPlannerPositionZoom;
    property OnPlannerBeforePositionZoom;
    property OnPlannerUpdateCompletion;
    property OnPlanTimeToStrings;
    property OnPlannerBalloon;
    property OnPositionToDay;
    property OnFooterHint;
    property OnHeaderAnchorEnter;
    property OnHeaderAnchorLeave;
    property OnHeaderAnchorClick;
    property OnHeaderClick;
    property OnHeaderHeightChange;
    property OnHeaderHint;
    property OnHeaderRightClick;
    property OnHeaderDblClick;
    property OnHeaderDragDrop;
    property OnHeaderDrawProp;
    property OnHeaderGroupDrawProp;
    property OnHeaderDraw;
    property OnHeaderStartEdit;
    property OnHeaderEndEdit;
    property OnHeaderSized;
    property OnTopLeftChanged;
    property OnPrintStart;
    property OnPrintHeader;
    property OnPrintFooter;
    property OnDragOver;
    property OnDragOverCell;
    property OnDragOverHeader;
    property OnDragOverItem;
    property OnDragDrop;
    property OnDragDropCell;
    property OnDragDropHeader;
    property OnDragDropItem;
    property OnGetCurrentTime;
    property OnResize;
    property OnSideBarClick;
    property OnSideBarRightClick;
    property OnSideBarDblClick;
    property OnSideBarHint;
{$IFDEF TMSSKINS}
    property Skin;
{$ENDIF}
  end;

  TPlannerIO = class(TComponent)
    FItems: TPlannerItems;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
  published
    property Items: TPlannerItems read FItems write FItems;
  end;

  TPlannerItemIO = class(TComponent)
    FItem: TPlannerItem;
  public
    constructor CreateItem(AOwner: TPlannerItems);
    destructor Destroy; override;
  published
    property Item: TPlannerItem read FItem write FItem;
  end;

function PlannerGetIdCol(Planner: TCustomPlanner;
  Index, Position: Integer): string;

function PlannerGetTimeSlotText(Planner: TCustomPlanner;
  Index, Position: Integer): string;

{$R PLANNER.RES}

implementation

uses
  ClipBrd, RichEdit, IniFiles, ActnList, PlanHTML, ImgList
{$IFDEF DELPHI7_LVL}
  , DateUtils
{$ENDIF}
{$IFDEF DELPHIXE2_LVL}
  , VCL.Themes
{$ENDIF}
{$IFDEF TMSCODESITE}
  , CsIntf
{$ENDIF}
  ;

const
  ComCtrl = 'comctl32.dll';
  BtnWidth = 16;
  DaysPerWeek = 7;
  FirstDayOfWeek = 1;
  LastDayOfWeek = DaysPerWeek;

  ShortDaySun = 'Sun';
  ShortDayMon = 'Mon';
  ShortDayTue = 'Tue';
  ShortDayWed = 'Wed';
  ShortDayThu = 'Thu';
  ShortDayFri = 'Fri';
  ShortDaySat = 'Sat';

type
  PHeaderSection = ^THeaderSection;

  THeaderSection = record
    FObject: TObject;
    Width: Integer;
    Title: string;
  end;
{$I DELPHIXE.INC}

function Max(a, b: Integer): Integer;
begin
  if a > b then
    Result := a
  else
    Result := b;
end;

function Min(a, b: Integer): Integer;
begin
  if a < b then
    Result := a
  else
    Result := b;
end;

procedure SwapLR(var R: TRect);
var
  i: Integer;
begin
  i := R.Left;
  R.Left := R.Right;
  R.Right := i;
end;


procedure TCustomPlanner.AdaptItemsStyle;
var
  i: integer;
begin
  Items.BeginUpdate;
  for i := 0 to Items.Count - 1 do
  begin
    Items[i].Color := DefaultItem.Color;
    Items[i].ColorTo := DefaultItem.ColorTo;
    Items[i].ColorDirection := DefaultItem.ColorDirection;

    Items[i].SelectColor := DefaultItem.SelectColor;
    Items[i].SelectColorTo := DefaultItem.SelectColorTo;

    Items[i].CaptionBkg := DefaultItem.CaptionBkg;
    Items[i].CaptionBkgTo := DefaultItem.CaptionBkgTo;
    Items[i].CaptionBkgDirection := DefaultItem.CaptionBkgDirection;

    Items[i].SelectCaptionBkg := DefaultItem.SelectCaptionBkg;
    Items[i].SelectCaptionBkgTo := DefaultItem.SelectCaptionBkgTo;

    Items[i].TrackColor := DefaultItem.TrackColor;
    Items[i].TrackSelectColor := DefaultItem.TrackSelectColor;
  end;
  Items.EndUpdate;


end;

procedure TCustomPlanner.SetComponentStyle(AStyle: TTMSStyle);
begin
  FTMSStyle := AStyle;
  case AStyle of
    tsOffice2003Blue: SetStyle(2);
    tsOffice2003Olive: SetStyle(3);
    tsOffice2003Silver: SetStyle(4);
    tsOffice2003Classic: SetStyle(1);
    tsOffice2007Luna: SetStyle(8);
    tsOffice2007Obsidian: SetStyle(9);
    tsOffice2007Silver: SetStyle(10);
    tsWindowsXP: SetStyle(0);
    tsWhidbey: SetStyle(7);
    tsWindowsVista: SetStyle(11);
    tsWindows7: SetStyle(12);
    tsTerminal: SetStyle(13);
    tsOffice2010Blue: SetStyle(14);
    tsOffice2010Silver: SetStyle(15);
    tsOffice2010Black: SetStyle(16);
    tsWindows8: SetStyle(17);
    tsOffice2013White: SetStyle(18);
    tsOffice2013LightGray: SetStyle(19);
    tsOffice2013Gray: SetStyle(20);
    tsWindows10: SetStyle(21);
    tsOffice2016White: SetStyle(22);
    tsOffice2016Gray: SetStyle(23);
    tsOffice2016Black: SetStyle(24);
  end;
end;

procedure PlannerSetStyle(StyleIndex: Integer; Planner: TCustomPlanner);
begin
  Planner.Sidebar.OccupiedFontColor:= clBlack;
  case StyleIndex of
    // Windows XP
    0:
      begin
        Planner.Sidebar.ActiveColor := clNone;
        Planner.Sidebar.ActiveColorTo := clNone;
        Planner.Sidebar.Background := clBtnFace;
        Planner.Sidebar.BackgroundTo := clWhite;
        Planner.Sidebar.Occupied := clBlue;
        Planner.Sidebar.OccupiedTo := clWhite;
        Planner.Sidebar.SeparatorLineColor := clGray;
        Planner.Sidebar.LineColor := clGray;
        Planner.Sidebar.Flat := True;
        Planner.Sidebar.Font.Color := clBlack;
        Planner.Header.ActiveColor := clNone;
        Planner.Header.ActiveColorTo := clNone;
        Planner.Header.Color := clBtnFace;
        Planner.Header.ColorTo := clWhite;
        Planner.Header.Flat := False;
        Planner.Header.Font.Color := clBlack;
        Planner.Footer.Color := clBtnFace;
        Planner.Footer.ColorTo := clWhite;
        Planner.Display.ColorActive := clWhite;
        Planner.Display.ColorNonActive := $00DEDEDE;
        Planner.Caption.Background := clGray;
        Planner.Caption.BackgroundTo := clWhite;
        Planner.SelectColor := clHighlight;
        Planner.TrackColor := clBlue;
        Planner.GridLineColor := $00CECECE;
        Planner.Display.HourLineColor := clGray;
        Planner.Caption.Font.Color := clWhite;

        Planner.DefaultItem.ColorTo := $F7F7F7;
        Planner.DefaultItem.Color := clWhite;
        Planner.DefaultItem.SelectColorTo := clInfoBk;
        Planner.DefaultItem.SelectColor := clWhite;
        Planner.DefaultItem.CaptionBkgTo := clSilver;
        Planner.DefaultItem.CaptionBkg := clWhite;
        Planner.DefaultItem.TrackColor := clBlue;
        Planner.DefaultItem.TrackSelectColor := clBlue;
        Planner.DefaultItem.CaptionBkgDirection := gdHorizontal;
        Planner.DefaultItem.ColorDirection := gdVertical;

      end;
    // Office 2002
    1:
      begin
        Planner.Sidebar.ActiveColor := clNone;
        Planner.Sidebar.ActiveColorTo := clNone;
        Planner.Sidebar.Background := clBtnFace;
        Planner.Sidebar.BackgroundTo := clNone;
        Planner.Sidebar.Occupied := clBlue;
        Planner.Sidebar.OccupiedTo := clNone;
        Planner.Sidebar.SeparatorLineColor := clGray;
        Planner.Sidebar.LineColor := clGray;
        Planner.Sidebar.Flat := True;
        Planner.Sidebar.Font.Color := clBlack;
        Planner.Header.ActiveColor := clNone;
        Planner.Header.ActiveColorTo := clNone;
        Planner.Header.Color := clBtnFace;
        Planner.Header.ColorTo := clNone;
        Planner.Header.Flat := False;
        Planner.Header.Font.Color := clBlack;
        Planner.Footer.Color := clBtnFace;
        Planner.Footer.ColorTo := clNone;
        Planner.Display.ColorActive := $80FFFF;
        Planner.Display.ColorNonActive := $40C0C0;
        Planner.Caption.Background := clGray;
        Planner.Caption.BackgroundTo := clNone;
        Planner.SelectColor := clHighlight;
        Planner.TrackColor := clBlue;

        Planner.DefaultItem.ColorTo := $F7F7F7;
        Planner.DefaultItem.Color := clWhite;
        Planner.DefaultItem.SelectColorTo := clInfoBk;
        Planner.DefaultItem.SelectColor := clWhite;
        Planner.DefaultItem.CaptionBkgTo := clSilver;
        Planner.DefaultItem.CaptionBkg := clWhite;
        Planner.DefaultItem.TrackColor := clBlue;
        Planner.DefaultItem.TrackSelectColor := clBlue;
        Planner.DefaultItem.CaptionBkgDirection := gdHorizontal;
        Planner.DefaultItem.ColorDirection := gdVertical;

      end;
    // Office 2003 (blue)
    2:
      begin
        Planner.Sidebar.ActiveColor := $D8E9EC;
        Planner.Sidebar.ActiveColorTo := $5DCBF9;
        Planner.Sidebar.Background := $FCEAD9;
        Planner.Sidebar.BackgroundTo := $E4A47C;
        Planner.Sidebar.Occupied := $81CCF9;
        Planner.Sidebar.OccupiedTo := $5EB3FA;
        Planner.Sidebar.SeparatorLineColor := clGray;
        Planner.Sidebar.LineColor := clGray;
        Planner.Sidebar.Flat := True;
        Planner.Sidebar.Font.Color := clBlack;
        Planner.Header.ActiveColor := $D8E9EC;
        Planner.Header.ActiveColorTo := $5DCBF9;
        Planner.Header.Color := $FCEAD9;
        Planner.Header.ColorTo := $E4A47C;
        Planner.Header.Flat := False;
        Planner.Header.Font.Color := clBlack;
        Planner.Footer.Color := $FCEAD9;
        Planner.Footer.ColorTo := $E4A47C;
        Planner.Display.ColorActive := $D0FCFD;
        Planner.Display.ColorNonActive := $B8F5FF;
        Planner.Caption.Background := $D58456;
        Planner.Caption.BackgroundTo := $943C07;
        Planner.SelectColor := clHighlight;
        Planner.TrackColor := clBlue;

        Planner.Caption.Font.Color := clWhite;

        Planner.GridLineColor := $B1E4F3;
        Planner.Display.HourLineColor := $98D0EA;

        Planner.DefaultItem.Color := $FCEAD9;
        Planner.DefaultItem.ColorTo := $E4A47C;
        Planner.DefaultItem.SelectColor := $81CCF9;
        Planner.DefaultItem.SelectColorTo := $5EB3FA;
        Planner.DefaultItem.CaptionBkg := $D58456;
        Planner.DefaultItem.CaptionBkgTo := $943C07;
        Planner.DefaultItem.TrackColor := clBlue;
        Planner.DefaultItem.TrackSelectColor := clBlue;
        Planner.DefaultItem.CaptionBkgDirection := gdHorizontal;
        Planner.DefaultItem.ColorDirection := gdVertical;

      end;
    // Office 2003 (olive)
    3:
      begin
        Planner.Sidebar.ActiveColor := $D8E9EC;
        Planner.Sidebar.ActiveColorTo := $5DCBF9;
        Planner.Sidebar.Background := $CFF0EA;
        Planner.Sidebar.BackgroundTo := $8CC0B1;
        Planner.Sidebar.Occupied := $087FE8;
        Planner.Sidebar.OccupiedTo := $7CDAF7;
        Planner.Sidebar.SeparatorLineColor := clOlive;
        Planner.Sidebar.LineColor := clOlive;
        Planner.Sidebar.Flat := True;
        Planner.Sidebar.Font.Color := clBlack;
        Planner.Header.ActiveColor := $D8E9EC;
        Planner.Header.ActiveColorTo := $5DCBF9;
        Planner.Header.Color := $CFF0EA;
        Planner.Header.ColorTo := $8CC0B1;
        Planner.Header.Flat := False;
        Planner.Header.Font.Color := clBlack;
        Planner.Footer.Color := $CFF0EA;
        Planner.Footer.ColorTo := $8CC0B1;
        Planner.Display.ColorActive := $D0FCFD;
        Planner.Display.ColorNonActive := $B8F5FF;
        Planner.Caption.Background := $82C0AF;
        Planner.Caption.BackgroundTo := $447A63;
        Planner.SelectColor := clHighlight;
        Planner.TrackColor := clOlive;
        Planner.GridLineColor := $B1E4F3;
        Planner.Display.HourLineColor := $98D0EA;
        Planner.Caption.Font.Color := clWhite;
        Planner.DefaultItem.Color := $E4F1F2;
        Planner.DefaultItem.ColorTo := $AADADA;
        Planner.DefaultItem.SelectColor := $81CCF9;
        Planner.DefaultItem.SelectColorTo := $5EB3FA;
        //      Planner.DefaultItem.CaptionBkg := $D58456;
        //      Planner.DefaultItem.CaptionBkgTo := $943C07;
        Planner.DefaultItem.CaptionBkg := $82C0AF;
        Planner.DefaultItem.CaptionBkgTo := $447A63;
        Planner.DefaultItem.TrackColor := clBlue;
        Planner.DefaultItem.TrackSelectColor := clBlue;
        Planner.DefaultItem.CaptionBkgDirection := gdHorizontal;
        Planner.DefaultItem.ColorDirection := gdVertical;

      end;
    // Office 2003 (silver)
    4:
      begin
        Planner.Sidebar.ActiveColor := $D8E9EC;
        Planner.Sidebar.ActiveColorTo := $5DCBF9;
        Planner.Sidebar.Background := $ECE2E1;
        Planner.Sidebar.BackgroundTo := $B39698;
        Planner.Sidebar.Occupied := $81CCF9;
        Planner.Sidebar.OccupiedTo := $5EB3FA;
        Planner.Sidebar.SeparatorLineColor := clGray;
        Planner.Sidebar.LineColor := clGray;
        Planner.Sidebar.Flat := True;
        Planner.Sidebar.Font.Color := clBlack;
        Planner.Header.ActiveColor := $D8E9EC;
        Planner.Header.ActiveColorTo := $5DCBF9;
        Planner.Header.Color := $ECE2E1;
        Planner.Header.ColorTo := $B39698;
        Planner.Header.Flat := False;
        Planner.Header.Font.Color := clBlack;
        Planner.Footer.Color := $ECE2E1;
        Planner.Footer.ColorTo := $B39698;
        Planner.Display.ColorActive := $D0FCFD;
        Planner.Display.ColorNonActive := $B8F5FF;
        Planner.Caption.Background := $BDA4A5;
        Planner.Caption.BackgroundTo := $957475;
        Planner.SelectColor := clHighlight;
        Planner.TrackColor := clBlue;
        Planner.GridLineColor := $B1E4F3;
        Planner.Display.HourLineColor := $98D0EA;
        Planner.Caption.Font.Color := clWhite;
        Planner.DefaultItem.Color := $F7F3F3;
        Planner.DefaultItem.ColorTo := $E6D8D8;
        Planner.DefaultItem.SelectColor := $81CCF9;
        Planner.DefaultItem.SelectColorTo := $5EB3FA;
        // Planner.DefaultItem.CaptionBkg := $D58456;
        // Planner.DefaultItem.CaptionBkgTo := $943C07;
        Planner.DefaultItem.CaptionBkg := $BDA4A5;
        Planner.DefaultItem.CaptionBkgTo := $957475;
        Planner.DefaultItem.TrackColor := clBlue;
        Planner.DefaultItem.TrackSelectColor := clBlue;
        Planner.DefaultItem.CaptionBkgDirection := gdHorizontal;
        Planner.DefaultItem.ColorDirection := gdVertical;

      end;
    // Flat style
    5:
      begin
        Planner.Sidebar.ActiveColor := clNone;
        Planner.Sidebar.ActiveColorTo := clNone;
        Planner.Sidebar.Background := clBtnFace;
        Planner.Sidebar.BackgroundTo := clNone;
        Planner.Sidebar.Occupied := clBlue;
        Planner.Sidebar.OccupiedTo := clNone;
        Planner.Sidebar.SeparatorLineColor := clGray;
        Planner.Sidebar.LineColor := clGray;
        Planner.Sidebar.Flat := True;
        Planner.Sidebar.Font.Color := clBlack;
        Planner.Header.ActiveColor := clNone;
        Planner.Header.ActiveColorTo := clNone;
        Planner.Header.Color := clBtnFace;
        Planner.Header.ColorTo := clNone;
        Planner.Header.Flat := True;
        Planner.Header.Font.Color := clBlack;
        Planner.Footer.Color := clBtnFace;
        Planner.Footer.ColorTo := clNone;
        Planner.Display.ColorActive := clWhite;
        Planner.Display.ColorNonActive := clSilver;
        Planner.Caption.Background := clGray;
        Planner.Caption.BackgroundTo := clNone;
        Planner.SelectColor := clHighlight;
        Planner.TrackColor := clBlue;

        Planner.DefaultItem.ColorTo := $F7F7F7;
        Planner.DefaultItem.Color := clWhite;
        Planner.DefaultItem.SelectColorTo := clInfoBk;
        Planner.DefaultItem.SelectColor := clWhite;
        Planner.DefaultItem.CaptionBkgTo := clSilver;
        Planner.DefaultItem.CaptionBkg := clWhite;
        Planner.DefaultItem.TrackColor := clBlue;
        Planner.DefaultItem.TrackSelectColor := clBlue;
        Planner.DefaultItem.CaptionBkgDirection := gdHorizontal;
        Planner.DefaultItem.ColorDirection := gdVertical;

      end;
    // Avant garde
    6:
      begin
        Planner.Sidebar.ActiveColor := clNone;
        Planner.Sidebar.ActiveColorTo := clNone;
        Planner.Sidebar.Background := $006580DA;
        Planner.Sidebar.BackgroundTo := $00F807F1;
        Planner.Sidebar.Occupied := clBlue;
        Planner.Sidebar.OccupiedTo := clNone;
        Planner.Sidebar.SeparatorLineColor := clGray;
        Planner.Sidebar.LineColor := clWhite;
        Planner.Sidebar.Font.Color := clWhite;
        Planner.Sidebar.Flat := True;
        Planner.Header.ActiveColor := clNone;
        Planner.Header.ActiveColorTo := clNone;
        Planner.Header.Color := $006580DA;
        Planner.Header.ColorTo := $00F807F1;
        Planner.Header.Flat := True;
        Planner.Footer.Color := clBtnFace;
        Planner.Footer.ColorTo := clNone;
        Planner.Display.ColorActive := $00FFD9B3;
        Planner.Display.ColorNonActive := $00F8898E;
        Planner.Caption.Background := $00804000;
        Planner.Caption.BackgroundTo := $00F8898E;
        Planner.SelectColor := clHighlight;
        Planner.TrackColor := clWhite;

        Planner.DefaultItem.ColorTo := $00FFD9B3;
        Planner.DefaultItem.Color := $00DEF9B9;
        Planner.DefaultItem.SelectColorTo := clInfoBk;
        Planner.DefaultItem.SelectColor := clWhite;
        Planner.DefaultItem.CaptionBkgTo := $006580DA;
        Planner.DefaultItem.CaptionBkg := $00F807F1;
        Planner.DefaultItem.TrackColor := clWhite;
        Planner.DefaultItem.TrackSelectColor := clWhite;
        Planner.DefaultItem.CaptionBkgDirection := gdHorizontal;
        Planner.DefaultItem.ColorDirection := gdVertical;

      end;
    // Whidbey
    7:
      begin
        Planner.Sidebar.ActiveColor := $D8E9EC;
        Planner.Sidebar.ActiveColorTo := $5DCBF9;
        Planner.Sidebar.Background := $00F5F9FA;
        Planner.Sidebar.BackgroundTo := $00A8C0C0;
        Planner.Sidebar.Occupied := $81CCF9;
        Planner.Sidebar.OccupiedTo := $5EB3FA;

        Planner.Sidebar.SeparatorLineColor := clGray;
        Planner.Sidebar.LineColor := clGray;
        Planner.Sidebar.Flat := True;
        Planner.Sidebar.Font.Color := clBlack;
        Planner.Header.ActiveColor := $D8E9EC;
        Planner.Header.ActiveColorTo := $5DCBF9;
        Planner.Header.Color := $00F5F9FA;
        Planner.Header.ColorTo := $00A8C0C0;
        Planner.Header.Flat := False;
        Planner.Header.Font.Color := clBlack;
        Planner.Footer.Color := $00F5F9FA;
        Planner.Footer.ColorTo := $00A8C0C0;

        Planner.Display.ColorActive := $D0FCFD;
        Planner.Display.ColorNonActive := $B8F5FF;

        //Planner.Caption.Background := $BDA4A5;
        //Planner.Caption.BackgroundTo := $957475;

        Planner.Caption.Background := $EBEEEF;
        Planner.Caption.BackgroundTo := $7E9898;

        Planner.SelectColor := clHighlight;
        Planner.TrackColor := clBlue;
        Planner.GridLineColor := $B1E4F3;
        Planner.Display.HourLineColor := $98D0EA;
        Planner.Caption.Font.Color := clWhite;
        Planner.DefaultItem.Color := $00F5F9FA;
        Planner.DefaultItem.ColorTo := $00A8C0C0;

        Planner.DefaultItem.SelectColor := $81CCF9;
        Planner.DefaultItem.SelectColorTo := $5EB3FA;
        //Planner.DefaultItem.CaptionBkg := $D58456;
        //Planner.DefaultItem.CaptionBkgTo := $943C07;
        Planner.DefaultItem.CaptionBkg := $BDA4A5;
        Planner.DefaultItem.CaptionBkgTo := $957475;
        Planner.DefaultItem.TrackColor := clBlue;
        Planner.DefaultItem.TrackSelectColor := clBlue;
        Planner.DefaultItem.CaptionBkgDirection := gdHorizontal;
        Planner.DefaultItem.ColorDirection := gdVertical;

      end;
    // Office 2007 Luna
    8:
      begin
        Planner.Sidebar.ActiveColor := $9DD8F9;
        Planner.Sidebar.ActiveColorTo := $5EC1F1;
        Planner.Sidebar.Background := $F2E4D5; //$FBF9F6;//$FFEFE3;
        Planner.Sidebar.BackgroundTo := $F2E4D5; //$E8DBD2;//$FFD2AF;
        Planner.Sidebar.Occupied := $7CDAF7;
        Planner.Sidebar.OccupiedTo := $087FE8;
        Planner.Sidebar.SeparatorLineColor := $FFD2AF;
        Planner.Sidebar.LineColor := $CF9365;
        Planner.Sidebar.Flat := True;
        Planner.Sidebar.Font.Color := $CF9365;
        Planner.Header.ActiveColor := $9DD8F9;
        Planner.Header.ActiveColorTo := $5EC1F1;
        Planner.Header.Color := $F6ECE4; //$FBF9F6;//$FFEFE3;
        Planner.Header.ColorTo := $EBD4C2; //$E8DBD2;//$FFD2AF;
        Planner.Header.Flat := False;
        Planner.Header.Font.Color := clBlack;
        Planner.Header.ItemColor := $E1BFA5;
        Planner.Header.LineColor := $CF9365;

        Planner.Footer.Color := $F6ECE4; //$FBF9F6;//$FFEFE3;
        Planner.Footer.ColorTo := $EBD4C2; //$E8DBD2;//$FFD2AF;
        Planner.Display.ColorActive := clWhite;
        Planner.Display.ColorNonActive := $F7EDE6;
        Planner.Caption.Background := $FFEFE3;
        Planner.Caption.BackgroundTo := $FFD2AF;
        Planner.Caption.GradientDirection := gdVertical;

        Planner.Caption.Font.Color := $723708;

        Planner.SelectColor := $7A4C29;
        Planner.TrackColor := clBlue;

        Planner.GridLineColor := $F1E1D5;
        Planner.Display.HourLineColor := $E1BFA5;
        Planner.ShadowColor := $DFDFDF;

        Planner.DefaultItem.Color := clWhite;
        Planner.DefaultItem.ColorTo := $EAD3C1;
        Planner.DefaultItem.SelectColor := $BBEEFF;
        Planner.DefaultItem.SelectColorTo := $78DAFF;
        Planner.DefaultItem.CaptionBkg := $FFEFE3;
        Planner.DefaultItem.CaptionBkgTo := $FFD2AF;
        Planner.DefaultItem.TrackColor := $AD7C56;
        Planner.DefaultItem.BorderColor := $AD7C56;
        Planner.DefaultItem.TrackSelectColor := clBlack;
        Planner.DefaultItem.CaptionBkgDirection := gdHorizontal;
        Planner.DefaultItem.ColorDirection := gdVertical;

      end;
    // Office 2007 Obsidian
    9:
      begin
        Planner.Sidebar.ActiveColor := $9DD8F9;
        Planner.Sidebar.ActiveColorTo := $5EC1F1;
        Planner.Sidebar.Background := $EBEBEB; //$F7F7F7;//$F2F1F0;
        Planner.Sidebar.BackgroundTo := $EBEBEB; //$DEDEDE;//$C9C2BD;
        Planner.Sidebar.Occupied := $7CDAF7;
        Planner.Sidebar.OccupiedTo := $087FE8;
        Planner.Sidebar.SeparatorLineColor := $5C534C;
        Planner.Sidebar.LineColor := $5C534C;
        Planner.Sidebar.Flat := True;
        Planner.Sidebar.Font.Color := $5C534C;

        Planner.Header.ActiveColor := $9DD8F9;
        Planner.Header.ActiveColorTo := $5EC1F1;
        Planner.Header.Color := $F6ECE4; //$F7F7F7;//$F2F1F0;
        Planner.Header.ColorTo := $EBD4C2; //$DEDEDE;//$C9C2BD;
        Planner.Header.Flat := False;
        Planner.Header.Font.Color := $5C534C;
        Planner.Header.ItemColor := $E1BFA5;
        Planner.Header.LineColor := $CF9365;

        Planner.Footer.Color := $F6ECE4; //$F7F7F7;//$F2F1F0;
        Planner.Footer.ColorTo := $EBD4C2; //$DEDEDE;//$C9C2BD;
        Planner.Display.ColorActive := clWhite;
        Planner.Display.ColorNonActive := $F7EDE6;
        Planner.Caption.Background := $F2F1F0;
        Planner.Caption.BackgroundTo := $C9C2BD;
        Planner.Caption.GradientDirection := gdVertical;
        Planner.Caption.Font.Color := clBlack;

        Planner.SelectColor := $7A4C29;
        Planner.TrackColor := clBlue;

        Planner.GridLineColor := $F1E1D5;
        Planner.Display.HourLineColor := $E1BFA5;
        Planner.ShadowColor := $DFDFDF;

        Planner.DefaultItem.Color := clWhite;
        Planner.DefaultItem.ColorTo := $EAD3C1;
        Planner.DefaultItem.SelectColor := $BBEEFF;
        Planner.DefaultItem.SelectColorTo := $78DAFF;
        Planner.DefaultItem.CaptionBkg := $F2F1F0;
        Planner.DefaultItem.CaptionBkgTo := $C9C2BD;
        Planner.DefaultItem.TrackColor := $AD7C56;
        Planner.DefaultItem.BorderColor := $AD7C56;
        Planner.DefaultItem.TrackSelectColor := clBlack;
        Planner.DefaultItem.CaptionBkgDirection := gdHorizontal;
        Planner.DefaultItem.ColorDirection := gdVertical;

      end;
    // Office 2007 Silver
    10:
      begin
        Planner.Sidebar.ActiveColor := $9DD8F9;
        Planner.Sidebar.ActiveColorTo := $5EC1F1;
        Planner.Sidebar.Background := $F2F1F0;
        Planner.Sidebar.BackgroundTo := $F2F1F0;
        Planner.Sidebar.Occupied := $7CDAF7;
        Planner.Sidebar.OccupiedTo := $087FE8;
        Planner.Sidebar.SeparatorLineColor := $FFD2AF;
        Planner.Sidebar.LineColor := $74706F;
        Planner.Sidebar.Flat := True;
        Planner.Sidebar.Font.Color := $74706F;

        Planner.Header.ActiveColor := $9DD8F9;
        Planner.Header.ActiveColorTo := $5EC1F1;
        Planner.Header.Color := $F8F7F6;
        Planner.Header.ColorTo := $E7DFDA;
        Planner.Header.Flat := False;
        Planner.Header.Font.Color := clBlack;
        Planner.Header.ItemColor := clSilver;
        Planner.Header.LineColor := clSilver;

        Planner.Footer.Color := Planner.Header.Color;
        Planner.Footer.ColorTo := Planner.Header.ColorTo;

        Planner.Display.ColorActive := clWhite;
        Planner.Display.ColorNonActive := $ECEAE8;
        Planner.Caption.Background := $FAEEEB;
        Planner.Caption.BackgroundTo := $D3C9C7;
        Planner.Caption.GradientDirection := gdVertical;
        Planner.Caption.Font.Color := clBlack;

        Planner.SelectColor := $5C534C;
        Planner.TrackColor := clBlue;
        Planner.GridLineColor := $A49991;
        Planner.Display.HourLineColor := $D1CBC7;
        Planner.ShadowColor := $DFDFDF;

        Planner.DefaultItem.Color := clWhite;
        Planner.DefaultItem.ColorTo := $DBD7D4;
        Planner.DefaultItem.SelectColor := $BBEEFF;
        Planner.DefaultItem.SelectColorTo := $78DAFF;
        Planner.DefaultItem.CaptionBkg := $FAEEEB;
        Planner.DefaultItem.CaptionBkgTo := $D3C9C7;
        Planner.DefaultItem.TrackColor := $A49991;
        Planner.DefaultItem.BorderColor := clBlack;
        Planner.DefaultItem.TrackSelectColor := clBlack;
        Planner.DefaultItem.CaptionBkgDirection := gdHorizontal;
        Planner.DefaultItem.ColorDirection := gdVertical;

      end;
    // WindowsVista
    11:
      begin
        Planner.Sidebar.ActiveColor := $FEF9F0;
        Planner.Sidebar.ActiveColorTo := $FDF0D7;
        Planner.Sidebar.Background := $FFFDF9;
        Planner.Sidebar.BackgroundTo := $FFFAF0;
        Planner.Sidebar.Occupied := $FFFFFF;
        Planner.Sidebar.OccupiedTo := $FFFFFF;
        Planner.Sidebar.SeparatorLineColor := $FDDE99;
        Planner.Sidebar.LineColor := $FDDE99;
        Planner.Sidebar.Flat := True;
        Planner.Sidebar.Font.Color := clBlack;
        Planner.Header.ActiveColor := $FEF9F0;
        Planner.Header.ActiveColorTo := $FDF0D7;
        Planner.Header.Color := $FFFDF9;
        Planner.Header.ColorTo := $FFFAF0;
        Planner.Header.Flat := False;
        Planner.Header.Font.Color := clBlack;
        Planner.Footer.Color := $FFFDF9;
        Planner.Footer.ColorTo := $FFFAF0;
        Planner.Display.ColorActive := $FDF8F1;
        Planner.Display.ColorNonActive := $FFFFFF;
        Planner.Caption.Background := $FDF8F1;
        Planner.Caption.BackgroundTo := $FCEFD5;
        Planner.SelectColor := $F5D089;
        Planner.TrackColor := $FCEFD5;
        Planner.GridLineColor := $FCF2DA;
        Planner.Display.HourLineColor := $FEDF9A;
        Planner.Caption.Font.Color := clBlack;

        Planner.DefaultItem.ColorTo := $FFFFFF;
        Planner.DefaultItem.Color := $FFFFFF;
        Planner.DefaultItem.SelectColorTo := $FDF0D7;
        Planner.DefaultItem.SelectColor := $FEF9F0;
        Planner.DefaultItem.CaptionBkgTo := $F5D089;
        Planner.DefaultItem.CaptionBkg := $F5D089;
        Planner.DefaultItem.TrackColor := $FCEFD5;
        Planner.DefaultItem.TrackSelectColor := $00AD7C56;
        Planner.DefaultItem.CaptionBkgDirection := gdHorizontal;
        Planner.DefaultItem.ColorDirection := gdVertical;

      end;
    // Windows7
    12:
      begin
        Planner.Sidebar.ActiveColor := $FCEBDC;
        Planner.Sidebar.ActiveColorTo := $FCDBC1;
        Planner.Sidebar.Background := $FDFBFA;
        Planner.Sidebar.BackgroundTo := $FDF3EB;
        Planner.Sidebar.Occupied := $FFFFFF;
        Planner.Sidebar.OccupiedTo := $FFFFFF;
        Planner.Sidebar.SeparatorLineColor := $CEA27D;
        Planner.Sidebar.LineColor := $CEA27D;
        Planner.Sidebar.Flat := True;
        Planner.Sidebar.Font.Color := clBlack;
        Planner.Header.ActiveColor := $FCEBDC;
        Planner.Header.ActiveColorTo := $FCDBC1;
        Planner.Header.Color := $FDFBFA;
        Planner.Header.ColorTo := $FDF3EB;
        Planner.Header.Flat := False;
        Planner.Header.Font.Color := clBlack;
        Planner.Footer.Color := $FDFBFA;
        Planner.Footer.ColorTo := $FDF3EB;
        Planner.Display.ColorActive := $FCEBDC;
        Planner.Display.ColorNonActive := $FFFFFF;
        Planner.Caption.Background := $FCEBDC;
        Planner.Caption.BackgroundTo := $FCDBC1;
        Planner.SelectColor := $F5D089;
        Planner.TrackColor := $FCDBC1;
        Planner.GridLineColor := $FBD6B8;
        Planner.Display.HourLineColor := $CEA27D;
        Planner.Caption.Font.Color := clBlack;

        Planner.DefaultItem.ColorTo := $FFFFFF;
        Planner.DefaultItem.Color := $FFFFFF;
        Planner.DefaultItem.SelectColorTo := $FCEBDC;
        Planner.DefaultItem.SelectColor := $FCDBC1;
        Planner.DefaultItem.CaptionBkgTo := $F5D089;
        Planner.DefaultItem.CaptionBkg := $F5D089;
        Planner.DefaultItem.TrackColor := $FCDBC1;
        Planner.DefaultItem.TrackSelectColor := $00AD7C56;
        Planner.DefaultItem.CaptionBkgDirection := gdHorizontal;
        Planner.DefaultItem.ColorDirection := gdVertical;

      end;
    // Terminal
    13:
      begin
        Planner.Sidebar.ActiveColor := clSilver;
        Planner.Sidebar.ActiveColorTo := clSilver;
        Planner.Sidebar.Background := clBtnFace;
        Planner.Sidebar.BackgroundTo := clBtnFace;
        Planner.Sidebar.Occupied := clWhite;
        Planner.Sidebar.OccupiedTo := clWhite;
        Planner.Sidebar.SeparatorLineColor := clGray;
        Planner.Sidebar.LineColor := clGray;
        Planner.Sidebar.Flat := True;
        Planner.Sidebar.Font.Color := clBlack;
        Planner.Header.ActiveColor := clSilver;
        Planner.Header.ActiveColorTo := clSilver;
        Planner.Header.Color := clBtnFace;
        Planner.Header.ColorTo := clBtnFace;
        Planner.Header.Flat := False;
        Planner.Header.Font.Color := clBlack;
        Planner.Footer.Color := clBtnFace;
        Planner.Footer.ColorTo := clBtnFace;
        Planner.Display.ColorActive := clWhite;
        Planner.Display.ColorNonActive := clBtnFace;
        Planner.Caption.Background := clGray;
        Planner.Caption.BackgroundTo := clGray;
        Planner.SelectColor := clHighlight;
        Planner.TrackColor := clHighlight;
        Planner.GridLineColor := clSilver;
        Planner.Display.HourLineColor := clGray;
        Planner.Caption.Font.Color := clWhite;

        Planner.DefaultItem.ColorTo := clWhite;
        Planner.DefaultItem.Color := clWhite;
        Planner.DefaultItem.SelectColorTo := clBtnFace;
        Planner.DefaultItem.SelectColor := clBtnFace;
        Planner.DefaultItem.CaptionBkgTo := clBtnFace;
        Planner.DefaultItem.CaptionBkg := clBtnFace;
        Planner.DefaultItem.TrackColor := clHighlight;
        Planner.DefaultItem.TrackSelectColor := clGray;
        Planner.DefaultItem.CaptionBkgDirection := gdHorizontal;
        Planner.DefaultItem.ColorDirection := gdVertical;

      end;
    // Office2010Blue
    14:
      begin
        Planner.Sidebar.ActiveColor := $7BEEFF;
        Planner.Sidebar.ActiveColorTo := $6BD8FF;
        Planner.Sidebar.Background := clWhite;
        Planner.Sidebar.BackgroundTo := clWhite;
        Planner.Sidebar.Occupied := $6CD0FF;
        Planner.Sidebar.OccupiedTo := $6CD0FF;
        Planner.Sidebar.SeparatorLineColor := $BD9D84;
        Planner.Sidebar.LineColor := $BD9D84;
        Planner.Sidebar.Flat := True;
        Planner.Sidebar.Font.Color := $5B391E;
        Planner.Header.ActiveColor := $7BEEFF;
        Planner.Header.ActiveColorTo := $6BD8FF;
        Planner.Header.Color := $E1BFA5;
        Planner.Header.ColorTo := $E1BFA5;
        Planner.Header.Flat := False;
        Planner.Header.Font.Color := $5B391E;
        Planner.Footer.Color := $E1BFA5;
        Planner.Footer.ColorTo := $E1BFA5;
        Planner.Display.ColorActive := clWhite;
        Planner.Display.ColorNonActive := $F7EDE6;
        Planner.Caption.Background := $FDF6EF;
        Planner.Caption.BackgroundTo := $F0DAC7;
        Planner.SelectColor := $7A4C29;
        Planner.TrackColor := $6BD8FF;
        Planner.GridLineColor := $F1E1D5;
        Planner.Display.HourLineColor := $E1BFA5;
        Planner.Caption.Font.Color := $5B391E;

        Planner.DefaultItem.ColorTo := $E6CAB5;
        Planner.DefaultItem.Color := $F6E8DF;
        Planner.DefaultItem.SelectColorTo := $E6CAB5;
        Planner.DefaultItem.SelectColor := $F6E8DF;
        Planner.DefaultItem.CaptionBkgTo := $F0DAC7;
        Planner.DefaultItem.CaptionBkg := $FDF6EF;
        Planner.DefaultItem.TrackColor := clBlack;
        Planner.DefaultItem.TrackSelectColor := clBlack;
        Planner.DefaultItem.CaptionBkgDirection := gdHorizontal;
        Planner.DefaultItem.ColorDirection := gdVertical;

      end;
    // Office2010Silver
    15:
      begin
        Planner.Sidebar.ActiveColor := $7BEEFF;
        Planner.Sidebar.ActiveColorTo := $6BD8FF;
        Planner.Sidebar.Background := clWhite;
        Planner.Sidebar.BackgroundTo := clWhite;
        Planner.Sidebar.Occupied := $6CD0FF;
        Planner.Sidebar.OccupiedTo := $6CD0FF;
        Planner.Sidebar.SeparatorLineColor := $B8B0A9;
        Planner.Sidebar.LineColor := $B8B0A9;
        Planner.Sidebar.Flat := True;
        Planner.Sidebar.Font.Color := $3B3B3B;
        Planner.Header.ActiveColor := $7BEEFF;
        Planner.Header.ActiveColorTo := $6BD8FF;
        Planner.Header.Color := $EFDBCE;
        Planner.Header.ColorTo := $EFDBCE;
        Planner.Header.Flat := False;
        Planner.Header.Font.Color := $3B3B3B;
        Planner.Footer.Color := $EFDBCE;
        Planner.Footer.ColorTo := $EFDBCE;
        Planner.Display.ColorActive := clWhite;
        Planner.Display.ColorNonActive := $F7EDE6;
        Planner.Caption.Background := $FFFFFF;
        Planner.Caption.BackgroundTo := $EDE5E0;
        Planner.SelectColor := $5C534C;
        Planner.TrackColor := $6BD8FF;
        Planner.GridLineColor := $ECE0D8;
        Planner.Display.HourLineColor := $E1BFA5;
        Planner.Caption.Font.Color := $3B3B3B;

        Planner.DefaultItem.ColorTo := $D1CBC6;
        Planner.DefaultItem.Color := $E8E8E8;
        Planner.DefaultItem.SelectColorTo := $D1CBC6;
        Planner.DefaultItem.SelectColor := $E8E8E8;
        Planner.DefaultItem.CaptionBkgTo := $EDE5E0;
        Planner.DefaultItem.CaptionBkg := $FFFFFF;
        Planner.DefaultItem.TrackColor := clBlack;
        Planner.DefaultItem.TrackSelectColor := clBlack;
        Planner.DefaultItem.CaptionBkgDirection := gdHorizontal;
        Planner.DefaultItem.ColorDirection := gdVertical;

      end;
    // Office2010Black
    16:
      begin
        Planner.Sidebar.ActiveColor := $7BEEFF;
        Planner.Sidebar.ActiveColorTo := $6BD8FF;
        Planner.Sidebar.Background := clWhite;
        Planner.Sidebar.BackgroundTo := clWhite;
        Planner.Sidebar.Occupied := $6CD0FF;
        Planner.Sidebar.OccupiedTo := $6CD0FF;
        Planner.Sidebar.SeparatorLineColor := $B8B8B8;
        Planner.Sidebar.LineColor := $B8B8B8;
        Planner.Sidebar.Flat := True;
        Planner.Sidebar.Font.Color := clBlack;
        Planner.Header.ActiveColor := $7BEEFF;
        Planner.Header.ActiveColorTo := $6BD8FF;
        Planner.Header.Color := $EFDBCE;
        Planner.Header.ColorTo := $EFDBCE;
        Planner.Header.Flat := False;
        Planner.Header.Font.Color := clBlack;
        Planner.Footer.Color := $EFDBCE;
        Planner.Footer.ColorTo := $EFDBCE;
        Planner.Display.ColorActive := clWhite;
        Planner.Display.ColorNonActive := $F7EDE6;
        Planner.Caption.Background := $BFBFBF;
        Planner.Caption.BackgroundTo := $919191;
        Planner.SelectColor := $5C534C;
        Planner.TrackColor := $6BD8FF;
        Planner.GridLineColor := $ECE0D8;
        Planner.Display.HourLineColor := $E1BFA5;
        Planner.Caption.Font.Color := clWhite;

        Planner.DefaultItem.ColorTo := $D2CCC7;
        Planner.DefaultItem.Color := $E7E7E7;
        Planner.DefaultItem.SelectColorTo := $D2CCC7;
        Planner.DefaultItem.SelectColor := $E7E7E7;
        Planner.DefaultItem.CaptionBkgTo := $919191;
        Planner.DefaultItem.CaptionBkg := $BFBFBF;
        Planner.DefaultItem.TrackColor := clBlack;
        Planner.DefaultItem.TrackSelectColor := clBlack;
        Planner.DefaultItem.CaptionBkgDirection := gdHorizontal;
        Planner.DefaultItem.ColorDirection := gdVertical;

      end;
    // Windows8
    17:
      begin
        Planner.Sidebar.ActiveColor := clNone;
        Planner.Sidebar.ActiveColorTo := clNone;
        Planner.Sidebar.Background := $F7F6F5;
        Planner.Sidebar.BackgroundTo := $F7F6F5;
        Planner.Sidebar.Occupied := $F7E0C9;
        Planner.Sidebar.OccupiedTo := $F7E0C9;
        Planner.Sidebar.SeparatorLineColor := $DCDBDA;
        Planner.Sidebar.LineColor := $DCDBDA;
        Planner.Sidebar.Flat := true;
        Planner.Sidebar.Border := true;
        Planner.Sidebar.Font.Color := clBlack;
        Planner.Header.ActiveColor := clNone;
        Planner.Header.ActiveColorTo := clNone;
        Planner.Header.Color := $F7F6F5;
        Planner.Header.ColorTo := $F7F6F5;
        Planner.Header.Flat := false;
        Planner.Header.Font.Color := clBlack;
        Planner.Header.LineColor := $DCDBDA;
        Planner.Footer.LineColor := $DCDBDA;
        Planner.Footer.Flat := true;
        Planner.Footer.Color := $F7F6F5;
        Planner.Footer.ColorTo := $F7F6F5;
        Planner.Display.ColorActive := clWhite;
        Planner.Display.ColorNonActive := $EEEEEE;
        Planner.Caption.Background := $DCDBDA;
        Planner.Caption.BackgroundTo := $DCDBDA;
        Planner.Caption.Font.Color := clBlack;
        Planner.SelectColor := $DAA026;
        Planner.TrackColor := $DCDBDA; //caption background
        Planner.GridLineColor := $DCDBDA;
        Planner.Display.HourLineColor := $DCDBDA;


        Planner.DefaultItem.ColorTo := clWhite;
        Planner.DefaultItem.Color := clWhite;
        Planner.DefaultItem.BorderColor :=  $DCDBDA;
        Planner.DefaultItem.SelectColorTo := $F7E0C9;
        Planner.DefaultItem.SelectColor := $F7E0C9;
        Planner.DefaultItem.CaptionBkgTo := $EEEEEE; //caption panel
        Planner.DefaultItem.CaptionBkg := $EEEEEE;
        Planner.DefaultItem.TrackColor := $F9CEA4; //bordercolorhover glowbtn
        Planner.DefaultItem.TrackSelectColor := $E4A262; //bordercolordown glowbtn
        Planner.DefaultItem.CaptionBkgDirection := gdHorizontal;
        Planner.DefaultItem.ColorDirection := gdVertical;

        Planner.DefaultItem.Shadow := false;
        Planner.DefaultItem.SelectFontColor := clBlack;
      end;
    // Office2013White
    18:
      begin
        Planner.Sidebar.ActiveColor := clNone;
        Planner.Sidebar.ActiveColorTo := clNone;
        Planner.Sidebar.Background := clWhite;
        Planner.Sidebar.BackgroundTo := clWhite;
        Planner.Sidebar.Occupied := $DAA026;
        Planner.Sidebar.OccupiedTo := $DAA026;
        Planner.Sidebar.SeparatorLineColor := $D4D4D4;
        Planner.Sidebar.LineColor := $D4D4D4;
        Planner.Sidebar.Flat := True;
        Planner.Sidebar.Border := true;
        Planner.Sidebar.Font.Color := clBlack;
        Planner.Header.ActiveColor := clNone;
        Planner.Header.ActiveColorTo := clNone;
        Planner.Header.Color := clWhite;
        Planner.Header.ColorTo := clWhite;
        Planner.Header.Flat := false;
        Planner.Header.Font.Color := clBlack;
        Planner.Header.LineColor := $D4D4D4;
        Planner.Footer.LineColor := $D4D4D4;
        Planner.Footer.Flat := true;
        Planner.Footer.Color := clWhite;
        Planner.Footer.ColorTo := clWhite;
        Planner.Display.ColorActive := clWhite;
        Planner.Display.ColorNonActive := $EEEEEE;
        Planner.Caption.Background := $D4D4D4;
        Planner.Caption.BackgroundTo := $D4D4D4;
        Planner.Caption.Font.Color := clBlack;
        Planner.SelectColor := $DAA026;
        Planner.TrackColor := $EEEEEE;
        Planner.GridLineColor := $D4D4D4;
        Planner.Display.HourLineColor := $D4D4D4;


        Planner.DefaultItem.ColorTo := clWhite;
        Planner.DefaultItem.Color := clWhite;
        Planner.DefaultItem.BorderColor :=  $D4D4D4;
        Planner.DefaultItem.SelectColorTo := $FCE2C8;
        Planner.DefaultItem.SelectColor := $FCE2C8;
        Planner.DefaultItem.CaptionBkgTo := $EEEEEE; //caption panel
        Planner.DefaultItem.CaptionBkg := $EEEEEE;
        Planner.DefaultItem.TrackColor := $EAB47E; //bordercolorhover glowbtn
        Planner.DefaultItem.TrackSelectColor := $E59D56; //bordercolordown glowbtn
        Planner.DefaultItem.CaptionBkgDirection := gdHorizontal;
        Planner.DefaultItem.ColorDirection := gdVertical;

        Planner.DefaultItem.Shadow := false;
        Planner.DefaultItem.SelectFontColor := clBlack;
      end;
     // Office2013LightGray
      19:
      begin
        Planner.Sidebar.ActiveColor := clNone;
        Planner.Sidebar.ActiveColorTo := clNone;
        Planner.Sidebar.Background := clWhite;
        Planner.Sidebar.BackgroundTo := clWhite;
        Planner.Sidebar.Occupied := $F6F6F6;
        Planner.Sidebar.OccupiedTo := $F6F6F6;
        Planner.Sidebar.SeparatorLineColor := $C6C6C6;
        Planner.Sidebar.LineColor := $C6C6C6;
        Planner.Sidebar.Flat := True;
        Planner.Sidebar.Border := true;
        Planner.Sidebar.Font.Color := clBlack;
        Planner.Header.ActiveColor := clNone;
        Planner.Header.ActiveColorTo := clNone;
        Planner.Header.Color := $FAFAFA;
        Planner.Header.ColorTo := $FAFAFA;
        Planner.Header.Flat := false;
        Planner.Header.Font.Color := clBlack;
        Planner.Header.LineColor := $C6C6C6;
        Planner.Footer.LineColor := $C6C6C6;
        Planner.Footer.Flat := true;
        Planner.Footer.Color := $FAFAFA;
        Planner.Footer.ColorTo := $FAFAFA;
        Planner.Display.ColorActive := clWhite;
        Planner.Display.ColorNonActive := $EEEEEE;
        Planner.Caption.Background := $F6F6F6; //$C6C6C6;
        Planner.Caption.BackgroundTo := $F6F6F6; //$C6C6C6;
        Planner.Caption.Font.Color := clBlack;
        Planner.SelectColor := $DAA026;
        Planner.TrackColor := $EEEEEE;
        Planner.GridLineColor := $C6C6C6;;
        Planner.Display.HourLineColor := $C6C6C6;


        Planner.DefaultItem.ColorTo := clWhite;
        Planner.DefaultItem.Color := clWhite;
        Planner.DefaultItem.BorderColor :=  $C6C6C6;
        Planner.DefaultItem.SelectColorTo := $FCE2C8;
        Planner.DefaultItem.SelectColor := $FCE2C8;
        Planner.DefaultItem.CaptionBkgTo := $EEEEEE; //caption panel
        Planner.DefaultItem.CaptionBkg := $EEEEEE;
        Planner.DefaultItem.TrackColor := $EAB47E; //bordercolorhover glowbtn
        Planner.DefaultItem.TrackSelectColor := $E59D56; //bordercolordown glowbtn
        Planner.DefaultItem.CaptionBkgDirection := gdHorizontal;
        Planner.DefaultItem.ColorDirection := gdVertical;

        Planner.DefaultItem.Shadow := false;
        Planner.DefaultItem.SelectFontColor := clBlack;
      end;
      // Office2013Gray
      20:
      begin
        Planner.Sidebar.ActiveColor := clNone;
        Planner.Sidebar.ActiveColorTo := clNone;
        Planner.Sidebar.Background := $F3F3F3;
        Planner.Sidebar.BackgroundTo := $F3F3F3;
        Planner.Sidebar.Occupied := $DAA026;
        Planner.Sidebar.OccupiedTo := $DAA026;
        Planner.Sidebar.SeparatorLineColor := $ABABAB;
        Planner.Sidebar.LineColor := $ABABAB;
        Planner.Sidebar.Flat := true;
        Planner.Sidebar.Border := true;
        Planner.Sidebar.Font.Color := clBlack;
        Planner.Header.ActiveColor := clNone;
        Planner.Header.ActiveColorTo := clNone;
        Planner.Header.Color := $F3F3F3;
        Planner.Header.ColorTo := $F3F3F3;
        Planner.Header.Flat := false;
        Planner.Header.Font.Color := clBlack;
        Planner.Header.LineColor := $ABABAB;
        Planner.Footer.LineColor := $ABABAB;
        Planner.Footer.Flat := true;
        Planner.Footer.Color := $F3F3F3;
        Planner.Footer.ColorTo := $F3F3F3;
        Planner.Display.ColorActive := clWhite;
        Planner.Display.ColorNonActive := $EEEEEE;
        Planner.Caption.Background := $E5E5E5;
        Planner.Caption.BackgroundTo := $E5E5E5;
        Planner.Caption.Font.Color := clBlack;
        Planner.SelectColor := $DAA026;
        Planner.TrackColor := $EEEEEE;
        Planner.GridLineColor := $ABABAB;
        Planner.Display.HourLineColor := $ABABAB;


        Planner.DefaultItem.ColorTo := clWhite;
        Planner.DefaultItem.Color := clWhite;
        Planner.DefaultItem.BorderColor :=  $ABABAB;
        Planner.DefaultItem.SelectColorTo := $FCE2C8;
        Planner.DefaultItem.SelectColor := $FCE2C8;
        Planner.DefaultItem.CaptionBkgTo := $EEEEEE; //caption panel
        Planner.DefaultItem.CaptionBkg := $EEEEEE;
        Planner.DefaultItem.TrackColor := $EAB47E; //bordercolorhover glowbtn
        Planner.DefaultItem.TrackSelectColor := $E59D56; //bordercolordown glowbtn
        Planner.DefaultItem.CaptionBkgDirection := gdHorizontal;
        Planner.DefaultItem.ColorDirection := gdVertical;

        Planner.DefaultItem.Shadow := false;
        Planner.DefaultItem.SelectFontColor := clBlack;
      end;
    // Windows10
    21:
      begin
        Planner.Sidebar.ActiveColor := clNone;
        Planner.Sidebar.ActiveColorTo := clNone;
        Planner.Sidebar.Background := $F7F6F5;
        Planner.Sidebar.BackgroundTo := $F7F6F5;
        Planner.Sidebar.Occupied := $F7E0C9;
        Planner.Sidebar.OccupiedTo := $F7E0C9;
        Planner.Sidebar.SeparatorLineColor := $DCDBDA;
        Planner.Sidebar.LineColor := $DCDBDA;
        Planner.Sidebar.Flat := true;
        Planner.Sidebar.Border := true;
        Planner.Sidebar.Font.Color := clBlack;
        Planner.Header.ActiveColor := clNone;
        Planner.Header.ActiveColorTo := clNone;
        Planner.Header.Color := $F7F6F5;
        Planner.Header.ColorTo := $F7F6F5;
        Planner.Header.Flat := false;
        Planner.Header.Font.Color := clBlack;
        Planner.Header.LineColor := $DCDBDA;
        Planner.Footer.LineColor := $DCDBDA;
        Planner.Footer.Flat := true;
        Planner.Footer.Color := $F7F6F5;
        Planner.Footer.ColorTo := $F7F6F5;
        Planner.Display.ColorActive := clWhite;
        Planner.Display.ColorNonActive := $EEEEEE;
        Planner.Caption.Background := $DCDBDA;
        Planner.Caption.BackgroundTo := $DCDBDA;
        Planner.Caption.Font.Color := clBlack;
        Planner.SelectColor := $DAA026;
        Planner.TrackColor := $DCDBDA; //caption background
        Planner.GridLineColor := $DCDBDA;
        Planner.Display.HourLineColor := $DCDBDA;


        Planner.DefaultItem.ColorTo := clWhite;
        Planner.DefaultItem.Color := clWhite;
        Planner.DefaultItem.BorderColor :=  $DCDBDA;
        Planner.DefaultItem.SelectColorTo := $F7E0C9;
        Planner.DefaultItem.SelectColor := $F7E0C9;
        Planner.DefaultItem.CaptionBkgTo := $EEEEEE; //caption panel
        Planner.DefaultItem.CaptionBkg := $EEEEEE;
        Planner.DefaultItem.TrackColor := $F9CEA4; //bordercolorhover glowbtn
        Planner.DefaultItem.TrackSelectColor := $E4A262; //bordercolordown glowbtn
        Planner.DefaultItem.CaptionBkgDirection := gdHorizontal;
        Planner.DefaultItem.ColorDirection := gdVertical;

        Planner.DefaultItem.Shadow := false;
        Planner.DefaultItem.SelectFontColor := clBlack;
      end;
    // Office2016White
    22:
      begin
        Planner.Sidebar.ActiveColor := clNone;
        Planner.Sidebar.ActiveColorTo := clNone;
        Planner.Sidebar.Background := clWhite;
        Planner.Sidebar.BackgroundTo := clWhite;
        Planner.Sidebar.Occupied := clWhite;
        Planner.Sidebar.OccupiedFontColor:= $666666;
        Planner.Sidebar.OccupiedTo := clWhite;
        Planner.Sidebar.SeparatorLineColor := $E1E1E1;
        Planner.Sidebar.LineColor := $E1E1E1;
        Planner.Sidebar.Flat := True;
        Planner.Sidebar.Border := true;
        Planner.Sidebar.Font.Color := $666666;
        Planner.Header.ActiveColor := clNone;
        Planner.Header.ActiveColorTo := clNone;
        Planner.Header.Color := clWhite;
        Planner.Header.ColorTo := clWhite;
        Planner.Header.Flat := false;
        Planner.Header.Font.Color := $666666;
        Planner.Header.LineColor := $E1E1E1;
        Planner.Footer.LineColor := $E1E1E1;
        Planner.Footer.Flat := true;
        Planner.Footer.Color := clWhite;
        Planner.Footer.ColorTo := clWhite;
        Planner.Display.ColorActive := clWhite;
        Planner.Display.ColorNonActive := $F0F0F0;
        Planner.Caption.Background := $F5D1A6;
        Planner.Caption.BackgroundTo := $F5D1A6;
        Planner.Caption.Font.Color := $262626;
        Planner.SelectColor := $C67200;
        Planner.TrackColor := $F5D1A6; //caption background
        Planner.GridLineColor := $E1E1E1;
        Planner.Display.HourLineColor := $E1E1E1;


        Planner.DefaultItem.ColorTo := $FEE9C1;
        Planner.DefaultItem.Color := $FEE9C1;
        Planner.DefaultItem.BorderColor :=  $FEE9C1;
        Planner.DefaultItem.SelectColorTo := $FEE9C1;
        Planner.DefaultItem.SelectColor := $FEE9C1;
        Planner.DefaultItem.CaptionBkgTo := $FEE9C1;
        Planner.DefaultItem.CaptionBkg := $FEE9C1;
        Planner.DefaultItem.TrackColor := $F5D1A6;
        Planner.DefaultItem.TrackSelectColor := $F5D1A6;
        Planner.DefaultItem.CaptionBkgDirection := gdHorizontal;
        Planner.DefaultItem.ColorDirection := gdVertical;

        Planner.DefaultItem.Shadow := false;
        Planner.DefaultItem.SelectFontColor := clBlack;
      end;
     // Office2016Gray
      23:
      begin
        Planner.Sidebar.ActiveColor := clNone;
        Planner.Sidebar.ActiveColorTo := clNone;
        Planner.Sidebar.Background := $6A6A6A;
        Planner.Sidebar.BackgroundTo := $6A6A6A;
        Planner.Sidebar.Occupied := $6A6A6A;
        Planner.Sidebar.OccupiedTo := $6A6A6A;
        Planner.Sidebar.OccupiedFontColor:= $F0F0F0;
        Planner.Sidebar.SeparatorLineColor := $E1E1E1;
        Planner.Sidebar.LineColor := $E1E1E1;
        Planner.Sidebar.Flat := True;
        Planner.Sidebar.Border := true;
        Planner.Sidebar.Font.Color := $F0F0F0;
        Planner.Header.ActiveColor := clNone;
        Planner.Header.ActiveColorTo := clNone;
        Planner.Header.Color := $F0F0F0;
        Planner.Header.ColorTo := $F0F0F0;
        Planner.Header.Flat := false;
        Planner.Header.Font.Color := $444444;
        Planner.Header.LineColor := $E1E1E1;
        Planner.Footer.LineColor := $E1E1E1;
        Planner.Footer.Flat := true;
        Planner.Footer.Color := $F0F0F0;
        Planner.Footer.ColorTo := $F0F0F0;
        Planner.Display.ColorActive := $F0F0F0;
        Planner.Display.ColorNonActive := $D4D4D4;
        Planner.Caption.Background := $FEF3DD;
        Planner.Caption.BackgroundTo := $FEF3DD;
        Planner.Caption.Font.Color := $444444;
        Planner.SelectColor := $C67200;
        Planner.TrackColor := $FEF3DD;
        Planner.GridLineColor := $E1E1E1;
        Planner.Display.HourLineColor := $E1E1E1;


        Planner.DefaultItem.ColorTo := $FEE9C1;
        Planner.DefaultItem.Color := $FEE9C1;
        Planner.DefaultItem.BorderColor :=  $FEE9C1;
        Planner.DefaultItem.SelectColorTo := $FEE9C1;
        Planner.DefaultItem.SelectColor := $FEE9C1;
        Planner.DefaultItem.CaptionBkgTo := $FEE9C1;
        Planner.DefaultItem.CaptionBkg := $FEE9C1;
        Planner.DefaultItem.TrackColor := $F5D1A6;
        Planner.DefaultItem.TrackSelectColor := $F5D1A6;
        Planner.DefaultItem.CaptionBkgDirection := gdHorizontal;
        Planner.DefaultItem.ColorDirection := gdVertical;

        Planner.DefaultItem.Shadow := false;
        Planner.DefaultItem.SelectFontColor := clBlack;
      end;
      // Office2016Black
      24:
      begin
        Planner.Sidebar.ActiveColor := clNone;
        Planner.Sidebar.ActiveColorTo := clNone;
        Planner.Sidebar.Background := $252525;
        Planner.Sidebar.BackgroundTo := $252525;
        Planner.Sidebar.Occupied := $252525;
        Planner.Sidebar.OccupiedTo := $252525;
        Planner.Sidebar.OccupiedFontColor:= $F0F0F0;
        Planner.Sidebar.SeparatorLineColor := $626262;
        Planner.Sidebar.LineColor := $626262;
        Planner.Sidebar.Flat := True;
        Planner.Sidebar.Border := true;
        Planner.Sidebar.Font.Color := $F0F0F0;
        Planner.Header.ActiveColor := clNone;
        Planner.Header.ActiveColorTo := clNone;
        Planner.Header.Color := $252525;
        Planner.Header.ColorTo := $252525;
        Planner.Header.Flat := false;
        Planner.Header.Font.Color := $F0F0F0;
        Planner.Header.LineColor := $626262;
        Planner.Footer.LineColor := $626262;
        Planner.Footer.Flat := true;
        Planner.Footer.Color := $252525;
        Planner.Footer.ColorTo := $252525;
        Planner.Display.ColorActive := $252525;
        Planner.Display.ColorNonActive := $252525;
        Planner.Caption.Background := $D77800;
        Planner.Caption.BackgroundTo := $D77800;
        Planner.Caption.Font.Color := $F1F1F1;
        Planner.SelectColor := $FEB858;
        Planner.TrackColor := $D77800;
        Planner.GridLineColor := $626262;
        Planner.Display.HourLineColor := $626262;


        Planner.DefaultItem.ColorTo := $D77800;
        Planner.DefaultItem.Color := $D77800;
        Planner.DefaultItem.BorderColor :=  $D77800;
        Planner.DefaultItem.SelectColorTo := $D77800;
        Planner.DefaultItem.SelectColor := $D77800;
        Planner.DefaultItem.CaptionBkgTo := $D77800;
        Planner.DefaultItem.CaptionBkg := $D77800;
        Planner.DefaultItem.TrackColor := $C35B0D;
        Planner.DefaultItem.TrackSelectColor := $C35B0D;
        Planner.DefaultItem.CaptionBkgDirection := gdHorizontal;
        Planner.DefaultItem.ColorDirection := gdVertical;

        Planner.DefaultItem.Shadow := false;
        Planner.DefaultItem.SelectFontColor := clWhite;
      end;
  end;
  Planner.UpdateSizes;
end;

function Clip(const value: Integer; const RangeLow, RangeHigh: Integer): Integer;
begin
  if value > RangeHigh then
    Result := RangeHigh
  else if value < RangeLow then
    Result := $00DEF9B9
  else
    Result := value;
end;

type
  TColorRecord = record
    RedValue: Byte; //  clRed = TColor($0000FF);   Low byte
    GreenValue: Byte; //  clLime = TColor($00FF00);  Middle byte
    BlueValue: Byte; //  clBlue = TColor($FF0000);  High byte
    SystemValue: Byte; //  becomes zero when calling ColorToRgb
  end;

function ColorToHtmlHexBgColor(const value: TColor): string;
const
  HtmlHexBgColor = ' BGCOLOR="#RRGGBB"';
  HexDigit: array [0 .. $F] of Char = '0123456789ABCDEF';
begin
  //  HTML Color looks like this: #RRGGBB
  with TColorRecord(ColorToRGB(value)) do
  begin
    Result := HtmlHexBgColor;
    Result[12] := HexDigit[RedValue shr 4];
    Result[13] := HexDigit[RedValue and $F];
    Result[14] := HexDigit[GreenValue shr 4];
    Result[15] := HexDigit[GreenValue and $F];
    Result[16] := HexDigit[BlueValue shr 4];
    Result[17] := HexDigit[BlueValue and $F];
  end;
end;

const
  CStyleLF = '\n';
  RegularCRLF = #13#10;
  HtmlBreak = '<BR>';
  RtfStart = '{\';
  HtmlEndTagStart = '</';
  HtmlNonBreakingSpace = '&nbsp;';

function ReplaceCLFWith(const value: string; const Replacement: string): string;
var
  CLFPos: Integer;
begin
  Result := value;
  CLFPos := Pos(CStyleLF, Result);
  while CLFPos > 0 do
  begin
    Result := Copy(Result, 1, CLFPos - 1) + RegularCRLF + Copy(Result,
      CLFPos + 2, Length(Result));
    CLFPos := Pos(CStyleLF, Result);
  end;
end;

function CLFToLF(value: string): string;
begin
  Result := ReplaceCLFWith(value, RegularCRLF);
end;

function CLToBR(value: string): string;
begin
  if value = '' then
    Result := HtmlNonBreakingSpace
  else
    Result := ReplaceCLFWith(value, HtmlBreak);
end;

function IsRtf(const value: string): Boolean;
begin
  Result := (Pos(RtfStart, value) = 1);
end;

function IsHtml(APlannerItem: TPlannerItem; const value: string;
  Caption: Boolean): Boolean;
begin
  Result := (Pos(HtmlEndTagStart, value) > 0);
  if (APlannerItem.InplaceEdit = peForm) and not Caption then
    Result := True;
end;

(*
function PlanTimeToStr(HourType: THourType; MinutesValue: Cardinal): string;
var
  Hours, Minutes: Integer;
begin
  Hours := MinutesValue div 60;
  Minutes := MinutesValue mod 60;
  Hours := Hours mod 24;

  if (HourType = ht12hrs) then
  begin
    if (Hours >= 12) then
      Result := TimePMString
    else
      Result := TimeAMString;
    Result := ' ' + Result;
    if (Hours > 12) then
      Hours := Hours - 12
  end
  else
    Result := '';

  Result := Format('%d%s%.2d%s', [Hours, TimeSeparator, Minutes, Result]);
end;
*)

{ TCustomPlanner }

constructor TCustomPlanner.Create(AOwner: TComponent);
var
  Bitmap: TBitmap;
  PlannerColorArrayPointer: PPlannerColorArray;
  ColorIndex: Integer;

begin
{$IFDEF ACTIVEXDEBUG}
  ShowMessage('TPlanner Create Start');
{$ENDIF}
  inherited Create(AOwner);
  Width := 350;
  Height := 300;
  FHTMLFactor := 1.0;
  FScrollDelay := 50;
  FMaxHintWidth := 240;
  FFont := TFont.Create;
  FWheelDelta := 1;
  FFont.OnChange := PlanFontChanged;
  FRichEdit := TPlannerRichEdit.Create(Self);
  FNavigatorButtons := TNavigatorButtons.Create(Self);
  FHeader := TAdvHeader.Create(Self);
  FFooter := TAdvFooter.Create(Self);
  FHeader.DoubleBuffered := True;
  FFooter.DoubleBuffered := True;

  FHeader.OnHeaderHint := DoHeaderHint;
  FFooter.OnHeaderHint := DoFooterHint;

  FBalloon := TBalloonSettings.Create;
  FBalloon.OnEnableChange := BalloonChange;
  FPrev := TAdvSpeedButton.Create(Self);
  FPrev.Direction := bdLeft;
  FNext := TAdvSpeedButton.Create(Self);
  FNext.Direction := bdRight;
  FMode := TPlannerMode.Create(Self);
  FGrid := TPlannerGrid.Create(Self);

  FGrid.Options := FGrid.Options - [goHorzLine];
{$IFDEF DELPHI2006_LVL}
  FGrid.OnMouseLeave := DoMouseLeave;
  FGrid.OnMouseEnter := DoMouseEnter;
{$ENDIF}
{$IFDEF DELPHIXE_LVL}
  FGrid.OnGesture := GridGesture;
{$ENDIF}
  FGrid.DoubleBuffered := False;
  FPlannerHeader := TPlannerHeader.Create(Self);
  FPlannerFooter := TPlannerFooter.Create(Self);
  FTimePointers := TPlannerTimePointers.Create(Self);
  FPanel := TPlannerPanel.Create(Self);
  FPanel.DoubleBuffered := True;
  FBands := TBands.Create(Self);
  FCaption := TPlannerCaption.Create(Self);
  FSidebar := TPlannerSideBar.Create(Self);
  FDisplay := TPlannerDisplay.Create(Self);
  FPlannerItems := CreateItems;
  FPrintOptions := TPlannerPrintOptions.Create;
  FHTMLOptions := TPlannerHTMLOptions.Create;
  FScrollBarStyle := TPlannerScrollBar.Create(Self);
  FInactiveDays := TWeekDays.Create;
  FDefaultItems := CreateItems;
  FBackGround := TBackground.Create(Self);
  FDefaultItem := FDefaultItems.Add;
  FSyncPlanner := TSyncPlanner.Create(Self);
  FDragImage := TDragImageList.Create(Self);

  if (csDesigning in ComponentState) and not(csLoading in ComponentState) then
    FDefaultItem.OnDesignChange := ItemDesignChange;

  FInactiveDays.OnChanged := InactiveChanged;
  FImageCache := THTMLPictureCache.Create;
  FPositionProps := TPositionProps.Create(Self);
  FSelectRange := True;
  FSelections := TPlannerSelections.Create(Self);
  FItemSelection := TPlannerItemSelection.Create;
  FShowOccupiedInPositionGap := True;
  FShowDesignHelper := True;
  FCheckConflicts := True;

  FFlat := True;
  FDrawPrecise := False;
  FRoundTime := False;
  FLinkArrowSize := ARROW_SIZE;
  FLinkArrowShape := asNormal;

  FGrid.Visible := True;
  FGrid.Parent := Self;
  FGrid.ShowHint := True;
  FGrid.Ctl3D := False;
  FPanel.Visible := True;
  FPanel.Parent := Self;
  FPanel.BevelOuter := bvNone;
  FPanel.BevelInner := bvNone;
  FTrackColor := clBlue;
  FTrackOnly := False;
  FFlashColor := clRed;
  FFlashFontColor := clWhite;
  FTrackWidth := 4;
  FPositions := 3;
  FPositionWidth := 0;
  FPrinterDriverFix := False;
  FLayer := 0;
  FEditOnSelectedClick := True;
  FItemGap := 11;
  FColor := clWindow;
  FSelectBlend := 90;
  FGradientSteps := 32;
  FGradientHorizontal := False;
  FSelectColor := clHighlight;
  FShowSelection := True;
  FDisjunctSelectColor := clHighlight;
  FGridLineColor := $00CECECE;
  FInplaceEdit := ieAlways;
  FDayNames := TStringList.Create;
  FPositionGapColor := clWhite;
  FAutoPositionPrevNext := False;
  FScrollBars := ssBoth;
  FOldOfficeTheme := otUnknown;

  FDayNames.Add(ShortDaySun);
  FDayNames.Add(ShortDayMon);
  FDayNames.Add(ShortDayTue);
  FDayNames.Add(ShortDayWed);
  FDayNames.Add(ShortDayThu);
  FDayNames.Add(ShortDayFri);
  FDayNames.Add(ShortDaySat);

  FHeader.Visible := True;
  FHeader.Parent := Self;
  FHeader.BorderStyle := bsNone;
  FHeader.AllowResize := False;
  FHeader.AllowSizing := False;
  FHeader.OnClick := HeaderClick;
  FHeader.OnRightClick := HeaderRightClick;
  FHeader.OnDblClick := HeaderDblClick;
  FHeader.OnDragDrop := HeaderDragDrop;
  FHeader.OnSized := HeaderSized;

  FFooter.Visible := True;
  FFooter.Parent := Self;
  FFooter.BorderStyle := bsNone;
  FFooter.AllowResize := False;

  FPrev.Parent := Self;
  FNext.Parent := Self;
  FPrev.OnClick := PrevClick;
  FNext.OnClick := NextClick;
  Bitmap := TBitmap.Create;
  Bitmap.LoadFromResourceID(HInstance, 500);
  FPrev.Glyph.Assign(Bitmap);
  Bitmap.LoadFromResourceID(HInstance, 501);
  FNext.Glyph.Assign(Bitmap);
  Bitmap.Free;
  FPositionAutoSize := False;
  FShadowColor := clGray;
  FHintColor := clInfoBk;
  FHintPause := Application.HintHidePause;
  FHintOnItemChange := True;
  FTimerID := 0;
  FOverlap := True;
  FLoading := False;
  FURLColor := clBlue;
  FShowLinks := False;

  FURLGlyph := TBitmap.Create;
  if (csDesigning in ComponentState) then
    FURLGlyph.LoadFromResourceID(HInstance, 503);
  FAttachementGlyph := TBitmap.Create;

  if (csDesigning in ComponentState) then
    FAttachementGlyph.LoadFromResourceID(HInstance, 502);

  FDeleteGlyph := TBitmap.Create;

  if (csDesigning in ComponentState) then
    FDeleteGlyph.LoadFromResourceID(HInstance, 504);

  FEnableKeyboard := True;
  FAutoItemScroll := True;
  FSelectionAlways := True;
  FInsertAlways := True;

  while FGrid.ColorList.Count < FPositions do
  begin
    PlannerColorArrayPointer := FGrid.ColorList.Add;

    for ColorIndex := 0 to NumColors do
    begin
      PlannerColorArrayPointer^[ColorIndex].Color := clNone;
      PlannerColorArrayPointer^[ColorIndex].Selected := 0;
    end;
  end;

  FCompletionColor1 := clRed;
  FCompletionColor2 := clWhite;

  FDTList := TDateTimeList.Create;

  ControlStyle := ControlStyle + [csAcceptsControls];

  FDesignTime := (csDesigning in ComponentState) and not
    ((csReading in Owner.ComponentState) or (csLoading in Owner.ComponentState));

{$IFDEF TMSSKINS}
  FSkin := TPlannerSkin.Create(Self);
{$ENDIF}
end;

destructor TCustomPlanner.Destroy;
begin
  if FBalloon.Enable then
    BalloonDone;

  FDefaultItem.Free;
  FDefaultItem := nil;
  FDefaultItems.Free;
  FRichEdit.Free;
  FBalloon.Free;
  FGrid.Free;
  FGrid := nil;
  FPanel.Free;
  FBands.Free;
  FCaption.Free;
  FSidebar.Free;
  FDisplay.Free;
  FDisplay := nil;
  FPlannerHeader.Free;
  FPlannerFooter.Free;
  FPlannerItems.Free;
  FPlannerItems := nil;
  FDragImage.Free;
  FDragImage := nil;
  FMode.Free;
  FFont.Free;
  FHeader.Free;
  FFooter.Free;
  FNext.Free;
  FPrev.Free;
  FNavigatorButtons.Free;
  FScrollBarStyle.Free;
  FPrintOptions.Free;
  FHTMLOptions.Free;
  FDayNames.Free;
  FInactiveDays.Free;
  FBackGround.Free;
  FSelections.Free;
  FSyncPlanner.Free;
  FSyncPlanner := nil;
  FImageCache.Free;
  FPositionProps.Free;
  FItemSelection.Free;
  FDTList.Free;
  FURLGlyph.Free;
  FDeleteGlyph.Free;
  FAttachementGlyph.Free;
  FTimePointers.Free;
{$IFDEF TMSSKINS}
  FSkin.Free;
{$ENDIF}
  inherited;
end;

procedure TCustomPlanner.SetStyle(StyleIndex: Integer);
begin
  PlannerSetStyle(StyleIndex, Self);
end;

procedure TCustomPlanner.SetSyncPlanner(const Value: TSyncPlanner);
begin
  FSyncPlanner.Assign(Value);
end;

{$IFDEF TMSSKINS}

procedure TCustomPlanner.SetPlannerSkin(AValue: TPlannerSkin);
begin
  FSkin.Assign(AValue);
end;
{$ENDIF}

procedure TCustomPlanner.Assign(Source: TPersistent);
begin
  if Assigned(Source) then
  begin
    Items.Assign((Source as TCustomPlanner).Items);
    Display.Assign((Source as TCustomPlanner).Display);
    Sidebar.Assign((Source as TCustomPlanner).Sidebar);
    Header.Assign((Source as TCustomPlanner).Header);
    Footer.Assign((Source as TCustomPlanner).Footer);
    Caption.Assign((Source as TCustomPlanner).Caption);
    SyncPlanner.Assign((Source as TCustomPlanner).SyncPlanner);
  end;
end;

function TCustomPlanner.GetBackGroundColor(ACol, ARow: Integer): TColor;
var
  PlannerColorArrayPointer: PPlannerColorArray;
begin
  if Sidebar.Position = spTop then
  begin
    if (ARow < FGrid.ColorList.Count) then
    begin
      PlannerColorArrayPointer := FGrid.ColorList.Items[ARow];

      if (ACol < NumColors) then
        Result := PlannerColorArrayPointer^[ACol].Color
      else
        Result := clNone;
    end
    else
      Result := FGrid.Color;
  end
  else
  begin
    if (ACol < FGrid.ColorList.Count) then
    begin
      Result := clNone;

      PlannerColorArrayPointer := FGrid.ColorList.Items[ACol];

      if (ARow < NumColors) then
        Result := PlannerColorArrayPointer^[ARow].Color;
    end
    else
      Result := FGrid.Color;
  end;
end;

procedure TCustomPlanner.ClearBackgroundColors;
var
  i, ColorIndex: Integer;
  PlannerColorArrayPointer: PPlannerColorArray;
begin
  for i := 1 to FGrid.ColorList.Count do
  begin
    PlannerColorArrayPointer := FGrid.ColorList.Items[i - 1];

    for ColorIndex := 0 to NumColors do
    begin
      PlannerColorArrayPointer^[ColorIndex].Color := clNone;
      PlannerColorArrayPointer^[ColorIndex].Selected := 0;
    end;
  end;
  Invalidate;
end;

procedure TCustomPlanner.SetBackGroundColor(ACol, ARow: Integer;
  const value: TColor);
var
  PlannerColorArrayPointer: PPlannerColorArray;
begin
  if (ACol < 0) or (ARow < 0) or (ACol >= FGrid.ColCount) or
    (ARow >= FGrid.RowCount) then
    Exit;

  if Sidebar.Position = spTop then
  begin
    if (ARow < FGrid.ColorList.Count) then
    begin
      PlannerColorArrayPointer := FGrid.ColorList.Items[ARow];

      if (ACol < NumColors) then
        PlannerColorArrayPointer^[ACol].Color := value;
    end;
    FGrid.InvalidateCell(ACol, ARow + FSidebar.FRowOffset);
  end
  else
  begin
    if (ACol < FGrid.ColorList.Count) then
    begin
      PlannerColorArrayPointer := FGrid.ColorList.Items[ACol];

      if (ARow < NumColors) then
        PlannerColorArrayPointer^[ARow].Color := value;
    end;
    FGrid.InvalidateCell(ACol + FSidebar.FColOffset, ARow);
  end;
end;

function TCustomPlanner.GetSelected(ACol, ARow: Integer): Boolean;
var
  PlannerColorArrayPointer: PPlannerColorArray;
begin
  Result := False;

  if Sidebar.Position = spTop then
  begin
    if (ARow < FGrid.ColorList.Count) then
    begin
      PlannerColorArrayPointer := FGrid.ColorList.Items[ARow];

      if (ACol < NumColors) then
        Result := PlannerColorArrayPointer^[ACol].Selected > 0
    end;
  end
  else
  begin
    if (ACol < FGrid.ColorList.Count) then
    begin
      PlannerColorArrayPointer := FGrid.ColorList.Items[ACol];

      if (ARow < NumColors) then
        Result := PlannerColorArrayPointer^[ARow].Selected > 0;
    end;
  end;
end;

procedure TCustomPlanner.SetSelected(ACol, ARow: Integer; const value: Boolean);
var
  PlannerColorArrayPointer: PPlannerColorArray;
begin
  if (ACol < 0) or (ARow < 0) or (ACol >= FGrid.ColCount) or
    (ARow >= FGrid.RowCount) then
    Exit;

  if Sidebar.Position = spTop then
  begin
    if (ARow < FGrid.ColorList.Count) then
    begin
      PlannerColorArrayPointer := FGrid.ColorList.Items[ARow];

      if (ACol < NumColors) then
      begin
        if value then
          PlannerColorArrayPointer^[ACol].Selected := PlannerColorArrayPointer^[ACol].Selected + 1
        else if PlannerColorArrayPointer^[ACol].Selected > 0 then
          PlannerColorArrayPointer^[ACol].Selected := PlannerColorArrayPointer^[ACol].Selected - 1;
      end;
    end;
    FGrid.InvalidateCell(ACol, ARow + FSidebar.FRowOffset);
  end
  else
  begin
    if (ACol < FGrid.ColorList.Count) then
    begin
      PlannerColorArrayPointer := FGrid.ColorList.Items[ACol];

      if (ARow < NumColors) then
      begin
        if value then
          PlannerColorArrayPointer^[ARow].Selected := PlannerColorArrayPointer^[ARow].Selected + 1
        else if PlannerColorArrayPointer^[ARow].Selected > 0 then
          PlannerColorArrayPointer^[ARow].Selected := PlannerColorArrayPointer^[ARow].Selected - 1;
      end;
    end;
    FGrid.InvalidateCell(ACol + FSidebar.FColOffset, ARow);
  end;
end;

procedure TCustomPlanner.DoHeaderHint(Sender: TObject; Index: Integer;
  var HintStr: string);
begin
  if Assigned(OnHeaderHint) then
    OnHeaderHint(Self, Index, HintStr);
end;

procedure TCustomPlanner.DoFooterHint(Sender: TObject; Index: Integer;
  var HintStr: string);
begin
  if Assigned(OnFooterHint) then
    OnFooterHint(Self, Index, HintStr);
end;

procedure TCustomPlanner.DoMouseLeave(Sender: TObject);
begin
  if Assigned(FOnPlannerMouseLeave) then
    FOnPlannerMouseLeave(Self);
end;

procedure TCustomPlanner.DoMouseEnter(Sender: TObject);
begin
  if Assigned(FOnPlannerMouseEnter) then
    FOnPlannerMouseEnter(Self);
end;

procedure TCustomPlanner.DoMouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  if Assigned(OnPlannerMouseDown) then
    OnPlannerMouseDown(Self, Button, Shift, X, Y);
end;

procedure TCustomPlanner.DoMouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  if Assigned(OnPlannerMouseUp) then
    OnPlannerMouseUp(Self, Button, Shift, X, Y);
end;

procedure TCustomPlanner.DoSideBarClick(Sender: TObject; Index: Integer);
begin
  if Assigned(OnSideBarClick) then
    OnSideBarClick(Sender, Index);
end;

procedure TCustomPlanner.DoSideBarRightClick(Sender: TObject; Index: Integer);
begin
  if Assigned(OnSideBarRightClick) then
    OnSideBarRightClick(Sender, Index);
end;

procedure TCustomPlanner.DoSideBarDblClick(Sender: TObject; Index: Integer);
begin
  if Assigned(OnSideBarDblClick) then
    OnSideBarDblClick(Sender, Index);
end;

procedure TCustomPlanner.DoItemGaugeSettings(APlannerItem: TPlannerItem; var GaugeSettings: TGaugeSettings);
begin
  if Assigned(OnItemCompletionSettings) then
    OnItemCompletionSettings(Self, APlannerItem, GaugeSettings);
end;

procedure TCustomPlanner.DoItemAfterPaint(APlannerItem: TPlannerItem;
  ACanvas: TCanvas; ARect: TRect);
begin
  if Assigned(OnItemAfterPaint) then
    OnItemAfterPaint(Self, APlannerItem, ACanvas, ARect);
end;

procedure TCustomPlanner.DoStartDrag(var DragObject: TDragObject);
begin
  inherited;
end;

procedure TCustomPlanner.DoAfterPaint;
begin
  if Assigned(OnAfterPaint) then
    OnAfterPaint(Self);
end;

procedure TCustomPlanner.DoEndDrag(Target: TObject; X: Integer; Y: Integer);
begin
  inherited;
end;


procedure TCustomPlanner.CreateDragImage(APlannerItem: TPlannerItem);
var
  b: TBitmap;
  delta: integer;
begin
  delta := (APlannerItem.ItemEnd - APlannerItem.ItemBegin);

  if delta = 0 then
    inc(delta);

  if (Sidebar.Orientation = soVertical) then
  begin
    FDragImage.Width := GridControl.ColWidths[GridControl.FixedCols];
    FDragImage.Height := Display.DisplayScale * delta;
  end
  else
  begin
    FDragImage.Height := GridControl.RowHeights[GridControl.FixedRows];
    FDragImage.Width := Display.DisplayScale * delta;
  end;

  b := TBitmap.create;
  b.Width := FDragImage.Width;
  b.Height := FDragImage.Height+20;
  PreviewPaint(APlannerItem,b.Canvas,Rect(0,0,FDragImage.Width, FDragImage.Height), (Sidebar.Orientation <> soVertical),false);

  FDragImage.Clear;
  FDragImage.Add(b,nil);
  b.Free;
end;

function TCustomPlanner.GetDragImages: TDragImageList;
begin
  Result := FDragImage;
end;

procedure TCustomPlanner.UpdateSelection(SelBegin, SelEnd, SelPos: Integer;
  Active: Boolean);
var
  i, f, l: Integer;
begin
  if SelBegin > SelEnd then
  begin
    l := SelBegin;
    f := SelEnd;
  end
  else
  begin
    l := SelEnd;
    f := SelBegin;
  end;

  for i := f to l - 1 do
  begin
    if Sidebar.Position = spTop then
      Selected[i, SelPos] := Active
    else
      Selected[SelPos, i] := Active;
  end;
end;

function TCustomPlanner.GetCellColorCol(Pos, Index: Integer; var UseColor: Boolean): TCellBrush;
var
  ABrush: TBrush;
  PlannerColorArrayPointer: PPlannerColorArray;
begin
  ABrush := TBrush.Create;
  GetCellBrush(Pos, Index, ABrush);
  Result.Color := ABrush.Color;
  Result.BrushStyle := ABrush.Style;
  ABrush.Free;

  { Custom cell Color }

  if (Pos < FGrid.ColorList.Count) and (Pos >= 0) and (Index < NumColors) then
  begin
    PlannerColorArrayPointer := FGrid.FColorList.Items[Pos];
    if PlannerColorArrayPointer^[Index].Color <> clNone then
      Result.Color := PlannerColorArrayPointer^[Index].Color;
    if PlannerColorArrayPointer^[Index].Selected > 0 then
    begin
      Result.Color := DisjunctSelectColor;
      UseColor := True;
    end;
  end;


  if CellInCurrTime(Index, Pos) then
  begin
    Result.Color := FDisplay.ColorCurrent;
    UseColor := True;
  end;
end;

function TCustomPlanner.IsCurPos(APosition: Integer): Boolean;
begin
  Result := True;
  if (Display.CurrentPosFrom = -1) or (Display.CurrentPosTo = -1) then
    Exit;

  Result := (APosition >= Display.CurrentPosFrom) and
    (APosition <= Display.CurrentPosTo);
end;

function TCustomPlanner.IsActive(AIndex, APosition: Integer): Boolean;
var
  DateTime: TDateTime;
  ActiveStart, ActiveEnd, M, Y: Integer;
  UsePP: Boolean;
  dbl: double;
begin
  UsePP := (PositionProps.Count > APosition) and (APosition >= 0);

  if UsePP then
    UsePP := PositionProps.Items[APosition].Use;

  if UsePP then
  begin
    ActiveStart := PositionProps.Items[APosition].ActiveStart;
    ActiveEnd := PositionProps.Items[APosition].ActiveEnd;
  end
  else
  begin
    ActiveStart := FDisplay.ActiveStart;
    ActiveEnd := FDisplay.ActiveEnd;
  end;

  Result := True;

  case FMode.FPlannerType of
    plDay, plCustomList:
      Result := (AIndex < ActiveStart) or (AIndex >= ActiveEnd);
    //  plWeek:
    //    begin
    //      Result := ((AIndex - FMode.WeekStart) mod DaysPerWeek) in [0, 1];
    //    end;
    plMonth:
      begin
        DateTime := Mode.StartOfMonth + AIndex;
        Result := DayOfWeek(DateTime) in FInactive;
      end;
    plActiveDayPeriod:
      begin
        Result := true;
      end;
    plDayPeriod, plWeek:
      begin
        DateTime := Mode.PeriodStartDate + AIndex;
        Result := DayOfWeek(DateTime) in FInactive;
      end;
    plHalfDayPeriod:
      begin
        DateTime := Mode.PeriodStartDate + AIndex / 2;
        Result := DayOfWeek(DateTime) in FInactive;
      end;
    plMultiMonth:
      begin
        M := Mode.Month + APosition;
        Y := Mode.Year;
        while M > 12 do
        begin
          Dec(M, 12);
          Inc(Y);
        end;
        if AIndex < PlanUtil.DaysInMonth(M, Y) then
        begin
          DateTime := EncodeDate(Y, M, AIndex + 1);
          Result := DayOfWeek(DateTime) in FInactive;
        end;
      end;
    plCustom:
      begin
        Result := False;
      end;
    plTimeLine:
      begin
        if ((MININDAY - (Mode.TimeLineNVUEnd + Mode.TimeLineNVUBegin) * Display.DisplayUnit) = 0) then
          dbl := AIndex * Display.DisplayUnit
        else
          dbl := AIndex * Display.DisplayUnit /
            (MININDAY - (Mode.TimeLineNVUEnd + Mode.TimeLineNVUBegin) * Display.DisplayUnit);
        DateTime := Mode.TimeLineStart + Trunc(dbl);
        Result := DayOfWeek(DateTime) in FInactive;
      end;
  end;
  Result := not Result;

  if Assigned(FOnPlannerIsActive) then
    FOnPlannerIsActive(Self, AIndex, APosition, Result);
end;

procedure TCustomPlanner.GetCellBrush(Pos, Index: Integer; ABrush: TBrush);
var
  DateTime: TDateTime;
  ActiveStart, ActiveEnd, M, Y: Integer;
  ColorActive, ColorNonActive: TColor;
  UsePP: Boolean;
  dbl: double;

begin
  ABrush.Style := bsSolid;

  UsePP := (PositionProps.Count > Pos) and (Pos >= 0);

  if UsePP then
    UsePP := PositionProps.Items[Pos].Use;

  if UsePP then
  begin
    ColorActive := PositionProps.Items[Pos].ColorActive;
    ColorNonActive := PositionProps.Items[Pos].ColorNonActive;
    ActiveStart := PositionProps.Items[Pos].ActiveStart;
    ActiveEnd := PositionProps.Items[Pos].ActiveEnd;
  end
  else
  begin
    ColorActive := Self.Display.ColorActive;
    ColorNonActive := Self.Display.ColorNonActive;
    ActiveStart := FDisplay.ActiveStart;
    ActiveEnd := FDisplay.ActiveEnd;
  end;

  if FBands.Show then
  begin
    if Odd(Index) then
      ColorActive := FBands.ActivePrimary
    else
      ColorActive := FBands.ActiveSecondary;

    if Odd(Index) then
      ColorNonActive := FBands.NonActivePrimary
    else
      ColorNonActive := FBands.NonActiveSecondary;
  end;

  ABrush.Style := bsSolid;
  ABrush.Color := ColorActive;

  case FMode.FPlannerType of
    plDay, plCustomList:
      begin
        if (Index < ActiveStart) or (Index >= ActiveEnd) then
          ABrush.Color := ColorNonActive;
      end;
    plMonth:
      begin
        DateTime := Mode.StartOfMonth + Index;
        if DayOfWeek(DateTime) in FInactive then
          ABrush.Color := ColorNonActive;
      end;
    plActiveDayPeriod:
      begin
        ABrush.Color := ColorActive;
      end;
    plDayPeriod, plWeek:
      begin
        DateTime := Mode.PeriodStartDate + Index;
        if DayOfWeek(DateTime) in FInactive then
          ABrush.Color := ColorNonActive;
      end;
    plHalfDayPeriod:
      begin
        DateTime := Mode.PeriodStartDate + Index / 2;
        if DayOfWeek(DateTime) in FInactive then
          ABrush.Color := ColorNonActive;
      end;
    plMultiMonth:
      begin
        M := Mode.Month + Pos;
        Y := Mode.Year;
        while M > 12 do
        begin
          Dec(M, 12);
          Inc(Y);
        end;

        if (Index < PlanUtil.DaysInMonth(M, Y)) then
        begin
          DateTime := EncodeDate(Y, M, Index + 1);
          if DayOfWeek(DateTime) in FInactive then
            ABrush.Color := ColorNonActive;
        end
        else
        begin
          ABrush.Color := Display.ColorNonSelect;
          ABrush.Style := Display.BrushNonSelect;
        end;
      end;
    plCustom:
      begin
      end;
    plTimeLine:
      begin
      if (MININDAY - (Mode.TimeLineNVUEnd + Mode.TimeLineNVUBegin) * Display.DisplayUnit) = 0 then
        dbl := Index * Display.DisplayUnit
      else
        dbl := Index * Display.DisplayUnit /
          (MININDAY - (Mode.TimeLineNVUEnd + Mode.TimeLineNVUBegin)
            * Display.DisplayUnit);
        DateTime := Mode.TimeLineStart + Trunc(dbl);
        if DayOfWeek(DateTime) in FInactive then
          ABrush.Color := ColorNonActive;
      end;
  end;

  if UsePP then
  begin
    if PositionProps.Items[Pos].MinSelection > 0 then
    begin
      if Index < PositionProps.Items[Pos].MinSelection then
      begin
        ABrush.Style := PositionProps.Items[Pos].BrushNoSelect;
        ABrush.Color := PositionProps.Items[Pos].ColorNoSelect;
      end;
    end;

    if PositionProps.Items[Pos].MaxSelection > 0 then
    begin
      if Index >= PositionProps.Items[Pos].MaxSelection then
      begin
        ABrush.Style := PositionProps.Items[Pos].BrushNoSelect;
        ABrush.Color := PositionProps.Items[Pos].ColorNoSelect;
      end;
    end;
  end;
end;

procedure TCustomPlanner.Print;
begin
  PrintSelection(0, Positions - 1);
end;

procedure TCustomPlanner.PrintTo(ACanvas: TCanvas);
begin
  PrintSelectionTo(ACanvas, 0, Positions - 1);
end;

procedure TCustomPlanner.PrintSelection(FromPos, ToPos: Integer);
begin
  with Printer do
  begin
    Title := FPrintOptions.JobName;
    Orientation := FPrintOptions.Orientation;
    BeginDoc;
    PrintSelectionTo(Canvas, FromPos, ToPos);
    EndDoc;
  end;
end;

procedure TCustomPlanner.PrintPages(NrOfPages: Integer);
var
  ItemsPerPage, i: Integer;
  FirstItem, LastItem: Integer;

begin
  if NrOfPages <= 0 then
    Exit;

  ItemsPerPage := (Display.DisplayEnd - Display.DisplayStart + 1) div NrOfPages;

  with Printer do
  begin
    Title := FPrintOptions.JobName;
    Orientation := FPrintOptions.Orientation;
    BeginDoc;

    FirstItem := 0;

    if ItemsPerPage > 0 then
      LastItem := ItemsPerPage - 1
    else
      LastItem := ItemsPerPage;

    for i := 1 to NrOfPages do
    begin
      PrintRangeTo(Printer.Canvas, 0, Positions - 1, FirstItem, LastItem);
      FirstItem := LastItem + 1;
      LastItem := LastItem + ItemsPerPage;

      if i = NrOfPages - 1 then
        LastItem := (Display.DisplayEnd - Display.DisplayStart);

      if i < NrOfPages then
        NewPage;
    end;
    EndDoc;
  end;
end;

procedure TCustomPlanner.PrintSelectionTo(ACanvas: TCanvas;
  FromPos, ToPos: Integer);
begin
  if (FromPos > ToPos) then
    Exit;

  if Sidebar.Orientation = soVertical then
    PrintCol(ACanvas, FromPos, ToPos, 0, FGrid.RowCount - 1)
  else
    PrintRow(ACanvas, FromPos, ToPos, 0, FGrid.ColCount - 1);
end;

procedure TCustomPlanner.PrintRange(FromPos, ToPos, FromItem, ToItem: Integer);
begin
  with Printer do
  begin
    Title := FPrintOptions.JobName;
    Orientation := FPrintOptions.Orientation;
    BeginDoc;
    PrintRangeTo(Printer.Canvas, FromPos, ToPos, FromItem, ToItem);
    EndDoc;
  end;
end;

procedure TCustomPlanner.PrintRangeTo(ACanvas: TCanvas;
  FromPos, ToPos, FromItem, ToItem: Integer);
begin
  if Sidebar.Orientation = soVertical then
    PrintCol(ACanvas, FromPos, ToPos, FromItem, ToItem)
  else
    PrintRow(ACanvas, FromPos, ToPos, FromItem, ToItem);
end;
{$IFDEF FREEWARE}

procedure PrintFreewareNotice(ACanvas: TCanvas; XSize, YSize: Integer;
  ClassName: string);
var
  DrawRect: TRect;
  LFont: TLogFont;
  HOldFont, HNewFont: HFont;
begin

  DrawRect.Left := 0;
  DrawRect.Right := XSize;
  DrawRect.Top := YSize shr 1;
  DrawRect.Bottom := YSize;

  ACanvas.Font.Size := 20;
  ACanvas.Font.Style := [fsBold];
  ACanvas.Font.Color := clSilver;
  GetObject(ACanvas.Font.Handle, SizeOf(LFont), Addr(LFont));
  LFont.lfEscapement := 45 * 10;
  LFont.lfOrientation := 45 * 10;

  HNewFont := CreateFontIndirect(LFont);
  HOldFont := SelectObject(ACanvas.Handle, HNewFont);

  SetTextAlign(ACanvas.Handle, TA_TOP);
  SetBkMode(ACanvas.Handle, Transparent);

  ACanvas.TextOut(XSize shr 2, (YSize shr 2) + (YSize shr 1),
    Format(COPYRIGHT, [ClassName]));

  HNewFont := SelectObject(ACanvas.Handle, HOldFont);
  DeleteObject(HNewFont);

end;
{$ENDIF}


procedure TCustomPlanner.PrintCol(ACanvas: TCanvas; FromPos, ToPos, FromRow, ToRow: Integer);
var
  XSize, YSize: Integer;
  PositionIndex, RowIndex, SubIndex, GroupIndex, ConflictingCellWidth: Integer;
  NumberOfConflicts: TPoint;
  DrawRect, ARect, NRect, SRect: TRect;
  APlannerItem: TPlannerItem;
  SidebarWidth, HeaderHeight, FooterHeight, GroupHeight, Side: Integer;
  LeftIndent, TopIndent: Integer;
  ColumnWidth, ColumnHeight, GapWidth: Integer;
  PrintPositions, NumCols: Integer;
  DoDraw: Boolean;
  SizedCols: Boolean;
  BottomPen: TPen;
  hdr, a, sa, fa: string;
  XS, YS, ml, hl: Integer;
  CR, hr: TRect;
  CID, CV, CT: string;
  AColorTo: TColor;
  Occupied: Boolean;
  gs: Integer;
  gc: string;

begin
  PrintPositions := (ToPos - FromPos) + 1;

  if Assigned(FOnPrintStart) then
    FOnPrintStart(Self, ACanvas);

  // Get the paper dimensions
  XSize := (ACanvas.ClipRect.Right - ACanvas.ClipRect.Left) - FPrintOptions.FLeftMargin - FPrintOptions.FRightMargin;

  YSize := (ACanvas.ClipRect.Bottom - ACanvas.ClipRect.Top) - FPrintOptions.FHeaderSize - FPrintOptions.FFooterSize - FPrintOptions.TopMargin;

  FHTMLFactor := CanvasToHTMLFactor(Canvas, ACanvas);

  LeftIndent := FPrintOptions.FLeftMargin;
  TopIndent := FPrintOptions.FHeaderSize + FPrintOptions.TopMargin;

  SidebarWidth := 0;
  HeaderHeight := 0;
  FooterHeight := 0;
  GroupHeight := 0;

  if (PositionGroup > 0) then
    GroupIndex := FromPos div PositionGroup
  else
    GroupIndex := 0;

  // Column width
  if FSidebar.Visible then
  begin
    if (FSidebar.Position = spLeftRight) then
      NumCols := PrintPositions + 2
    else
      NumCols := PrintPositions + 1;
  end
  else
    NumCols := PrintPositions;

  SizedCols := (Round(FGrid.ColWidths[1] * (NumCols)) > XSize);

  if SizedCols or FPrintOptions.FFitToPage then
    ColumnWidth := (XSize div NumCols)
  else
    ColumnWidth := FGrid.ColWidths[1];

  if (FPositionGap > 0) and (FSidebar.ShowInPositionGap) then
    GapWidth := Round(FPositionGap / FGrid.ColWidths[1] * ColumnWidth)
  else
    GapWidth := 0;

  // Row Height
  if FHeader.Visible then
    HeaderHeight := Round(YSize * (Header.Height / (FGrid.RowHeights[0] * (ToRow - FromRow + 1))));

  if FFooter.Visible then
    FooterHeight := Round(YSize * (Footer.Height / (FGrid.RowHeights[0] * (ToRow - FromRow + 1))));

  // Double header size when group captions need to be printed
  //  if FHeader.Visible and (PositionGroup > 0) then
  //    GroupHeight := HeaderHeight;

  if FHeader.Visible and (PositionGroup > 0) then
  begin
    GroupHeight := Round(Header.TextHeight / Header.Height * HeaderHeight);
  end;

  YSize := YSize - HeaderHeight - GroupHeight - FooterHeight;

  ColumnHeight := YSize div (ToRow - FromRow + 1);

  if FPrintOptions.CellHeight > 0 then
    ColumnHeight := FPrintOptions.CellHeight;

  if FPrintOptions.CellWidth > 0 then
    ColumnWidth := FPrintOptions.CellWidth;

  if (FPrintOptions.FHeader.Count > 0) or Assigned(FOnPrintHeader) then
  begin
    // Print Header over full size
    DrawRect.Left := LeftIndent;
    DrawRect.Right := LeftIndent + XSize;
    DrawRect.Top := FPrintOptions.TopMargin;
    DrawRect.Bottom := TopIndent;
    ACanvas.Brush.Style := bsClear;
    ACanvas.Font.Assign(FPrintOptions.FHeaderFont);

    if Assigned(FOnPrintHeader) then
      FOnPrintHeader(Self, ACanvas, DrawRect)
    else
    begin
      if Pos('</', FPrintOptions.FHeader.Text) > 0 then
        HTMLDrawEx(ACanvas, FPrintOptions.FHeader.Text, DrawRect,
          PlannerImages, 0, 0, -1, -1, 1, False, False, True, False, True,
          False, False
          , False
          , FHTMLFactor, URLColor, clNone, clNone, clGray, a, sa, fa, XS, YS,
          ml, hl, hr
          , CR, CID, CV, CT, FImageCache, FContainer, Handle
        )
      else
        PrinterDrawString(ACanvas, FPrintOptions.FHeader.Text, DrawRect,
          AlignToFlag(FPrintOptions.FHeaderAlignment));
    end;
  end;

  if (FPrintOptions.FFooter.Count > 0) or Assigned(FOnPrintFooter) then
  begin
    // Print footer over full size
    DrawRect.Left := LeftIndent;
    DrawRect.Right := LeftIndent + XSize;
    DrawRect.Top := YSize + HeaderHeight + GroupHeight +
      FPrintOptions.FHeaderSize + FPrintOptions.TopMargin + FooterHeight;
    DrawRect.Bottom := DrawRect.Top + FPrintOptions.FFooterSize +
      FPrintOptions.TopMargin;
    ACanvas.Brush.Style := bsClear;
    ACanvas.Font.Assign(FPrintOptions.FFooterFont);

    if Assigned(FOnPrintFooter) then
      FOnPrintFooter(Self, ACanvas, DrawRect)
    else
    begin
      if Pos('</', FPrintOptions.FFooter.Text) > 0 then
        HTMLDrawEx(ACanvas, FPrintOptions.FFooter.Text, DrawRect,
          PlannerImages, 0, 0, -1, -1, 1, False, False, True, False, True,
          False, False
          , False
          , FHTMLFactor, URLColor, clNone, clNone, clGray, a, sa, fa, XS, YS,
          ml, hl, hr
          , CR, CID, CV, CT, FImageCache, FContainer, Handle
        )
      else
        PrinterDrawString(ACanvas, FPrintOptions.FFooter.Text, DrawRect,
          AlignToFlag(FPrintOptions.FFooterAlignment));
    end;
  end;

  // Draw the left sidebar
  if FSidebar.Visible and (FSidebar.Position in [spLeft, spLeftRight]) then
  begin
    if SizedCols or FPrintOptions.FFitToPage then
    begin
      SidebarWidth := Round
        (XSize * (FGrid.ColWidths[0] / (FGrid.ColWidths[1] * (PrintPositions))));

      if FSidebar.Position = spLeftRight then
        ColumnWidth := Trunc((XSize - 2 * SidebarWidth) / PrintPositions)
      else
        ColumnWidth := Trunc((XSize - SidebarWidth) / PrintPositions);
    end
    else
      SidebarWidth := Round(FGrid.ColWidths[0] {* FHTMLFactor});

    if FPrintOptions.SidebarWidth > 0 then
      SidebarWidth := FPrintOptions.SidebarWidth;

    for PositionIndex := FromRow to ToRow do
    begin
      DrawRect.Left := LeftIndent;
      DrawRect.Top := TopIndent + HeaderHeight + GroupHeight + ColumnHeight *
        (PositionIndex - FromRow);
      DrawRect.Right := DrawRect.Left + SidebarWidth;
      DrawRect.Bottom := DrawRect.Top + ColumnHeight;

      ACanvas.Font.Assign(Sidebar.Font);
      ACanvas.Brush.Color := Sidebar.Background;

      ACanvas.Font.Assign(Sidebar.Font);

      if (Assigned(FOnPlannerSideProp)) then
        FOnPlannerSideProp(Self, PositionIndex, ACanvas.Brush, ACanvas.Font,
          AColorTo);

      ACanvas.Pen.Color := ACanvas.Brush.Color;
      ACanvas.Pen.Width := PrintOptions.LineWidth;

      if PositionIndex = FromRow then
      begin
        ACanvas.MoveTo(DrawRect.Left, DrawRect.Top);
        ACanvas.LineTo(DrawRect.Right, DrawRect.Top);
      end;

      APlannerItem := Items.FindItemIdx(PositionIndex);

      Occupied := (APlannerItem <> nil) and Sidebar.ShowOccupied;

      if Occupied then
      begin
        ACanvas.Brush.Color := Sidebar.Occupied;
        if Sidebar.OccupiedTo <> clNone then
          DrawGradient(ACanvas, ACanvas.Brush.Color, Sidebar.OccupiedTo, 64,
            DrawRect, True)
        else
          ACanvas.Rectangle(DrawRect.Left, DrawRect.Top, DrawRect.Right,
            DrawRect.Bottom);
      end
      else
      begin
        if Sidebar.BackgroundTo <> clNone then
          DrawGradient(ACanvas, ACanvas.Brush.Color, Sidebar.BackgroundTo, 64,
            DrawRect, True)
        else
          ACanvas.Rectangle(DrawRect.Left, DrawRect.Top, DrawRect.Right,
            DrawRect.Bottom);
      end;

      ACanvas.Pen.Color := Sidebar.SeparatorLineColor;
      ACanvas.Pen.Width := PrintOptions.LineWidth;

      if PositionIndex = FromRow then
      begin
        ACanvas.MoveTo(DrawRect.Left, DrawRect.Top);
        ACanvas.LineTo(DrawRect.Right, DrawRect.Top);
      end;

      InflateRect(DrawRect, -1, -1);

      if (Assigned(FOnPlannerSideDraw)) then
        FOnPlannerSideDraw(Self, ACanvas, DrawRect, PositionIndex)
      else
      begin
        FGrid.PaintSideCol(ACanvas, DrawRect, PositionIndex, 0, 0, False, True);

        if Assigned(FOnPlannerSideDrawAfter) then
          FOnPlannerSideDrawAfter(Self, ACanvas, DrawRect, PositionIndex);
      end;

      ACanvas.Brush.Color := Color;
      ACanvas.Font.Assign(Font);
    end;
  end;

  // Draw the right sidebar
  if FSidebar.Visible and (FSidebar.Position in [spRight, spLeftRight]) then
  begin
    if SizedCols or FPrintOptions.FFitToPage then
    begin
      SidebarWidth := Round(XSize * (FGrid.ColWidths[FGrid.ColCount - 1] /
            (FGrid.ColWidths[1] * (PrintPositions))));

      if FSidebar.Position = spLeftRight then
        ColumnWidth := Trunc((XSize - 2 * SidebarWidth) / PrintPositions)
      else
        ColumnWidth := Trunc((XSize - SidebarWidth) / PrintPositions);
    end
    else
      SidebarWidth := Round(FGrid.ColWidths[FGrid.ColCount - 1]
        {* FHTMLFactor});

    if FPrintOptions.SidebarWidth > 0 then
      SidebarWidth := FPrintOptions.SidebarWidth;

    for PositionIndex := FromRow to ToRow do
    begin
      DrawRect.Left := LeftIndent + (PrintPositions * ColumnWidth);
      if (FSidebar.Position in [spLeft, spLeftRight]) then
        DrawRect.Left := DrawRect.Left + SidebarWidth;

      DrawRect.Top := TopIndent + HeaderHeight + GroupHeight + ColumnHeight *
        (PositionIndex - FromRow);
      DrawRect.Right := DrawRect.Left + SidebarWidth;
      DrawRect.Bottom := DrawRect.Top + ColumnHeight;

      ACanvas.Font.Assign(Sidebar.Font);
      ACanvas.Brush.Color := Sidebar.Background;

      ACanvas.Font.Assign(Sidebar.Font);

      if (Assigned(FOnPlannerSideProp)) then
        FOnPlannerSideProp(Self, PositionIndex, ACanvas.Brush, ACanvas.Font,
          AColorTo);

      ACanvas.Pen.Color := ACanvas.Brush.Color;
      ACanvas.Pen.Width := PrintOptions.LineWidth;

      if PositionIndex = FromRow then
      begin
        ACanvas.MoveTo(DrawRect.Left, DrawRect.Top);
        ACanvas.LineTo(DrawRect.Right, DrawRect.Top);
      end;

      APlannerItem := Items.FindItemIdx(PositionIndex);

      Occupied := (APlannerItem <> nil) and Sidebar.ShowOccupied;

      if Occupied then
      begin
        ACanvas.Brush.Color := Sidebar.Occupied;
        if Sidebar.OccupiedTo <> clNone then
          DrawGradient(ACanvas, ACanvas.Brush.Color, Sidebar.OccupiedTo, 64,
            DrawRect, True)
        else
          ACanvas.Rectangle(DrawRect.Left, DrawRect.Top, DrawRect.Right,
            DrawRect.Bottom);
      end
      else
      begin
        if Sidebar.BackgroundTo <> clNone then
          DrawGradient(ACanvas, ACanvas.Brush.Color, Sidebar.BackgroundTo, 64,
            DrawRect, True)
        else
          ACanvas.Rectangle(DrawRect.Left, DrawRect.Top, DrawRect.Right,
            DrawRect.Bottom);
      end;

      ACanvas.Pen.Color := Sidebar.SeparatorLineColor;
      ACanvas.Pen.Width := PrintOptions.LineWidth;

      if PositionIndex = FromRow then
      begin
        ACanvas.MoveTo(DrawRect.Left, DrawRect.Top);
        ACanvas.LineTo(DrawRect.Right, DrawRect.Top);
      end;

      InflateRect(DrawRect, -1, -1);

      if (Assigned(FOnPlannerSideDraw)) then
        FOnPlannerSideDraw(Self, ACanvas, DrawRect, PositionIndex)
      else
      begin
        FGrid.PaintSideCol(ACanvas, DrawRect, PositionIndex, 0, 0, False, True);

        if Assigned(FOnPlannerSideDrawAfter) then
          FOnPlannerSideDrawAfter(Self, ACanvas, DrawRect, PositionIndex);
      end;

      ACanvas.Brush.Color := Color;
      ACanvas.Font.Assign(Font);
    end;
  end;

  Side := 1;

  if FSidebar.Visible and (FSidebar.Position = spRight) then
  begin
    Side := 0;
    SidebarWidth := 0;
  end;

  // Draw the Header
  if FHeader.Visible then
  begin
    SetBkMode(ACanvas.Handle, Transparent);
    for PositionIndex := FromPos to ToPos do
    begin
      ACanvas.Font.Assign(Header.Font);
      ACanvas.Brush.Color := FColor;

      if (PositionGroup = 1) and (Header.CustomGroups.Count > 0) then
      begin
        gs := Header.GroupSplit(PositionIndex);
        gc := Header.GetGroupCaption(PositionIndex);

        if (gs <> -1) then
        begin
          DrawRect.Left := LeftIndent + SidebarWidth +
            (ColumnWidth * (PositionIndex - FromPos));
          DrawRect.Top := 1 + TopIndent;
          DrawRect.Right := DrawRect.Left + ColumnWidth * gs;

          if DrawRect.Right > LeftIndent + SidebarWidth + ColumnWidth *
            (1 + ToPos - FromPos) then
            DrawRect.Right := LeftIndent + SidebarWidth + ColumnWidth *
              (1 + ToPos - FromPos);

          DrawRect.Bottom := GroupHeight + TopIndent;

          //***
          ACanvas.Brush.Color := FHeader.Color;
          if FHeader.ColorTo <> clNone then
            DrawGradient(ACanvas, ACanvas.Brush.Color, FHeader.ColorTo, 64,
              DrawRect, False)
          else
            ACanvas.Rectangle(DrawRect.Left, DrawRect.Top, DrawRect.Right,
              DrawRect.Bottom);

          RectLine(ACanvas, DrawRect, GridLineColor, PrintOptions.LineWidth);

          InflateRect(DrawRect, -1, -1);

          ACanvas.Brush.Style := bsClear;

          ACanvas.Font.Assign(Header.GroupFont);

          hdr := gc;

          if Pos('</', hdr) > 0 then
          begin
            HTMLDrawEx(ACanvas, hdr, DrawRect, PlannerImages, 0, 0, -1, -1, 1,
              False, False, True, False, True, False, False
              , False
              , FHTMLFactor, URLColor, clNone, clNone, clGray, a, sa, fa, XS,
              YS, ml, hl, hr
              , CR, CID, CV, CT, FImageCache, FContainer, Handle
            );
          end
          else
          begin
            PrinterDrawString(ACanvas, CLFToLF(hdr), DrawRect,
              AlignToFlag(Header.Alignment) OR VAlignToFlag(Header.VAlignment)
                OR WordWrapToFlag(hdr, Header.WordWrap));
          end;

          hdr := '';
          ACanvas.Font.Assign(Header.Font);
        end;
      end;

      if (PositionGroup > 0) and (Header.CustomGroups.Count = 0) then
      begin
        if (PositionIndex mod PositionGroup = 0) or (PositionIndex = FromPos)
          then
        begin
          DrawRect.Left := LeftIndent + SidebarWidth +
            (ColumnWidth * (PositionIndex - FromPos));
          DrawRect.Top := 1 + TopIndent;
          DrawRect.Right := DrawRect.Left + ColumnWidth *
            (PositionGroup - (PositionIndex mod PositionGroup));

          if DrawRect.Right > LeftIndent + SidebarWidth + ColumnWidth *
            (1 + ToPos - FromPos) then
            DrawRect.Right := LeftIndent + SidebarWidth + ColumnWidth *
              (1 + ToPos - FromPos);

          DrawRect.Bottom := GroupHeight + TopIndent;

          ACanvas.Brush.Color := FHeader.Color;
          if FHeader.ColorTo <> clNone then
            DrawGradient(ACanvas, ACanvas.Brush.Color, FHeader.ColorTo, 64,
              DrawRect, False)
          else
            ACanvas.Rectangle(DrawRect.Left, DrawRect.Top, DrawRect.Right,
              DrawRect.Bottom);

          RectLine(ACanvas, DrawRect, GridLineColor, PrintOptions.LineWidth);

          if Header.GroupCaptions.Count > GroupIndex then
          begin
            InflateRect(DrawRect, -1, -1);

            ACanvas.Font.Assign(Header.GroupFont);
            ACanvas.Brush.Style := bsClear;

            hdr := Header.GroupCaptions[GroupIndex];
            if Pos('</', hdr) > 0 then
            begin
              HTMLDrawEx(ACanvas, hdr, DrawRect, PlannerImages, 0, 0, -1, -1,
                1, False, False, True, False, True, False, False
                , False
                , FHTMLFactor, URLColor, clNone, clNone, clGray, a, sa, fa, XS,
                YS, ml, hl, hr
                , CR, CID, CV, CT, FImageCache, FContainer, Handle
              );
            end
            else
            begin
              PrinterDrawString(ACanvas, CLFToLF(hdr), DrawRect,
                AlignToFlag(Header.Alignment) OR VAlignToFlag
                  (Header.VAlignment) OR WordWrapToFlag(hdr,
                  Header.WordWrap));
            end;

            ACanvas.Font.Assign(Header.Font);
          end;
          Inc(GroupIndex);
        end;

      end;

      DrawRect.Left := LeftIndent + SidebarWidth +
        (ColumnWidth * (PositionIndex - FromPos));
      DrawRect.Top := 4 + PrintOptions.LineWidth + TopIndent + GroupHeight;
      DrawRect.Right := DrawRect.Left + ColumnWidth;
      DrawRect.Bottom := HeaderHeight + GroupHeight + TopIndent;

      ACanvas.Brush.Color := FHeader.Color;
      if FHeader.ColorTo <> clNone then
        DrawGradient(ACanvas, ACanvas.Brush.Color, FHeader.ColorTo, 64,
          DrawRect, False)
      else
        ACanvas.Rectangle(DrawRect.Left, DrawRect.Top, DrawRect.Right,
          DrawRect.Bottom);

      RectLine(ACanvas, DrawRect, GridLineColor, PrintOptions.LineWidth);

      InflateRect(DrawRect, -1, -1);

      DoDraw := True;
      ACanvas.Brush.Color := FColor;

      if Assigned(FOnPlannerHeaderDraw) then
      begin
        Font := Self.Font;
        ACanvas.Brush.Color := FColor;
        ACanvas.Pen.Color := FHeader.FLineColor;
        ACanvas.Pen.Width := 1;
        FOnPlannerHeaderDraw(Self, ACanvas, DrawRect, PositionIndex + 1,
          DoDraw);
      end;

      if DoDraw then
      begin
        DrawRect.Bottom := DrawRect.Top + Round
          (HeaderHeight * Header.TextHeight / Header.Height);

        ACanvas.Brush.Style := bsClear;

        if Header.Captions.Count > PositionIndex + Side then
        begin
          hdr := Header.Captions[PositionIndex + Side];

          if Pos('</', hdr) > 0 then
          begin
            HTMLDrawEx(ACanvas, hdr, DrawRect, PlannerImages, 0, 0, -1, -1, 1,
              False, False, True, False, True, False, False
              , False
              , FHTMLFactor, URLColor, clNone, clNone, clGray, a, sa, fa, XS,
              YS, ml, hl, hr
              , CR, CID, CV, CT, FImageCache, FContainer, Handle
            );
          end
          else
          begin
            PrinterDrawString(ACanvas, CLFToLF(hdr), DrawRect,
              AlignToFlag(Header.Alignment) OR VAlignToFlag(Header.VAlignment)
                OR WordWrapToFlag(hdr, Header.WordWrap));
          end;
        end;

        APlannerItem := Items.HeaderFirst(PositionIndex);
        while Assigned(APlannerItem) do
        begin
          DrawRect.Left := DrawRect.Left + 2;
          DrawRect.Right := DrawRect.Right - 2;
          DrawRect.Top := DrawRect.Bottom;
          DrawRect.Bottom := DrawRect.Top + Round(HeaderHeight * Header.ItemHeight / Header.Height);

          APlannerItem.FRepainted := False;
          // Paint full Items here
          FGrid.PaintItemCol(ACanvas, DrawRect, APlannerItem, True, False);
          APlannerItem := Items.HeaderNext(PositionIndex);
        end;
      end;

    end;
  end;

  // Draw the background cells
  for RowIndex := FromRow to ToRow do
    for PositionIndex := FromPos to ToPos do
    begin
      // nr. of Items at cell
      NumberOfConflicts := Items.NumItem(RowIndex, RowIndex, PositionIndex);

      // Cell bounding rect
      DrawRect.Left := LeftIndent + SidebarWidth + ColumnWidth * (PositionIndex - FromPos);
      DrawRect.Top := TopIndent + HeaderHeight + GroupHeight + ColumnHeight * (RowIndex - FromRow);
      DrawRect.Right := DrawRect.Left + ColumnWidth;
      DrawRect.Bottom := DrawRect.Top + ColumnHeight;
      RectLineEx(ACanvas, DrawRect, GridLineColor, PrintOptions.LineWidth);

      BottomPen := TPen.Create;
      BottomPen.Assign(ACanvas.Pen);

      BottomPen.Width := PrintOptions.LineWidth;
      BottomPen.Color := GridLineColor;

      if (Mode.PlannerType = plDay) then
      begin
        if ((RowIndex + 1 + Display.DisplayStart)
            * Display.DisplayUnit mod 60 = 0) then
          BottomPen.Color := Display.HourLineColor;
      end;

      if Assigned(FOnPlannerBottomLine) then
        FOnPlannerBottomLine(Self, RowIndex, PositionIndex, BottomPen);

      GetCellBrush(PositionIndex, RowIndex, ACanvas.Brush);
      ACanvas.Pen.Color := BottomPen.Color;
      ACanvas.Pen.Width := BottomPen.Width;
      ACanvas.MoveTo(DrawRect.Left, DrawRect.Bottom);
      ACanvas.LineTo(DrawRect.Right, DrawRect.Bottom);
      BottomPen.Free;

      ACanvas.Pen.Color := GridLineColor;
      ACanvas.Pen.Width := PrintOptions.LineWidth;

      if GapWidth > 0 then
      begin
        SRect := DrawRect;
        SRect.Right := SRect.Left + GapWidth;
        RectLine(ACanvas, SRect, GridLineColor, PrintOptions.LineWidth);
        InflateRect(SRect, -1, -1);
        ACanvas.Rectangle(SRect.Left, SRect.Top, SRect.Right, SRect.Bottom);

        ACanvas.Font.Assign(Sidebar.Font);

        if (Assigned(FOnPlannerSideProp)) then
          FOnPlannerSideProp(Self, PositionIndex, ACanvas.Brush, ACanvas.Font,
            AColorTo);

        FGrid.PaintSideCol(ACanvas, SRect, RowIndex, PositionIndex, 0, False, True);
        DrawRect.Left := DrawRect.Left + GapWidth;
      end;

      if (BackgroundColor[PositionIndex, RowIndex] <> clNone) then
        ACanvas.Brush.Color := BackgroundColor[PositionIndex, RowIndex];

      //if Selected[PositionIndex, RowIndex] then
      //  ACanvas.Brush.Color := DisjunctSelectColor;

      InflateRect(DrawRect, -1, -1);

      if (Assigned(FOnPlannerBkgProp)) then
        FOnPlannerBkgProp(Self, RowIndex, PositionIndex, ACanvas.Brush, ACanvas.Pen);

      ACanvas.FillRect(DrawRect);
      ACanvas.Brush.Color := Color;

      APlannerItem := Items.FindBackground(RowIndex, PositionIndex);

      if Assigned(APlannerItem) then
      begin
        ARect := DrawRect;
        InflateRect(ARect, 1, 1);
        NRect.Top := ARect.Top - ((RowIndex - Max(FromRow,
              APlannerItem.ItemBegin)) * (ARect.Bottom - ARect.Top));

        NRect.Bottom := ARect.Bottom +
          ((Min(ToRow + 1, APlannerItem.ItemEnd) - RowIndex - 1) *
            (ARect.Bottom - ARect.Top));
        NRect.Left := ARect.Left;
        NRect.Right := ARect.Right;

        APlannerItem.Repainted := False;
        FGrid.PaintItemCol(ACanvas, NRect, APlannerItem, True, False);
      end;

      if (Assigned(FOnPlannerBkgDraw)) then
        FOnPlannerBkgDraw(Self, ACanvas, DrawRect, RowIndex, PositionIndex);
    end;

  // Draw the normal cells
  for RowIndex := FromRow to ToRow do
    for PositionIndex := FromPos to ToPos do
    begin
      // nr. of Items at cell
      NumberOfConflicts := Items.NumItem(RowIndex, RowIndex, PositionIndex);

      // Cell bounding rect
      DrawRect.Left := LeftIndent + SidebarWidth + GapWidth + ColumnWidth *
        (PositionIndex - FromPos);
      DrawRect.Top := TopIndent + HeaderHeight + GroupHeight + ColumnHeight *
        (RowIndex - FromRow);
      DrawRect.Right := DrawRect.Left + ColumnWidth - GapWidth;
      DrawRect.Bottom := DrawRect.Top + ColumnHeight;

      for SubIndex := 0 to NumberOfConflicts.Y do
      begin
        ARect := DrawRect;
        //InflateRect(ARect,1,1);
        if (NumberOfConflicts.Y > 0) then
        begin
          ConflictingCellWidth := (ARect.Right - ARect.Left) div
            (NumberOfConflicts.Y);
          ARect.Left := ARect.Left + SubIndex * ConflictingCellWidth;
          ARect.Right := ARect.Left + ConflictingCellWidth;
        end;

        APlannerItem := Items.FindItemIndex(RowIndex, PositionIndex, SubIndex);
        if (APlannerItem <> nil) then
        begin
          NRect.Top := ARect.Top - ((RowIndex - Max(FromRow,
                APlannerItem.ItemBegin)) * (ARect.Bottom - ARect.Top));
          NRect.Bottom := ARect.Bottom +
            ((Min(ToRow + 1, APlannerItem.ItemEnd) - RowIndex - 1) *
              (ARect.Bottom - ARect.Top));
          NRect.Left := ARect.Left;
          NRect.Right := ARect.Right;
          APlannerItem.Repainted := False;
          FGrid.PaintItemCol(ACanvas, NRect, APlannerItem, True, False);
          ARect.Left := ARect.Right - FItemGap;
          {item found, paint only extra rect at Right}
        end;
      end;
    end;

  // Draw the Footer
  if FFooter.Visible then
  begin
    SetBkMode(ACanvas.Handle, Transparent);
    for PositionIndex := FromPos to ToPos do
    begin
      ACanvas.Font.Assign(Footer.Font);
      ACanvas.Brush.Color := FColor;

      DrawRect.Left := LeftIndent + SidebarWidth +
        (ColumnWidth * (PositionIndex - FromPos));
      DrawRect.Top := TopIndent + HeaderHeight + GroupHeight + ColumnHeight *
        (ToRow - FromRow + 1);
      DrawRect.Right := DrawRect.Left + ColumnWidth;
      DrawRect.Bottom := DrawRect.Top + FooterHeight;

      RectLine(ACanvas, DrawRect, GridLineColor, PrintOptions.LineWidth);

      InflateRect(DrawRect, -1, -1);

      DoDraw := True;
      ACanvas.Brush.Color := FColor;

      if Assigned(FOnPlannerFooterDraw) then
      begin
        Font := Self.Font;
        ACanvas.Brush.Color := FColor;
        ACanvas.Pen.Color := FFooter.FLineColor;
        ACanvas.Pen.Width := PrintOptions.LineWidth;
        FOnPlannerFooterDraw(Self, ACanvas, DrawRect, PositionIndex + 1,
          DoDraw);
      end;

      if DoDraw then
      begin
        DrawRect.Bottom := DrawRect.Top + FooterHeight;

        if Footer.Captions.Count > PositionIndex + Side then
        begin
          hdr := Footer.Captions[PositionIndex + Side];
          if Pos('</', hdr) > 0 then
          begin
            HTMLDrawEx(ACanvas, hdr, DrawRect, PlannerImages, 0, 0, -1, -1, 1,
              False, False, True, False, True, False, False
              , False
              , FHTMLFactor, URLColor, clNone, clNone, clGray, a, sa, fa, XS,
              YS, ml, hl, hr
              , CR, CID, CV, CT, FImageCache, FContainer, Handle
            );
          end
          else
            PrinterDrawString(ACanvas, CLFToLF(hdr), DrawRect,
              AlignToFlag(Footer.Alignment));
        end;
      end;
    end;
  end;

  FHTMLFactor := 1.0;
{$IFDEF FREEWARE}
  PrintFreewareNotice(ACanvas, XSize, YSize, Self.ClassName);
{$ENDIF}
end;

procedure TCustomPlanner.PrintRow(ACanvas: TCanvas; FromPos, ToPos, FromCol, ToCol: Integer);
var
  XSize, YSize: Integer;
  PositionIndex, ColIndex, SubIndex, ConflictingCellWidth: Integer;
  NumberOfConflicts: TPoint;
  DrawRect, ARect, NRect: TRect;
  APlannerItem: TPlannerItem;
  SidebarWidth, HeaderHeight, GroupHeight, GroupIndex: Integer;
  LeftIndent, TopIndent: Integer;
  ColumnWidth, ColumnHeight: Integer;
  PrintPositions, NumRows: Integer;
  DoDraw: Boolean;
  SizedRows: Boolean;
  BottomPen: TPen;
  HeadIndent, MaxRight: Integer;
  hdr, a, sa, fa: string;
  XS, YS, ml, hl: Integer;
  CR, hr: TRect;
  CID, CV, CT: string;
  AColorTo: TColor;
  gs: Integer;
  gc: string;
  lf: TLogFont;
  tf: TFont;
  th: integer;

begin
  PrintPositions := (ToPos - FromPos) + 1;

  if Assigned(FOnPrintStart) then
    FOnPrintStart(Self, ACanvas);

  XSize := ACanvas.ClipRect.Right - ACanvas.ClipRect.Left -
    FPrintOptions.FLeftMargin - FPrintOptions.FRightMargin;
  YSize := ACanvas.ClipRect.Bottom - ACanvas.ClipRect.Top -
    FPrintOptions.FHeaderSize - FPrintOptions.FFooterSize;

  FHTMLFactor := CanvasToHTMLFactor(Canvas, ACanvas);

  if FSidebar.Visible then
    NumRows := PrintPositions + 1
  else
    NumRows := PrintPositions;

  SizedRows := (Round(FGrid.RowHeights[1] * NumRows) > YSize);

  if SizedRows or FPrintOptions.FFitToPage then
    ColumnHeight := (YSize div NumRows)
  else
    ColumnHeight := FGrid.RowHeights[1];

  LeftIndent := FPrintOptions.FLeftMargin;
  TopIndent := FPrintOptions.FHeaderSize + FPrintOptions.TopMargin;

  HeadIndent := LeftIndent;

  // Draw Header
  if FPrintOptions.FHeader.Count > 0 then
  begin
    DrawRect.Left := LeftIndent;
    DrawRect.Right := XSize + LeftIndent;
    DrawRect.Top := FPrintOptions.TopMargin;
    DrawRect.Bottom := TopIndent;
    ACanvas.Brush.Style := bsClear;
    ACanvas.Font.Assign(FPrintOptions.FHeaderFont);
    SetBkMode(ACanvas.Handle, Transparent);
    if Pos('</', FPrintOptions.FHeader.Text) > 0 then
      HTMLDrawEx(ACanvas, FPrintOptions.FHeader.Text, DrawRect, PlannerImages,
        0, 0, -1, -1, 1, False, False, True, False, True, False, False
        , False
        , FHTMLFactor, URLColor, clNone, clNone, clGray, a, sa, fa, XS, YS, ml,
        hl, hr
        , CR, CID, CV, CT, FImageCache, FContainer, Handle
      )
    else
      PrinterDrawString(ACanvas, FPrintOptions.FHeader.Text, DrawRect,
        AlignToFlag(FPrintOptions.FHeaderAlignment));
  end;

  // Draw Footer
  if (FPrintOptions.FFooter.Count > 0) or Assigned(FOnPrintFooter) then
  begin
    DrawRect.Left := LeftIndent;
    DrawRect.Right := LeftIndent + XSize;
    DrawRect.Top := YSize + FPrintOptions.TopMargin;
    DrawRect.Bottom := YSize + FPrintOptions.FFooterSize +
      FPrintOptions.TopMargin;

    DrawRect.Top := YSize + FPrintOptions.FHeaderSize;
    DrawRect.Bottom := DrawRect.Top + FPrintOptions.FFooterSize;
    ACanvas.Brush.Style := bsClear;
    ACanvas.Font.Assign(FPrintOptions.FFooterFont);
    SetBkMode(ACanvas.Handle, Transparent);
    if Assigned(FOnPrintFooter) then
      FOnPrintFooter(Self, ACanvas, DrawRect)
    else
    begin
      if Pos('</', FPrintOptions.FFooter.Text) > 0 then
        HTMLDrawEx(ACanvas, FPrintOptions.FFooter.Text, DrawRect,
          PlannerImages, 0, 0, -1, -1, 1, False, False, True, False, True,
          False, False
          , False
          , FHTMLFactor, URLColor, clNone, clNone, clGray, a, sa, fa, XS, YS,
          ml, hl, hr
          , CR, CID, CV, CT, FImageCache, FContainer, Handle
        )
      else
        PrinterDrawString(ACanvas, FPrintOptions.FFooter.Text, DrawRect,
          AlignToFlag(FPrintOptions.FFooterAlignment));
    end;
  end;

  SidebarWidth := 0;
  GroupHeight := 0;

  if PositionGroup > 0 then
    GroupIndex := FromPos div PositionGroup
  else
    GroupIndex := 0;

  HeaderHeight := Round(XSize * (Header.Height / (FGrid.ColWidths[0] * (ToCol - FromCol + 1))));

  //if PrintOptions.HeaderSize > 0 then
  //  HeaderHeight := PrintOptions.HeaderSize;

  if FHeader.Visible and (PositionGroup > 0) then
    GroupHeight := HeaderHeight;

  // XSize := XSize - HeaderHeight - GroupHeight;

  ColumnWidth := (XSize - HeaderHeight) div (ToCol - FromCol + 1);

  if FPrintOptions.CellHeight > 0 then
    ColumnHeight := FPrintOptions.CellHeight;

  if FPrintOptions.CellWidth > 0 then
    ColumnWidth := FPrintOptions.CellWidth;

  // Print the SideBar on Top
  if Sidebar.Visible then
  begin
    if SizedRows or FPrintOptions.FitToPage then
      SidebarWidth := Round(YSize * (FGrid.RowHeights[0] / (FGrid.RowHeights[1] * (PrintPositions))))
    else
      SidebarWidth := Round(FGrid.RowHeights[0] {* FHTMLFactor});

    if FPrintOptions.SidebarWidth > 0 then
      SidebarWidth := FPrintOptions.SidebarWidth;

    for ColIndex := FromCol to ToCol do
    begin
      DrawRect.Top := TopIndent;
      DrawRect.Left := LeftIndent + HeaderHeight + ColumnWidth *
        (ColIndex - FromCol);
      DrawRect.Bottom := DrawRect.Top + SidebarWidth;
      DrawRect.Right := DrawRect.Left + ColumnWidth;

      ACanvas.Font.Assign(Sidebar.Font);
      ACanvas.Brush.Color := Sidebar.Background;

      if (Assigned(FOnPlannerSideProp)) then
        FOnPlannerSideProp(Self, ColIndex, ACanvas.Brush, ACanvas.Font,
          AColorTo);

      ACanvas.Pen.Color := ACanvas.Brush.Color;
      ACanvas.Pen.Width := PrintOptions.LineWidth;

      ACanvas.Rectangle(DrawRect.Left, DrawRect.Top, DrawRect.Right,
        DrawRect.Bottom);

      InflateRect(DrawRect, -1, -1);

      ACanvas.Pen.Color := Sidebar.SeparatorLineColor;
      ACanvas.Pen.Width := PrintOptions.LineWidth;

      if (Assigned(FOnPlannerSideDraw)) then
        FOnPlannerSideDraw(Self, ACanvas, DrawRect, ColIndex)
      else
      begin
        FGrid.PaintSideRow(ACanvas, DrawRect, ColIndex, 0, False, True,
          ColumnWidth);

        if Assigned(FOnPlannerSideDrawAfter) then
          FOnPlannerSideDrawAfter(Self, ACanvas, DrawRect, ColIndex);
      end;

      ACanvas.Brush.Color := Color;
      ACanvas.Font.Assign(Font);
    end;
  end;

  // Draw the Header
  if FHeader.Visible then
  begin
    SetBkMode(ACanvas.Handle, Transparent);
    for PositionIndex := FromPos to ToPos do
    begin
      ACanvas.Font.Assign(Header.Font);

      if (PositionGroup = 1) and (Header.CustomGroups.Count > 0) then
      begin
        gs := Header.GroupSplit(PositionIndex);
        gc := Header.GetGroupCaption(PositionIndex);

        if gs <> -1 then
        begin
          DrawRect.Top := TopIndent + SidebarWidth + (ColumnHeight * (PositionIndex - FromPos));
          DrawRect.Left := 1 + LeftIndent;
          DrawRect.Right := (GroupHeight div 2) + LeftIndent;
          DrawRect.Bottom := DrawRect.Top + ColumnHeight * gs;

          if DrawRect.Bottom > TopIndent + SidebarWidth + ColumnHeight * (1 + ToPos - FromPos) then
            DrawRect.Bottom := TopIndent + SidebarWidth + ColumnHeight * (1 + ToPos - FromPos);

          ACanvas.Brush.Color := FHeader.Color;
          if FHeader.ColorTo <> clNone then
            DrawGradient(ACanvas, ACanvas.Brush.Color, FHeader.ColorTo, 64,
              DrawRect, True)
          else
            ACanvas.Rectangle(DrawRect.Left, DrawRect.Top, DrawRect.Right,
              DrawRect.Bottom);

          RectLine(ACanvas, DrawRect, GridLineColor, PrintOptions.LineWidth);

          InflateRect(DrawRect, -1, -1);

          ACanvas.Font.Assign(Header.GroupFont);

          hdr := gc;

          if Pos('</', hdr) > 0 then
          begin
            HTMLDrawEx(ACanvas, hdr, DrawRect, PlannerImages, 0, 0, -1, -1, 1,
              False, False, True, False, True, False, False
              , False
              , FHTMLFactor, URLColor, clNone, clNone, clGray, a, sa, fa, XS,
              YS, ml, hl, hr
              , CR, CID, CV, CT, FImageCache, FContainer, Handle
            );
          end
          else
          begin
            PrinterDrawString(ACanvas, CLFToLF(hdr), DrawRect,
              AlignToFlag(Header.Alignment));
          end;

          hdr := '';

          ACanvas.Font.Assign(Header.Font);

        end;
      end;

      if (PositionGroup > 1) and (Header.CustomGroups.Count = 0) then
      begin
        if (PositionIndex mod PositionGroup = 0) or (PositionIndex = FromPos) then
        begin
          DrawRect.Top := TopIndent + SidebarWidth +
            (ColumnHeight * (PositionIndex - FromPos));
          DrawRect.Left := 1 + LeftIndent;
          DrawRect.Right := (GroupHeight div 2) + LeftIndent;

          DrawRect.Bottom := DrawRect.Top + ColumnHeight *
            (PositionGroup - (PositionIndex mod PositionGroup));

          if DrawRect.Bottom > TopIndent + SidebarWidth + ColumnHeight *
            (1 + ToPos - FromPos) then
            DrawRect.Bottom := TopIndent + SidebarWidth + ColumnHeight *
              (1 + ToPos - FromPos);

          ACanvas.Brush.Color := FHeader.Color;
          if FHeader.ColorTo <> clNone then
            DrawGradient(ACanvas, ACanvas.Brush.Color, FHeader.ColorTo, 64,
              DrawRect, True)
          else
            ACanvas.Rectangle(DrawRect.Left, DrawRect.Top, DrawRect.Right,
              DrawRect.Bottom);

          RectLine(ACanvas, DrawRect, GridLineColor, PrintOptions.LineWidth);

          if Header.GroupCaptions.Count > GroupIndex then
          begin
            InflateRect(DrawRect, -1, -1);

            ACanvas.Font.Assign(Header.GroupFont);

            hdr := Header.GroupCaptions[GroupIndex];
            if Pos('</', hdr) > 0 then
            begin
              HTMLDrawEx(ACanvas, hdr, DrawRect, PlannerImages, 0, 0, -1, -1,
                1, False, False, True, False, True, False, False
                , False
                , FHTMLFactor, URLColor, clNone, clNone, clGray, a, sa, fa, XS,
                YS, ml, hl, hr
                , CR, CID, CV, CT, FImageCache, FContainer, Handle);
            end
            else
            begin
              if Header.RotateGroupOnLeft then
              begin
                tf := TFont.Create;
                try
                  tf.Assign(Header.GroupFont);
                  GetObject(tf.Handle, SizeOf(lf), @lf);
                  lf.lfEscapement := 900;
                  lf.lfOrientation := 900;
                  tf.Handle := CreateFontIndirect(lf);
                  ACanvas.Font.Assign(tf);
                  ACanvas.TextOut(DrawRect.Left - 4, DrawRect.Bottom, CLFToLF(hdr));
                finally
                  tf.Free;
                end;
              end
              else
                PrinterDrawString(ACanvas, CLFToLF(hdr), DrawRect, AlignToFlag(Header.Alignment));
            end;

            hdr := '';

            ACanvas.Font.Assign(Header.Font);
          end;
          Inc(GroupIndex);
        end;
      end;

      DrawRect.Top := TopIndent + SidebarWidth + ColumnHeight *
        (PositionIndex - FromPos);
      DrawRect.Left := 1 + LeftIndent + (GroupHeight div 2);
      DrawRect.Bottom := DrawRect.Top + ColumnHeight;
      DrawRect.Right := HeaderHeight + LeftIndent;

      ACanvas.Brush.Color := FHeader.Color;
      if FHeader.ColorTo <> clNone then
        DrawGradient(ACanvas, ACanvas.Brush.Color, FHeader.ColorTo, 64,
          DrawRect, True)
      else
        ACanvas.Rectangle(DrawRect.Left, DrawRect.Top, DrawRect.Right,
          DrawRect.Bottom);

      RectLine(ACanvas, DrawRect, GridLineColor, PrintOptions.LineWidth);

      HeadIndent := DrawRect.Right;

      InflateRect(DrawRect, -1, -1);

      DoDraw := True;
      if Assigned(FOnPlannerHeaderDraw) then
      begin
        Font := Self.Font;
        ACanvas.Brush.Color := FColor;
        ACanvas.Pen.Color := FHeader.FLineColor;
        ACanvas.Pen.Width := PrintOptions.LineWidth;
        FOnPlannerHeaderDraw(Self, ACanvas, DrawRect, PositionIndex + 1, DoDraw);
      end;

      if DoDraw then
      begin
        DrawRect.Bottom := DrawRect.Top + Round
          (HeaderHeight * Header.TextHeight / Header.Height);

        ACanvas.Brush.Style := bsClear;

        if (FSidebar.Visible) then
        begin
          if Header.Captions.Count > PositionIndex + 1 then
          begin
            hdr := Header.Captions[PositionIndex + 1];

            if pos('</',hdr) > 0 then
            begin
              HTMLDrawEx(ACanvas, hdr, DrawRect, PlannerImages, 0, 0, -1, -1, 1, False, False,
                True, False, True, False, False
                ,False
                , FHTMLFactor, URLColor, clNone, clNone, clGray, a, sa, fa, XS, YS, ml, hl, hr
                , cr, CID, CV, CT, FImageCache, FContainer, Handle
                );
            end
            else
              PrinterDrawString(ACanvas,CLFToLF(hdr),

            DrawRect, AlignToFlag(Header.Alignment));
            ACanvas.Font.Assign(Header.Font);
          end;

          (*
          if Header.Captions.Count > PositionIndex + 1 then
          begin
            PrinterDrawString(ACanvas,
              CLFToLF(Header.Captions[PositionIndex + 1]), DrawRect,
              AlignToFlag(Header.Alignment))
          end;
          *)
        end
        else
        begin
          if Header.Captions.Count > PositionIndex + 1 then
            PrinterDrawString(ACanvas, Header.Captions[PositionIndex + 1],
              DrawRect, AlignToFlag(Header.Alignment));
        end;

        APlannerItem := Items.HeaderFirst(PositionIndex);
        while Assigned(APlannerItem) do
        begin
          DrawRect.Left := DrawRect.Left + 2;
          DrawRect.Right := DrawRect.Right - 2;
          DrawRect.Top := DrawRect.Bottom;
          DrawRect.Bottom := DrawRect.Top + Round
            (HeaderHeight * Header.ItemHeight / Header.Height);

          APlannerItem.FRepainted := False;
          {Paint full Items here}
          FGrid.PaintItemCol(Canvas, DrawRect, APlannerItem, True, False);
          APlannerItem := Items.HeaderNext(PositionIndex);
        end;
      end;

    end;
  end;

  // Draw the background cells

  for ColIndex := FromCol to ToCol do
    for PositionIndex := FromPos to ToPos do
    begin
      // Nr. of Items at cell
      NumberOfConflicts := Items.NumItem(ColIndex, ColIndex, PositionIndex);

      // Cell bounding rect
      DrawRect.Top := TopIndent + SidebarWidth + ColumnHeight *
        (PositionIndex - FromPos);
      DrawRect.Left := LeftIndent + HeaderHeight + ColumnWidth *
        (ColIndex - FromCol);
      DrawRect.Bottom := DrawRect.Top + ColumnHeight;
      DrawRect.Right := DrawRect.Left + ColumnWidth;

      if DrawRect.Left < HeadIndent then
        DrawRect.Left := HeadIndent;

      if DrawRect.Right > XSize then
        DrawRect.Right := XSize;

      GetCellBrush(PositionIndex, ColIndex, ACanvas.Brush);

      if BackgroundColor[ColIndex, PositionIndex] <> clNone then
        ACanvas.Brush.Color := BackgroundColor[ColIndex, PositionIndex];

      //if Selected[ColIndex, PositionIndex] then
      //  ACanvas.Brush.Color := DisjunctSelectColor;

      RectLineExExEx(ACanvas, DrawRect, GridLineColor, PrintOptions.LineWidth);

      BottomPen := TPen.Create;
      BottomPen.Assign(ACanvas.Pen);

      BottomPen.Width := PrintOptions.LineWidth;
      BottomPen.Color := GridLineColor;

      if (Assigned(FOnPlannerBkgProp)) then
        FOnPlannerBkgProp(Self, ColIndex, PositionIndex, ACanvas.Brush, ACanvas.Pen);

      //InflateRect(DrawRect, -1, -1);
      ACanvas.FillRect(DrawRect);
      ACanvas.Brush.Color := Color;

      if (Mode.PlannerType = plDay) then
      begin
        if ((ColIndex + 1 + Display.DisplayStart) * Display.DisplayUnit mod 60 = 0) then
          BottomPen.Color := Display.HourLineColor;
      end;

      if Assigned(FOnPlannerBottomLine) then
        FOnPlannerBottomLine(Self, ColIndex, PositionIndex, BottomPen);

      ACanvas.Pen.Color := BottomPen.Color;
      ACanvas.Pen.Width := BottomPen.Width;
      ACanvas.MoveTo(DrawRect.Right - (BottomPen.Width div 2), DrawRect.Top);
      ACanvas.LineTo(DrawRect.Right - (BottomPen.Width div 2), DrawRect.Bottom);
      ACanvas.Pen.Width := PrintOptions.LineWidth;
      BottomPen.Free;

      {
      if ColIndex = ToCol then
      begin
        ACanvas.MoveTo(DrawRect.Right, DrawRect.Top);
        ACanvas.LineTo(DrawRect.Right, DrawRect.Bottom);
      end;

      if PositionIndex = ToPos then
      begin
        ACanvas.MoveTo(DrawRect.Left, DrawRect.Bottom);
        ACanvas.LineTo(DrawRect.Right, DrawRect.Bottom);
      end;
      }

      APlannerItem := Items.FindBackground(ColIndex, PositionIndex);

      if Assigned(APlannerItem) then
      begin
        ARect := DrawRect;
        InflateRect(DrawRect, 1, 1);

        NRect.Left := ARect.Left - ((ColIndex - APlannerItem.ItemBegin) *
            (ARect.Right - ARect.Left));
        NRect.Right := ARect.Right + ((APlannerItem.ItemEnd - ColIndex - 1) *
            (ARect.Right - ARect.Left));
        NRect.Top := ARect.Top;
        NRect.Bottom := ARect.Bottom;

        if NRect.Left < HeadIndent then
          NRect.Left := HeadIndent;

        if NRect.Right > XSize then
          NRect.Right := XSize;

        APlannerItem.Repainted := False;
        FGrid.PaintItemRow(ACanvas, NRect, APlannerItem, True, False);
      end;

      if (Assigned(FOnPlannerBkgDraw)) then
        FOnPlannerBkgDraw(Self, ACanvas, DrawRect, ColIndex, PositionIndex);
    end;

  // Draw the normal cells
  for ColIndex := FromCol to ToCol do
    for PositionIndex := FromPos to ToPos do
    begin
      // Nr. of Items at cell
      NumberOfConflicts := Items.NumItem(ColIndex, ColIndex, PositionIndex);

      // Cell bounding rect
      DrawRect.Top := TopIndent + SidebarWidth + ColumnHeight *
        (PositionIndex - FromPos);
      DrawRect.Left := LeftIndent + HeaderHeight + ColumnWidth *
        (ColIndex - FromCol);
      DrawRect.Bottom := DrawRect.Top + ColumnHeight;
      DrawRect.Right := DrawRect.Left + ColumnWidth;

      if DrawRect.Left < HeadIndent then
        DrawRect.Left := HeadIndent;

      for SubIndex := 0 to NumberOfConflicts.Y do
      begin
        ARect := DrawRect;
        //InflateRect(DrawRect, 1, 1);

        if (NumberOfConflicts.Y > 0) then
        begin
          ConflictingCellWidth := (ARect.Bottom - ARect.Top) div
            (NumberOfConflicts.Y);
          ARect.Top := ARect.Top + SubIndex * ConflictingCellWidth;
          ARect.Bottom := ARect.Top + ConflictingCellWidth;
        end;

        APlannerItem := Items.FindItemIndex(ColIndex, PositionIndex, SubIndex);

        if (APlannerItem <> nil) then
        begin
          NRect.Left := ARect.Left - ((ColIndex - APlannerItem.ItemBegin) *
              (ARect.Right - ARect.Left));
          NRect.Right := ARect.Right + ((APlannerItem.ItemEnd - ColIndex - 1) *
              (ARect.Right - ARect.Left));

          NRect.Top := ARect.Top;
          NRect.Bottom := ARect.Bottom;
          APlannerItem.Repainted := False;

          if NRect.Left < HeadIndent then
            NRect.Left := HeadIndent;

          if NRect.Right > XSize then
            NRect.Right := XSize;

          FGrid.PaintItemRow(ACanvas, NRect, APlannerItem, True, False);
          ARect.Left := ARect.Right - FItemGap;
          // Item found, paint only extra rect at Right
        end;
      end;
    end;

  FHTMLFactor := 1.0;
{$IFDEF FREEWARE}
  PrintFreewareNotice(ACanvas, XSize, YSize, Self.ClassName);
{$ENDIF}
end;

function TCustomPlanner.GetDayName(WeekDay: Integer): string;
begin
  if (WeekDay > DaysPerWeek) then
    WeekDay := WeekDay mod DaysPerWeek;

  while (WeekDay < FirstDayOfWeek) do
    WeekDay := WeekDay + DaysPerWeek;

  if (WeekDay <= FDayNames.Count) and (WeekDay > 0) then
    Result := FDayNames.Strings[WeekDay - 1]
  else
    case WeekDay of
      1: Result := ShortDaySun;
      2: Result := ShortDayMon;
      3: Result := ShortDayTue;
      4: Result := ShortDayWed;
      5: Result := ShortDayThu;
      6: Result := ShortDayFri;
      7: Result := ShortDaySat;
    end;
end;

procedure TCustomPlanner.ScrollToIndex(Index: integer);
begin
  if (Sidebar.Position in [spLeft, spRight, spLeftRight]) then
  begin
    GridTopRow := Min(Index, GridControl.RowCount - GridControl.VisibleRowCount);
  end
  else
  begin
    GridLeftCol := Min(Index, GridControl.ColCount - GridControl.VisibleColCount);
  end;
end;

procedure TCustomPlanner.ScrollToPosition(Pos: integer);
begin
  if (Sidebar.Position in [spLeft, spRight, spLeftRight]) then
  begin
    GridLeftCol := Min(Pos, GridControl.ColCount - GridControl.VisibleColCount);
  end
  else
  begin
    GridTopRow := Min(Pos, GridControl.RowCount - GridControl.VisibleRowCount);
  end;
end;


procedure TCustomPlanner.ScrollToTime(ATime: TDateTime);
begin
  if (Sidebar.Position in [spLeft, spRight, spLeftRight]) then
    GridTopRow := AbsTimeToCell(ATime)
  else
    GridLeftCol := AbsTimeToCell(ATime);
end;

procedure TCustomPlanner.SelectGrid;
begin
  if Assigned(Items.Selected) then
    Items.Selected.Focus := False;
  Items.Selected := nil;
  FGrid.SetFocus;
end;

function TCustomPlanner.RichToText: string;
var
  MemoryStream: TMemoryStream;
{$IFNDEF DELPHI_UNICODE}
  RtfText: string;
{$ENDIF}
{$IFDEF DELPHI_UNICODE}
  RtfText: ansistring;
  i: Integer;
  ch: ansichar;
{$ENDIF}
begin
  MemoryStream := TMemoryStream.Create;
{$IFDEF DELPHI_UNICODE}
  FRichEdit.Lines.SaveToStream(MemoryStream, TEncoding.Unicode);
{$ENDIF}
{$IFNDEF DELPHI_UNICODE}
  FRichEdit.Lines.SaveToStream(MemoryStream);
{$ENDIF}
  MemoryStream.Position := 0;
{$IFDEF DELPHI_UNICODE}
  RtfText := '';
  for i := 1 to MemoryStream.Size do
  begin
    MemoryStream.read(ch, 1);
    RtfText := RtfText + ch;
  end;
  Result := widestring(RtfText);
{$ENDIF}
{$IFNDEF DELPHI_UNICODE}
  if MemoryStream.Size > 0 then
    SetString(RtfText, PChar(MemoryStream.Memory), MemoryStream.Size);
  MemoryStream.Free;
  Result := RtfText;
{$ENDIF}
end;

procedure TCustomPlanner.SetGridLineColor(const value: TColor);
begin
  if value <> GridLineColor then
  begin
    FGridLineColor := value;
    FGrid.Invalidate;
  end;
end;

procedure TCustomPlanner.SetColor(const value: TColor);
begin
  if value <> Color then
  begin
    FColor := value;
    FGrid.Color := FColor;
    FGrid.Invalidate;
  end;
end;

procedure TCustomPlanner.TextToRich(const RtfText: string);
var
  MemoryStream: TMemoryStream;
{$IFDEF DELPHI_UNICODE}
  ch: Char;
  ach: ansichar;
  i: Integer;
{$ENDIF}
begin
{$IFDEF DELPHI_UNICODE}
  if RtfText <> '' then
  begin
    MemoryStream := TMemoryStream.Create;
    for i := 1 to Length(RtfText) do
    begin
      ch := RtfText[i];
      ach := ansichar(ch);
      MemoryStream.Write(ach, 1);
    end;
    MemoryStream.Position := 0;
    FRichEdit.Lines.LoadFromStream(MemoryStream);
    MemoryStream.Free;
  end
  else
    RichEdit.Clear;
{$ENDIF}
{$IFNDEF DELPHI_UNICODE}
  if RtfText <> '' then
  begin
    MemoryStream := TMemoryStream.Create;
    MemoryStream.Write(RtfText[1], Length(RtfText));
    MemoryStream.Position := 0;
    FRichEdit.Lines.LoadFromStream(MemoryStream);
    MemoryStream.Free;
  end
  else
    FRichEdit.Clear;
{$ENDIF}
end;

procedure TCustomPlanner.SaveToFile(Filename: string);
var
  FileStream: TFileStream;
begin
  FileStream := TFileStream.Create(Filename, fmCreate);
  try
    SaveToStream(FileStream);
  finally
    FileStream.Free;
  end;
end;

procedure TCustomPlanner.LoadFromFile(Filename: string);
var
  FileStream: TFileStream;
begin
  FileStream := TFileStream.Create(Filename, fmOpenRead);
  try
    LoadFromStream(FileStream);
  finally
    FileStream.Free;
  end;
end;

procedure TCustomPlanner.InsertFromFile(Filename: string);
var
  FileStream: TFileStream;
begin
  FileStream := TFileStream.Create(Filename, fmOpenRead);
  try
    InsertFromStream(FileStream);
  finally
    FileStream.Free;
  end;
end;

procedure TCustomPlanner.SavePositionToStream(Stream: TStream;
  Position: Integer);
var
  NewItems: TPlannerItems;
  ItemIndex: Integer;
  PlannerIO: TPlannerIO;

begin
  Items.SetTimeTags;
  NewItems := CreateItems;
  try
    for ItemIndex := 0 to Items.Count - 1 do
    begin
      if Items.Items[ItemIndex].ItemPos = Position then
      begin
        NewItems.Add.Assign(Items.Items[ItemIndex]);
      end;
    end;

    PlannerIO := TPlannerIO.Create(Self);
    try
      PlannerIO.Items.Assign(NewItems);
      Stream.WriteComponent(PlannerIO);
    finally
      PlannerIO.Free;
    end;
  finally
    NewItems.Free;
  end;
end;

procedure TCustomPlanner.LoadPositionFromStream(Stream: TStream;
  Position: Integer);
var
  NewItems: TPlannerItems;
  PlannerIO: TPlannerIO;
  ItemIndex: Integer;
  APlannerItem: TPlannerItem;

begin
  PlannerIO := TPlannerIO.Create(Self);
  try
    Stream.ReadComponent(PlannerIO);
    NewItems := CreateItems;
    try
      NewItems.Assign(PlannerIO.Items);
      Items.BeginUpdate;
      for ItemIndex := 0 to NewItems.Count - 1 do
      begin
        NewItems.Items[ItemIndex].ItemPos := Position;
        APlannerItem := Items.Add;
        APlannerItem.Assign(NewItems.Items[ItemIndex]);
        APlannerItem.GetTimeTag;
      end;

    finally
      Items.EndUpdate;
      NewItems.Free;
    end;
  finally
    PlannerIO.Free;
  end;
end;

procedure TCustomPlanner.SavePositionToFile(Filename: string;
  Position: Integer);
var
  FileStream: TFileStream;
begin
  FileStream := TFileStream.Create(Filename, fmCreate);
  try
    SavePositionToStream(FileStream, Position);
  finally
    FileStream.Free;
  end;
end;

procedure TCustomPlanner.LoadPositionFromFile(Filename: string;
  Position: Integer);
var
  FileStream: TFileStream;
begin
  FileStream := TFileStream.Create(Filename, fmOpenRead);
  try
    LoadPositionFromStream(FileStream, Position);
  finally
    FileStream.Free;
  end;
end;

procedure TCustomPlanner.SaveLayerToStream(Stream: TStream; Layer: Integer);
var
  NewItems: TPlannerItems;
  ItemIndex: Integer;
  PlannerIO: TPlannerIO;
begin
  Items.SetTimeTags;
  NewItems := CreateItems;
  try
    for ItemIndex := 0 to Items.Count - 1 do
    begin
      if Items.Items[ItemIndex].Layer = Layer then
      begin
        NewItems.Add.Assign(Items.Items[ItemIndex]);
      end;
    end;

    PlannerIO := TPlannerIO.Create(Self);
    try
      PlannerIO.Items.Assign(NewItems);
      Stream.WriteComponent(PlannerIO);
    finally
      PlannerIO.Free;
    end;
  finally
    NewItems.Free;
  end;
end;

procedure TCustomPlanner.LoadLayerFromStream(Stream: TStream; Layer: Integer);
var
  NewItems: TPlannerItems;
  PlannerIO: TPlannerIO;
  ItemIndex: Integer;
  APlannerItem: TPlannerItem;
begin
  PlannerIO := TPlannerIO.Create(Self);
  try
    Stream.ReadComponent(PlannerIO);
    NewItems := CreateItems;
    try
      NewItems.Assign(PlannerIO.Items);
      Items.BeginUpdate;
      for ItemIndex := 0 to NewItems.Count - 1 do
      begin
        NewItems.Items[ItemIndex].Layer := Layer;
        APlannerItem := Items.Add;
        APlannerItem.Assign(NewItems.Items[ItemIndex]);
        APlannerItem.GetTimeTag;
      end;
    finally
      Items.EndUpdate;
      NewItems.Free;
    end;
  finally
    PlannerIO.Free;
  end;
end;

procedure TCustomPlanner.SaveLayerToFile(Filename: string; Layer: Integer);
var
  FileStream: TFileStream;
begin
  FileStream := TFileStream.Create(Filename, fmCreate);
  try
    SaveLayerToStream(FileStream, Layer);
  finally
    FileStream.Free;
  end;
end;

procedure TCustomPlanner.LoadLayerFromFile(Filename: string; Layer: Integer);
var
  FileStream: TFileStream;
begin
  FileStream := TFileStream.Create(Filename, fmOpenRead);
  try
    LoadLayerFromStream(FileStream, Layer);
  finally
    FileStream.Free;
  end;
end;

procedure TCustomPlanner.SaveToStream(Stream: TStream);
var
  PlannerIO: TPlannerIO;
begin
  //save ItemBegin / ItemEnd correct for current display unit
  Items.BeginUpdate;
  Items.SetTimeTags;

  PlannerIO := TPlannerIO.Create(Self);
  try
    PlannerIO.Items.Assign(Self.Items);
    Stream.WriteComponent(PlannerIO);
  finally
    PlannerIO.Free;
  end;
  Items.EndUpdate;
end;

procedure TCustomPlanner.LoadFromStream(Stream: TStream);
var
  PlannerIO: TPlannerIO;
begin
  FLoading := True;
  try
    PlannerIO := TPlannerIO.Create(Self);
    try
      Stream.ReadComponent(PlannerIO);
      Items.Assign(PlannerIO.Items);
    finally
      PlannerIO.Free;
    end;
    Items.SetConflicts;
  finally
    FLoading := False;
  end;

  Items.BeginUpdate;
  Items.GetTimeTags;
  Items.OffsetItems(0);
  Items.EndUpdate;
end;

procedure TCustomPlanner.InsertFromStream(Stream: TStream);
var
  PlannerIO: TPlannerIO;
  NewItems: TPlannerItems;
  ItemIndex: Integer;
  APlannerItem: TPlannerItem;
begin
  PlannerIO := TPlannerIO.Create(Self);
  try
    Stream.ReadComponent(PlannerIO);
    NewItems := CreateItems;
    try
      NewItems.Assign(PlannerIO.Items);
      Items.BeginUpdate;

      for ItemIndex := 1 to NewItems.Count do
      begin
        APlannerItem := Items.Add;
        APlannerItem.Assign(NewItems.Items[ItemIndex - 1]);
        APlannerItem.GetTimeTag;
      end;
    finally
      NewItems.Free;
      Items.EndUpdate;
    end;
  finally
    PlannerIO.Free;
  end;
end;

function FontSizeToHtmlFontSize(FontSize: Integer): string;
begin
  case FontSize of
    1 .. 8:
      Result := '"1"';
    9, 10:
      Result := '"2"';
    11, 12:
      Result := '"3"';
    13, 14:
      Result := '"4"';
    15 .. 18:
      Result := '"5"';
    19 .. 24:
      Result := '"6"';
  else
    Result := '"2"';
  end;
end;

function FontToHtmlFont(const Font: TFont): string;
begin
  Result := Format('<font face="%s" size=%s>', [Font.Name,
    FontSizeToHtmlFontSize(Font.Size)]);
end;

function EmbedInHtmlTag(const value: string; const Tag: string): string;
begin
  Result := Format('<%s>%s</%s>', [Tag, value, Tag]);
end;

function EmbedInHtmlFontStyles(const value: string;
  const FontStyle: TFontStyles): string;
begin
  Result := value;
  if fsBold in FontStyle then
    Result := EmbedInHtmlTag(Result, 'B');
  if fsItalic in FontStyle then
    Result := EmbedInHtmlTag(Result, 'I');
  if fsUnderline in FontStyle then
    Result := EmbedInHtmlTag(Result, 'U');
end;

function EmbedInHtmlOptions(const value: string; const FontStyle: TFontStyles;
  const FontTag: string; const FontColor: TColor): string;
var
  ColorStr: string;
begin
  Result := EmbedInHtmlFontStyles(value, FontStyle);

  ColorStr := '';
  if FontColor <> clBlack then
    ColorStr := ' color=' + ColorToHTML(FontColor);

  if (FontTag <> '') or (ColorStr <> '') then
    Result := Format('<font %s %s>%s</Font>', [FontTag, ColorStr, Result]);
end;

const
  Percent = '%';

function HtmlOptionsToHtmlTablePrefix(HTMLOptions: TPlannerHTMLOptions): string;
begin
  //  style="border-collapse:collapse"
  with HTMLOptions do
    Result := Format('<table border="%d" cellspacing="%d" Width="%d%s" %s>',
      [BorderSize, CellSpacing, Width, Percent, TableStyle]);
end;

function PlannerGetTimeSlotText(Planner: TCustomPlanner; Index, Position: Integer): string;
var
  Line1, Line2, Line3: string; // HoursString, MinutesString, AmPmString
  HS: Boolean;
begin
  Planner.FGrid.GetSideBarLines(Index, Position, Line1, Line2, Line3, HS);

  if Planner.Mode.PlannerType in [plDay, plMonth, plTimeLine] then
  begin
    Result := Format('%s', [Line2]);
    if Line3 <> '' then
      Result := Format('%s %s', [Result, Line3]);
  end
  else
  begin
    Result := Line1 + Line2 + Line3;
  end;

end;

function PlannerGetIdCol(Planner: TCustomPlanner; Index, Position: Integer): string;
var
  Line1, Line2, Line3: string; // HoursString, MinutesString, AmPmString
  HS: Boolean;
begin
  Planner.FGrid.GetSideBarLines(Index, Position, Line1, Line2, Line3, HS);

  if Planner.Mode.PlannerType in [plDay, plTimeLine] then
  begin
    Result := Format('%s%s%s', [Line1, TimeSeparator, Line2]);
    if Line3 <> '' then
      Result := Format('%s %s', [Result, Line3]);
  end
  else
  begin
    Result := Line1 + Line2 + Line3;
  end;
end;

procedure TCustomPlanner.SaveToBMP(Filename: string; Size: TSize);
var
  BMP: TBitmap;
begin
  BMP := TBitmap.Create;
  try
    BMP.Width := Size.cx;
    BMP.Height := Size.cy;
    PrintTo(BMP.Canvas);
    BMP.SaveToFile(Filename);
  finally
    BMP.Free;
  end;
end;

procedure TCustomPlanner.SaveToHTMLCol(Filename: string;
  Unicode: Boolean = False);
var
  RowIndex, ColIndex, PosIndex: Integer;
  WidthPercentage, MaxPos, TotCol: Integer;
  TheBackgroundColor: TColor;
  HtmlText, HtmlBackGroundColor, ColSpan: string;
  APlannerItem: TPlannerItem;
  w, sw, txt: string;
  HtmlAlignment: string;
  rtf: string;
  GotSpan: Boolean;
  ABrush: TBrush;
  sl: TStringList;
  grp, grpm, grpc: Integer;
  plancol: integer;

  function IsSideBar(col: integer): boolean;
  begin
    Result := false;
    case SideBar.Position of
    spLeft: Result := col = 0;
    spRight: Result := col = FGrid.ColCount - 1;
    spLeftRight: Result := (col = 0) or (col = FGrid.ColCount - 1);
    end;
  end;

begin
  HtmlText := '';

  if HTMLOptions.HeaderFile <> '' then
  begin
    sl := TStringList.Create;
    try
      sl.LoadFromFile(HTMLOptions.HeaderFile);
      HtmlText := HtmlText + sl.Text;
    finally
      sl.Free;
    end;
  end;

  with FGrid do
  begin
    HtmlText := HtmlText + HTMLOptions.PrefixTag + FontToHtmlFont(Self.Font)
      + HtmlOptionsToHtmlTablePrefix(HTMLOptions);

    WidthPercentage := Round((Sidebar.Width / Self.Width) * 100);
    w := Format('Width="%d%s"', [Round((100 - WidthPercentage) / ColCount),
      Percent]);
    sw := Format('Width="%d%s"', [WidthPercentage, Percent]);

    if PositionGroup > 0 then
    begin
      HtmlBackGroundColor := ColorToHtmlHexBgColor(Sidebar.Background);
      HtmlText := HtmlText + '<tr>';

      if (Sidebar.Position in [spLeft, spLeftRight]) then
      begin
        HtmlText := HtmlText + '<td ' + HtmlBackGroundColor + '>&nbsp;</td>';
      end;

      ColIndex := 0;
      grpc := 0;

      while ColIndex < ColCount - 1 do
      begin
        if PositionGroup = 1 then
        begin
          grpm := Header.CustomGroups.Items[grpc].Span;
        end
        else
          grpm := PositionGroup;

        MaxPos := 0;

        for grp := 1 to grpm do
        begin
          MaxPos := MaxPos + Items.MaxItemsInPos(ColIndex);
          ColIndex := ColIndex + 1;
        end;

        if (MaxPos > 1) and (ColIndex > 0) then
          ColSpan := ' colspan="' + IntToStr(MaxPos) + '"'
        else
          ColSpan := '';

        HtmlText := HtmlText + '<td ' + w + ColSpan;

        HtmlAlignment := '';
        case Header.Alignment of
          taRightJustify:
            HtmlAlignment := ' align="Right"';
          taCenter:
            HtmlAlignment := ' align="center"';
        end;

        HtmlText := HtmlText + HtmlAlignment;

        if Header.GroupCaptions.Count > grpc then
          txt := CLToBR(Header.GroupCaptions[grpc])
        else
          txt := HtmlNonBreakingSpace;

        txt := EmbedInHtmlOptions(txt, HTMLOptions.HeaderFontStyle,
          HTMLOptions.HeaderFontTag, Header.Font.Color);

        HtmlText := HtmlText + HtmlBackGroundColor + '>' + txt + '</td>'#13#10;

        Inc(grpc);
      end;

      HtmlText := HtmlText + '</tr>';
    end;

    for ColIndex := 0 to ColCount - 1 do
    begin

      if IsSideBar(ColIndex) then
        HtmlText := HtmlText + '<td ' + sw
      else
      begin
        plancol := ColIndex - 1;
        if SideBar.Position = spRight then
          plancol := ColIndex;

        MaxPos := Items.MaxItemsInPos(plancol);
{$IFDEF TMSDEBUG}
        outputdebugstring(PChar(IntToStr(plancol) + ':' + IntToStr(MaxPos)));
{$ENDIF}
        if (MaxPos > 1) and (plancol >= 0) then
          ColSpan := ' colspan="' + IntToStr(MaxPos) + '"'
        else
          ColSpan := '';

        HtmlText := HtmlText + '<td ' + w + ColSpan;
      end;

      HtmlAlignment := '';
      case Header.Alignment of
        taRightJustify:
          HtmlAlignment := ' align="Right"';
        taCenter:
          HtmlAlignment := ' align="center"';
      end;

      HtmlText := HtmlText + HtmlAlignment;

      HtmlBackGroundColor := ColorToHtmlHexBgColor(Sidebar.Background);

      if Header.Captions.Count > ColIndex then
        txt := CLToBR(Header.Captions[ColIndex])
      else
        txt := HtmlNonBreakingSpace;

      txt := EmbedInHtmlOptions(txt, HTMLOptions.HeaderFontStyle,
        HTMLOptions.HeaderFontTag, Header.Font.Color);

      HtmlText := HtmlText + HtmlBackGroundColor + '>' + txt + '</td>'#13#10
    end;

    HtmlText := HtmlText + '</tr>';

    w := '';

    for RowIndex := 0 to RowCount - 1 do
    begin
      HtmlText := HtmlText + '<tr>';

      for ColIndex := 0 to ColCount - 1 do
      begin
        GotSpan := False;

        if IsSideBar(ColIndex) then
        begin
          HtmlBackGroundColor := ColorToHtmlHexBgColor(Sidebar.Background);
          txt := PlannerGetIdCol(Self, RowIndex, ColIndex);

          txt := EmbedInHtmlOptions(txt, HTMLOptions.SidebarFontStyle,
            HTMLOptions.SidebarFontTag, Sidebar.Font.Color);

          HtmlText := HtmlText + '<td ' + sw + HtmlBackGroundColor + '>' +
            txt + '</td>';
        end
        else
        begin
          plancol := ColIndex - 1;
          if SideBar.Position = spRight then
            plancol := ColIndex;

          MaxPos := Items.MaxItemsInPos(plancol);

          for PosIndex := 0 to MaxPos - 1 do
          begin
            HtmlBackGroundColor := '';

            ABrush := TBrush.Create;
            GetCellBrush(plancol, RowIndex, ABrush);

            HtmlBackGroundColor := ColorToHtmlHexBgColor(ABrush.Color);

            ABrush.Free;

            TheBackgroundColor := BackgroundColor[plancol, RowIndex];
            if TheBackgroundColor <> clNone then
              HtmlBackGroundColor := ColorToHtmlHexBgColor(TheBackgroundColor);

            APlannerItem := Items.FindItem(RowIndex, plancol);

            if Assigned(APlannerItem) then
              TotCol := APlannerItem.Conflicts
            else
              TotCol := 0;

            APlannerItem := Items.FindItemPosIdx(RowIndex, plancol, PosIndex);

            if Assigned(APlannerItem) then
            begin
              HtmlAlignment := ' valign="Top"';
              case APlannerItem.Alignment of
                taRightJustify:
                  HtmlAlignment := HtmlAlignment + ' align="Right"';
                taCenter:
                  HtmlAlignment := HtmlAlignment + ' align="center"';
              end;

              if (APlannerItem.ItemBegin = RowIndex) then
              begin
                rtf := APlannerItem.Text.Text;
                if IsRtf(rtf) then
                begin
                  TextToRich(rtf);
                  rtf := FRichEdit.Text;
                end
                else
                begin
                  rtf := HTMLConvert(rtf);
                  rtf := StringReplace(rtf,#13#10,'<BR>',[rfReplaceAll]);
                end;

                if HTMLOptions.ShowCaption then
                  rtf := APlannerItem.GetCaptionString + '<HR>' + rtf;

                rtf := EmbedInHtmlOptions(rtf, HTMLOptions.CellFontStyle,
                  HTMLOptions.CellFontTag, APlannerItem.Font.Color);

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

                HtmlBackGroundColor := ColorToHtmlHexBgColor
                  (APlannerItem.Color);

                if (MaxPos > 1) and (APlannerItem.ConflictPos = 0) and
                  (TotCol = 1) then
                begin
                  ColSpan := ' colspan="' + IntToStr(MaxPos) + '"';
                end
                else
                  ColSpan := '';

                if (APlannerItem.ItemEnd > APlannerItem.ItemBegin)
                  and not GotSpan and (APlannerItem.ConflictPos = PosIndex)
                  then
                  HtmlText := HtmlText + '<td ' + w + HtmlAlignment +
                    ' rowspan="' + IntToStr
                    (APlannerItem.ItemEnd - APlannerItem.ItemBegin)
                    + '"' + ColSpan + HtmlBackGroundColor +
                    ' bordercolor="#000000">' + rtf + '</td>'
                else
                begin
                  HtmlText := HtmlText + '<td ' + w + HtmlAlignment +
                    HtmlBackGroundColor + '>' + rtf + '</td>'
                end;
              end;

              if (MaxPos > 0) and (APlannerItem.ConflictPos = 0) and
                (TotCol = 1) then
                GotSpan := True;
            end
            else
            begin
              if TotCol = 0 then
              begin
                if (PosIndex = 0) then
                begin
                  if MaxPos > 1 then
                    ColSpan := ' colspan="' + IntToStr(MaxPos) + '"'
                  else
                    ColSpan := '';

                  HtmlText := HtmlText + '<td ' + ColSpan +
                    HtmlBackGroundColor + '>&nbsp;' +
                    '</td>'#13#10
                end;
              end
              else
              begin
                if not GotSpan then
                  HtmlText := HtmlText + '<td ' + w + HtmlBackGroundColor +
                    '>&nbsp;' + '</td>'
              end;
            end;
          end;
        end;
      end;
      HtmlText := HtmlText + '</tr>';
    end;
    HtmlText := HtmlText + '</table></Font>';
  end;

  HtmlText := HtmlText + HTMLOptions.SuffixTag;

  if HTMLOptions.FooterFile <> '' then
  begin
    sl := TStringList.Create;
    try
      sl.LoadFromFile(HTMLOptions.FooterFile);
      HtmlText := HtmlText + sl.Text;
    finally
      sl.Free;
    end;
  end;

  sl := TStringList.Create;
  sl.Text := HtmlText;
  try
{$IFDEF DELPHI_UNICODE}
    if Unicode then
      sl.SaveToFile(Filename, TEncoding.Unicode)
    else
      sl.SaveToFile(Filename, TEncoding.ASCII);
{$ENDIF}
{$IFNDEF DELPHI_UNICODE}
    sl.SaveToFile(Filename);
{$ENDIF}
  finally
    sl.Free;
  end;
end;

procedure TCustomPlanner.SaveToHTMLRow(Filename: string;
  Unicode: Boolean = False);
var
  RowIndex, ColIndex, StartCol: Integer;
  HtmlText, HtmlBackGroundColor, txt: string;
  tf: TextFile;
  APlannerItem: TPlannerItem;
  w, sw, hw: string;
  HtmlAlignment: string;
  rtf: string;
  ABrush: TBrush;
  sl: TStringList;
  TotPos, MaxPos, SubPos: Integer;
  NumDown, RowSpan: Integer;
  GotSpan: Boolean;
  ColSpan: string;
  RowSp, HeightSB: string;
  HeightCell: Integer;
  grp, grpc, grpm, grprow, grpsp: Integer;

  function HTMLSpaces(s: string): string;
  var
    i: Integer;
  begin
    Result := '';
    for i := 1 to Length(s) do
      if s[i] = ' ' then
        Result := Result + '&nbsp;'
      else
        Result := Result + s[i];
  end;

begin
  HtmlText := '';

  if HTMLOptions.HeaderFile <> '' then
  begin
    sl := TStringList.Create;
    try
      sl.LoadFromFile(HTMLOptions.HeaderFile);
      HtmlText := HtmlText + sl.Text;
    finally
      sl.Free;
    end;
  end;

  with FGrid do
  begin
    //    HtmlText := HtmlText + FontToHtmlFont(Self.Font) + HtmlOptionsToHtmlTablePrefix(HTMLOptions);
    HtmlText := HtmlText + FontToHtmlFont(Self.Font)
      + '<table border="' + IntToStr(HTMLOptions.BorderSize)
      + '" ' + ' cellspacing="' + IntToStr(HTMLOptions.CellSpacing)
      + '" width="' + IntToStr(Self.Width) + 'px" '
      + HTMLOptions.TableStyle
      + '>';

    if (Header.Visible) then
      w := 'width="' + IntToStr(Round((Self.Width - Header.Height) / ColCount)
          - 2) + '"'
    else
      w := 'width="' + IntToStr(Round((Self.Width) / ColCount)) + '"';

    sw := 'width="' + IntToStr(Display.DisplayScale) + 'px"';
    hw := 'width="' + IntToStr(Header.Height) + 'px" ';

    HeightSB := ' height="' + IntToStr(Sidebar.Width) + 'px" ';

    HtmlText := HtmlText + '<tr>';
    StartCol := 1;
    HtmlBackGroundColor := ColorToHtmlHexBgColor(Header.Color);

    if PositionGroup > 0 then
    begin
      HtmlText := HtmlText + '<td ' + hw + HtmlBackGroundColor + '>&nbsp;</td>';
    end;

    if Header.Visible then
    begin
      HtmlText := HtmlText + '<td ' + hw + HtmlBackGroundColor + '>&nbsp;</td>';
      StartCol := 0;
    end;

    for ColIndex := 0 to ColCount - 1 do
    begin
      HtmlBackGroundColor := ColorToHtmlHexBgColor(Sidebar.Background);

      txt := PlannerGetIdCol(Self, ColIndex, 0);
      txt := EmbedInHtmlOptions(txt, HTMLOptions.HeaderFontStyle,
        HTMLOptions.HeaderFontTag, Header.Font.Color);

      HtmlText := HtmlText + '<td ' + sw + HeightSB + HtmlBackGroundColor +
        '>' + '<div style="overflow:hidden;width:' + IntToStr
        (Display.DisplayScale - 2) + 'px">' + txt + '</div></td>';
    end;

    HtmlText := HtmlText + '</tr>';

    grpc := 0;
    grprow := 1;

    for RowIndex := 1 to RowCount - 1 do
    begin
      MaxPos := Items.MaxItemsInPos(RowIndex - 1);
      SubPos := 1;

      while SubPos <= MaxPos do
      begin
        HtmlText := HtmlText + '<tr>';

        if (PositionGroup > 0) and (RowIndex = grprow) then
        begin
          HtmlBackGroundColor := ColorToHtmlHexBgColor(Header.Color);

          if PositionGroup = 1 then
          begin
            grpm := Header.CustomGroups.Items[grpc].Span;
          end
          else
            grpm := PositionGroup;

          grprow := grprow + grpm;

          grpsp := 0;

          for grp := 1 to grpm do
          begin
            grpsp := grpsp + Items.MaxItemsInPos(grpc + grp - 1);
          end;

          if (grpsp > 1) then
            RowSp := ' rowspan="' + IntToStr(grpsp) + '" '
          else
            RowSp := '';

          HtmlText := HtmlText + '<td ' + RowSp + hw + HtmlBackGroundColor +
            '>' + Header.GroupCaptions[grpc] + '</td>';

          Inc(grpc);
        end;

        for ColIndex := StartCol to ColCount do
        begin
          if ColIndex = 0 then
          begin
            if (ColIndex = 0) and (SubPos = 1) then
            begin
              HtmlBackGroundColor := ColorToHtmlHexBgColor(Header.Color);

              if Header.Captions.Count > ColIndex then
                txt := CLToBR(Header.Captions[RowIndex])
              else
                txt := HtmlNonBreakingSpace;

              txt := EmbedInHtmlOptions(txt, HTMLOptions.SidebarFontStyle,
                HTMLOptions.SidebarFontTag, Sidebar.Font.Color);

              if (MaxPos > 1) then
                RowSp := ' rowspan="' + IntToStr(MaxPos) + '" '
              else
                RowSp := '';

              HtmlText := HtmlText + '<td ' + hw + RowSp +
                HtmlBackGroundColor + '>' +
                '<div style="overflow:hidden;width:' + IntToStr(Header.Height)
                + 'px">' + txt + '</div></td>';
            end;
          end
          else
          begin
            HtmlBackGroundColor := '';

            ABrush := TBrush.Create;
            GetCellBrush(RowIndex - 1, ColIndex - 1, ABrush);
            HtmlBackGroundColor := ColorToHtmlHexBgColor(ABrush.Color);
            ABrush.Free;

            if BackgroundColor[ColIndex - 1, RowIndex - 1] <> clNone then
              HtmlBackGroundColor := ColorToHtmlHexBgColor
                (BackgroundColor[ColIndex - 1, RowIndex - 1]);

            APlannerItem := Items.FindItem(ColIndex - 1, RowIndex - 1);

            if Assigned(APlannerItem) then
              TotPos := APlannerItem.Conflicts
            else
              TotPos := 0;

            if (PositionWidth = 0) then
            begin
              if (TotPos > 0) then
                HeightCell := Round
                  (((Self.Height - Sidebar.Width - Self.Caption.Height)
                      / Self.Positions) / MaxPos) - MaxPos
              else
                HeightCell := Round
                  ((Self.Height - Sidebar.Width - Self.Caption.Height)
                    / Self.Positions);
            end
            else
            begin
              HeightCell := PositionWidth;
              //if (TotPos > 0) then
              //  HeightCell := Round(((Self.Height - SideBar.Width - Self.Caption.Height) / PositionWidth)/MaxPos) - MaxPos
              //else
              //  HeightCell := Round((Self.Height - SideBar.Width - Self.Caption.Height) / PositionWidth);
            end;

            APlannerItem := Items.FindItemPosIdx(ColIndex - 1, RowIndex - 1,
              SubPos - 1);

            if (Assigned(APlannerItem)) then
            begin
              HtmlAlignment := ' valign="Top"';
              case APlannerItem.Alignment of
                taRightJustify:
                  HtmlAlignment := HtmlAlignment + ' align="Right"';
                taCenter:
                  HtmlAlignment := HtmlAlignment + ' align="center"';
              end;

              if (APlannerItem.ItemBegin = ColIndex - 1) then
              begin
                GotSpan := False;

                rtf := APlannerItem.Text.Text;
                if IsRtf(rtf) then
                begin
                  TextToRich(rtf);
                  rtf := FRichEdit.Text;
                end
                else
                begin
                  rtf := HTMLConvert(rtf);
                  rtf := StringReplace(rtf,#13#10,'<BR>',[rfReplaceAll]);
                end;

                if HTMLOptions.ShowCaption then
                  rtf := HTMLSpaces(APlannerItem.GetCaptionString)
                    + '<HR>' + rtf;

                rtf := EmbedInHtmlOptions(rtf, HTMLOptions.CellFontStyle,
                  HTMLOptions.CellFontTag, APlannerItem.Font.Color);

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

                RowSpan := APlannerItem.ItemEnd - APlannerItem.ItemBegin;

                if (MaxPos > 1) and (APlannerItem.ConflictPos = 0) and
                  (TotPos = 1) then
                  ColSpan := ' rowspan="' + IntToStr(MaxPos) + '"'
                else
                  ColSpan := '';

                if (MaxPos > 0) and (APlannerItem.ConflictPos = 0) and
                  (TotPos = 1) then
                  GotSpan := True;

                HtmlBackGroundColor := ColorToHtmlHexBgColor
                  (APlannerItem.Color);

                if (APlannerItem.ItemEnd > APlannerItem.ItemBegin)
                  and not GotSpan then
                  HtmlText := HtmlText + '<td height="' + IntToStr(HeightCell)
                    + 'px" ' + w + HtmlAlignment + ColSpan + ' colspan="' +
                    IntToStr(RowSpan) + '"' + HtmlBackGroundColor +
                    ' bordercolor="#000000"><div style="overflow:hidden;height:'
                    + IntToStr(HeightCell) + 'px">' + rtf + '</div></td>'
                else
                begin
                  HtmlText := HtmlText + '<td height="' + IntToStr(HeightCell)
                    + 'px" ' + ' bordercolor="#000000" ' + w + HtmlAlignment +
                    HtmlBackGroundColor + ' colspan="' + IntToStr(RowSpan) +
                    '"><div style="overflow:hidden;height:' + IntToStr
                    (HeightCell) + 'px">' + rtf + '</div></td>';
                end;
              end;
            end
            else
            begin
              if (TotPos = 0) and (SubPos = 1) then
              begin
                if (MaxPos > 1) then
                  ColSpan := ' rowspan="' + IntToStr(MaxPos) + '"'
                else
                  ColSpan := '';

                HtmlText := HtmlText + '<td width="' + IntToStr
                  (Display.DisplayScale - 2) + 'px" height="' + IntToStr
                  (HeightCell) + 'px" ' + ColSpan + HtmlBackGroundColor +
                  '>' + '<div style="overflow:hidden;width:' + IntToStr
                  (Display.DisplayScale - 2) + 'px' + '">&nbsp;' +
                  '</div></td>'#13#10
              end
              else
              begin
                if (Assigned(Items.FindItemPosIdx(ColIndex - 1, RowIndex - 1,
                      SubPos - 2)) or (SubPos = 1)) then
                begin
                  NumDown := 1;

                  while not Assigned(Items.FindItemPosIdx(ColIndex - 1,
                      RowIndex - 1, SubPos - 1 + NumDown)) and
                    (NumDown <= MaxPos - SubPos) do
                    Inc(NumDown);

                  if (NumDown > 0) then
                  begin
                    if (NumDown > 1) then
                      ColSpan := ' rowspan="' + IntToStr(NumDown) + '"'
                    else
                      ColSpan := '';

                    HtmlText := HtmlText + '<td height="' + IntToStr
                      (HeightCell) + 'px"' + ColSpan + HtmlBackGroundColor +
                      '>&nbsp;</td>';
                  end;
                end;
              end;
            end;
          end;
        end;
        Inc(SubPos);
        HtmlText := HtmlText + '</tr>';
      end;
    end;
    HtmlText := HtmlText + '</table></Font>';
  end;
  //End Modified

  if HTMLOptions.FooterFile <> '' then
  begin
    sl := TStringList.Create;
    try
      sl.LoadFromFile(HTMLOptions.FooterFile);
      HtmlText := HtmlText + sl.Text;
    finally
      sl.Free;
    end;
  end;

  sl := TStringList.Create;
  sl.Text := HtmlText;
  try
{$IFDEF DELPHI_UNICODE}
    if Unicode then
      sl.SaveToFile(Filename, TEncoding.Unicode)
    else
      sl.SaveToFile(Filename, TEncoding.ASCII);
{$ENDIF}
{$IFNDEF DELPHI_UNICODE}
    sl.SaveToFile(Filename);
{$ENDIF}
  finally
    sl.Free;
  end;
end;

procedure TCustomPlanner.SaveToHTML(Filename: string; Unicode: Boolean = False);
begin
  if Sidebar.Orientation = soVertical then
    SaveToHTMLCol(Filename, Unicode)
  else
    SaveToHTMLRow(Filename, Unicode);
end;

procedure TCustomPlanner.Resize;
begin
  inherited;
  if FGrid.FMemo.Visible then
    FGrid.FMemo.Visible := False;
  if FRichEdit.Visible then
    FRichEdit.Visible := False;
  if Assigned(FHeader) then
    if Assigned(FHeader.FInplaceEdit) then
    begin
      if FHeader.FInplaceEdit.Visible then
        FHeader.FInplaceEdit.Visible := False;
    end;
  UpdateSizes;
end;

procedure TCustomPlanner.WMMoving(var Message: TMessage);
begin
  inherited;
end;

procedure TCustomPlanner.BalloonInit;

  procedure WindowBlend(hwnd: THandle; colorkey: TColor; alpha: Byte; R: TRect);
  var
    dw: dword;
    blnd: _BLENDFUNCTION;
    dskdc: THandle;
    Size, src: TPoint;
    hdc: THandle;
  begin
    hdc := GetDC(hwnd);
    dw := GetWindowLong(hwnd, GWL_EXSTYLE);
    SetWindowLong(hwnd, GWL_EXSTYLE, dw or WS_EX_LAYERED);
    DynaLink_SetLayeredWindowAttributes(hwnd, dword(colorkey), alpha, 2);
    blnd.BlendOp := AC_SRC_OVER;
    blnd.BlendFlags := 0;
    blnd.SourceConstantAlpha := 0;
    blnd.AlphaFormat := 0;
    dskdc := GetDC(0);
    Size := Point(R.Right - R.Left, R.Bottom - R.Top);
    src := Point(R.Left, R.Top);
    DynaLink_UpdateLayeredWindow(hwnd, dskdc, nil, @Size, hdc, @src,
      dword(colorkey), blnd, ULW_ALPHA);
    ReleaseDC(0, dskdc);
    ReleaseDC(hwnd, hdc);
  end;

begin
  FGrid.CreateToolTip;
  FGrid.AddToolTip(3, 'Planner', 'ToolTipText');
  if FBalloon.InitialDelay <> -1 then
    SendMessage(FGrid.FHToolTip, TTM_SETDELAYTIME, TTDT_INITIAL,
      FBalloon.InitialDelay);

  if FBalloon.ReshowDelay <> -1 then
    SendMessage(FGrid.FHToolTip, TTM_SETDELAYTIME, TTDT_RESHOW,
      FBalloon.ReshowDelay);

  if FBalloon.AutoHideDelay <> -1 then
    SendMessage(FGrid.FHToolTip, TTM_SETDELAYTIME, TTDT_AUTOPOP,
      FBalloon.AutoHideDelay);

  if (FBalloon.Transparency > 0) then
    WindowBlend(FGrid.FHToolTip, 0, 255 - FBalloon.Transparency,
      Rect(0, 0, 100, 100));

  FHeader.CreateToolTip;
  FHeader.AddToolTip(3, 'Header', 'ToolTipText');
  if FBalloon.InitialDelay <> -1 then
    SendMessage(FHeader.FHToolTip, TTM_SETDELAYTIME, TTDT_INITIAL,
      FBalloon.InitialDelay);

  if FBalloon.ReshowDelay <> -1 then
    SendMessage(FHeader.FHToolTip, TTM_SETDELAYTIME, TTDT_RESHOW,
      FBalloon.ReshowDelay);

  if FBalloon.AutoHideDelay <> -1 then
    SendMessage(FHeader.FHToolTip, TTM_SETDELAYTIME, TTDT_AUTOPOP,
      FBalloon.AutoHideDelay);

  if (FBalloon.Transparency > 0) then
    WindowBlend(FHeader.FHToolTip, 0, 255 - FBalloon.Transparency,
      Rect(0, 0, 100, 100));
end;

procedure TCustomPlanner.BalloonDone;
begin
  FGrid.DestroyToolTip;
  FHeader.DestroyToolTip;
end;

procedure TCustomPlanner.BalloonChange(Sender: TObject);
begin
  if not (csLoading in ComponentState) then
  begin
    if FBalloon.Enable then
      BalloonInit
    else
      BalloonDone;
  end;
end;

procedure TCustomPlanner.SetSelectRange(const value: Boolean);
begin
  if value then
    FGrid.Options := [goRangeSelect]
  else
    FGrid.Options := [];

  FSelectRange := value;
end;

procedure TCustomPlanner.SetItemSelection(AValue: TPlannerItemSelection);
begin
  FItemSelection.Assign(AValue);
end;

procedure TCustomPlanner.Loaded;
begin
  inherited;
{$IFDEF TMSCODESITE}
  CodeSite.SendMsg('TPlanner Loaded begin');
{$ENDIF}
  FCaption.UpdatePanel;
  FDisplay.InitPrecis;
  FDisplay.UpdatePlanner;

  // initialize FInactive set
  InactiveChanged(Self);

  Items.SetConflicts;
  FGrid.Color := Self.Color;
  FHeader.Flat := FPlannerHeader.Flat;

  if FPlannerHeader.AutoSize then
    AutoSizeHeader;

  FGrid.ScrollBars := FScrollBars;

  FScrollBarStyle.UpdateProps;
  FGrid.UpdateVScrollBar;
{$IFDEF TMSCODESITE}
  CodeSite.SendMsg('TPlanner Loaded end');
{$ENDIF}
  UpdateTimer;
  FGrid.UpdateNVI;

  Sidebar.ActiveColor := Sidebar.ActiveColor;
  FGrid.FOldSelection := FGrid.Selection;

  if Footer.ShowCompletion and Footer.Visible then
    UpdateCompletion;

  UpdateSizes;
  FGrid.UpdatePositions;

  Items.SetConflicts;

  if FBalloon.Enable then
    BalloonInit;
  case Sidebar.Orientation of
    soHorizontal:
      FHeader.Rotate := Header.RotateOnLeft;
    soVertical:
      FHeader.Rotate := Header.RotateOnTop;
  end;

  if AutoThemeAdapt and not(csDesigning in ComponentState) then
  begin
    ThemeAdapt;
    if not (csDesigning in ComponentState) then
      ThemeNotifier(Self).RegisterWindow(Handle);
  end;

  InitVCLStyle(false);
end;

procedure TCustomPlanner.HeaderHeightChange(ASize: Integer);
begin
  if Assigned(FOnHeaderHeightChange) then
    FOnHeaderHeightChange(Self, ASize);
end;

procedure TCustomPlanner.NextClick(Sender: TObject);
begin
  if Assigned(FOnPlannerNext) then
    FOnPlannerNext(Self);
end;

procedure TCustomPlanner.PrevClick(Sender: TObject);
begin
  if Assigned(FOnPlannerPrev) then
    FOnPlannerPrev(Self);
end;

procedure TCustomPlanner.PrevPosition(Sender: TObject);
begin
  if Assigned(FOnPlannerPrevPosition) then
  begin
    FOnPlannerPrevPosition(Self);
  end
  else
    if Assigned(FOnPlannerPrev) then
      FOnPlannerPrev(Self);
end;

procedure TCustomPlanner.NextPosition(Sender: TObject);
begin
  if Assigned(FOnPlannerNextPosition) then
  begin
    FOnPlannerNextPosition(Self);
  end
  else
    if Assigned(FOnPlannerNext) then
      FOnPlannerNext(Self);
end;

procedure TCustomPlanner.HeaderClick(Sender: TObject; SectionIndex: Integer);
begin
  if Assigned(FOnHeaderClick) then
    FOnHeaderClick(Self, SectionIndex);
end;

procedure TCustomPlanner.HeaderRightClick(Sender: TObject;
  SectionIndex: Integer);
begin
  if Assigned(FOnHeaderRightClick) then
    FOnHeaderRightClick(Self, SectionIndex);
end;

procedure TCustomPlanner.HeaderDblClick(Sender: TObject; SectionIndex: Integer);
begin
  if Assigned(FOnHeaderDblClick) then
    FOnHeaderDblClick(Self, SectionIndex)
end;

procedure TCustomPlanner.HeaderAnchorEnter(Sender: TObject;
  SectionIndex: Integer; Anchor: string);
begin
  if Assigned(FOnHeaderAnchorEnter) then
    FOnHeaderAnchorEnter(Self, SectionIndex, Anchor)
end;

procedure TCustomPlanner.HeaderAnchorLeave(Sender: TObject;
  SectionIndex: Integer; Anchor: string);
begin
  if Assigned(FOnHeaderAnchorLeave) then
    FOnHeaderAnchorLeave(Self, SectionIndex, Anchor)
end;

procedure TCustomPlanner.HeaderAnchorClick(Sender: TObject;
  SectionIndex: Integer; Anchor: string);
begin
  if Assigned(FOnHeaderAnchorClick) then
    FOnHeaderAnchorClick(Self, SectionIndex, Anchor)
  else
    ShellExecute(0, 'open', PChar(Anchor), nil, nil, SW_NORMAL);
end;

procedure TCustomPlanner.HeaderDraw(Sender: TObject; SectionIndex: Integer;
  ACanvas: TCanvas; ARect: TRect);
begin
  if Assigned(FOnHeaderDraw) then
    FOnHeaderDraw(Self, SectionIndex, ACanvas, ARect);
end;

procedure TCustomPlanner.HeaderDrawProp(Sender: TObject; SectionIndex: Integer;
  var AColor, AColorTo: TColor; AFont: TFont);
begin
  if Assigned(FOnHeaderDrawProp) then
    FOnHeaderDrawProp(Self, SectionIndex, AColor, AColorTo, AFont);
end;

procedure TCustomPlanner.HeaderGroupDrawProp(Sender: TObject; SectionIndex: Integer;
  var AColor, AColorTo: TColor; AFont: TFont);
begin
  if Assigned(FOnHeaderGroupDrawProp) then
    FOnHeaderGroupDrawProp(Self, SectionIndex, AColor, AColorTo, AFont);
end;


procedure TCustomPlanner.HeaderDragDrop(Sender: TObject;
  FromSection, ToSection: Integer);
var
  fs, ts: Integer;
begin
  if ToSection > Positions then
    Exit;
  if FromSection > Positions then
    Exit;

  MovePosition(FromSection - 1, ToSection - 1);

  fs := FromSection;
  ts := ToSection;

  if (Sidebar.Position in [spLeft, spLeftRight, spTop]) then
  begin
    Dec(fs);
    Dec(ts);
  end;

  MoveResource(fs, ts);

  if Assigned(FOnHeaderDragDrop) then
    FOnHeaderDragDrop(Self, FromSection, ToSection);
end;

procedure TCustomPlanner.MoveResource(FromPos, ToPos: Integer);
begin

end;

procedure TCustomPlanner.PlanFontChanged(Sender: TObject);
begin
  Invalidate;
end;

procedure TCustomPlanner.CreateWnd;
var
  dsn: boolean;
begin
  inherited;
  FCaption.UpdatePanel;
  UpdateSizes;

  dsn := FDesignTime and not ((csReading in ComponentState) or (csLoading in ComponentState));

  // initialize to Windows 7 color style
  if dsn then
  begin
    SetStyle(12);
  end;

  if not Assigned(Parent) or not (Parent is TWinControl) then
    Exit;

  if not (csDesigning in ComponentState) and not (csLoading in ComponentState) then
  begin
    InitVCLStyle(false);
  end;

end;

procedure TCustomPlanner.CreateParams(var Params: TCreateParams);
begin
  inherited CreateParams(Params);
  with Params do
  begin
    Style := Style and not WS_BORDER;
  end;
end;

procedure TCustomPlanner.DestroyWnd;
begin
  inherited;
end;

procedure TCustomPlanner.Paint;
var
  R: TRect;
begin
  inherited;

  R := ClientRect;

  if FHeader.Visible and (FSidebar.Position <> spTop) then
  begin
    R.Bottom := FHeader.Height + FCaption.Height;
    Canvas.Brush.Color := FHeader.Color;
    Canvas.Pen.Color := FHeader.Color;
    Canvas.FillRect(R); // fill the Header background
    R := ClientRect;
    R.Top := FHeader.Height + FCaption.Height;
  end;
end;

procedure TCustomPlanner.ThemeAdapt;
var
  ot: TOfficeTheme;
begin
  if (csDesigning in ComponentState) then
    Exit;

  ot := GetOfficeTheme;

  if (ot = FOldOfficeTheme) then
    Exit;

  case ot of
  ot2003Classic: SetComponentStyle(tsOffice2003Classic);
  ot2003Blue: SetComponentStyle(tsOffice2003Blue);
  ot2003Olive: SetComponentStyle(tsOffice2003Olive);
  ot2003Silver: SetComponentStyle(tsOffice2003Silver);
  ot2007Blue: SetComponentStyle(tsOffice2007Luna);
  ot2007Silver: SetComponentStyle(tsOffice2007Silver);
  ot2007Black: SetComponentStyle(tsOffice2007Obsidian);
  ot2010Blue: SetComponentStyle(tsOffice2010Blue);
  ot2010Silver: SetComponentStyle(tsOffice2010Silver);
  ot2010Black: SetComponentStyle(tsOffice2010Black);
  ot2013White: SetComponentStyle(tsOffice2013White);
  ot2013Silver: SetComponentStyle(tsOffice2013LightGray);
  ot2013Gray: SetComponentStyle(tsOffice2013Gray);
  ot2016White: SetComponentStyle(tsOffice2016White);
  ot2016Gray: SetComponentStyle(tsOffice2016Gray);
  ot2016Black: SetComponentStyle(tsOffice2016Black);
  end;

  FOldOfficeTheme := ot;
end;


procedure TCustomPlanner.Invalidate;
var
  i: Integer;
begin
  inherited;

  for i := 1 to ControlCount do
    Controls[i - 1].Invalidate;
end;

procedure TCustomPlanner.SetActiveDisplay(const value: Boolean);
begin
  if FActiveDisplay <> value then
  begin
    if Sidebar.Orientation = soVertical then
    begin
      if value then
        FGrid.TopRow := Display.ActiveStart
      else
        FGrid.TopRow := 0;
    end
    else
    begin
      if value then
        FGrid.LeftCol := Display.ActiveStart
      else
        FGrid.LeftCol := 0;
    end;

    FActiveDisplay := value;
  end;
end;

procedure TCustomPlanner.SetFont(value: TFont);
begin
  Font.Assign(value);
end;

procedure TCustomPlanner.SetTrackColor(const value: TColor);
begin
  if FTrackColor <> value then
  begin
    FTrackColor := value;
    Invalidate;
  end;
end;

procedure TCustomPlanner.SetTrackOnly(const value: Boolean);
begin
  if FTrackOnly <> value then
  begin
    FTrackOnly := value;
    Invalidate;
  end;
end;

procedure TCustomPlanner.SetTrackProportional(const value: Boolean);
begin
  if FTrackProportional <> value then
  begin
    FTrackProportional := value;
    Invalidate;
  end;
end;

procedure TCustomPlanner.SetImages(const value: TImageList);
begin
  if FPlannerImages <> value then
  begin
    FPlannerImages := value;
    Invalidate;
  end;
end;

procedure TCustomPlanner.SetDragItemImage(const Value: Boolean);
begin
  if (FDragItemImage <> Value) then
  begin
    FDragItemImage := Value;
    if Value then
      FixControlStyles(GetParentForm(Self));
  end;
end;

procedure TCustomPlanner.SetDrawPrecise(const value: Boolean);
begin
  if FDrawPrecise <> value then
  begin
    FDrawPrecise := value;
    FGrid.DoubleBuffered := true;
    Invalidate;
  end;
end;

procedure TCustomPlanner.SetLayer(const value: LongInt);
begin
  if FLayer <> value then
  begin
    FLayer := value;
    Items.SetConflicts;
    Invalidate;
  end;
end;

procedure TCustomPlanner.SetLinkArrowShape(const Value: TArrowShape);
begin
  if (FLinkArrowShape <> Value) then
  begin
    FLinkArrowShape := Value;
    Invalidate;
  end;
end;

procedure TCustomPlanner.SetLinkArrowSize(const Value: integer);
begin
  if (FLinkArrowSize <> Value) then
  begin
    FLinkArrowSize := Value;
    Invalidate;
  end;
end;

procedure TCustomPlanner.SetHourType(const value: THourType);
begin
  if FHourType <> value then
  begin
    FHourType := value;
    FGrid.Invalidate;
  end;
end;

procedure TCustomPlanner.SetGridTopRow(const value: Integer);
begin
  if (value <> FGrid.TopRow) then
  begin
    if (value <= FGrid.RowCount - FGrid.VisibleRowCount) then
    begin
      if value < FGrid.FixedRows then
        FGrid.TopRow := FGrid.FixedRows
      else
        FGrid.TopRow := value;
    end
    else
      FGrid.TopRow := FGrid.RowCount - FGrid.VisibleRowCount;
  end;
end;

function TCustomPlanner.GetGridTopRow: Integer;
begin
  Result := FGrid.TopRow;
end;

procedure TCustomPlanner.SetGridLeftCol(const value: Integer);
begin
  if (csLoading in ComponentState) then
  begin
    FLoadLeftCol := value;
  end;

  if (PositionWidth = 0) and (Sidebar.Position <> spTop) then
    Exit;

  if (FGrid.ColCount - FGrid.VisibleColCount < value) then
    FGrid.LeftCol := FGrid.ColCount - FGrid.VisibleColCount
  else
    FGrid.LeftCol := value;
end;

function TCustomPlanner.GetGridLeftCol: Integer;
begin
  Result := FGrid.LeftCol;
end;

procedure TCustomPlanner.SetPositions(const value: Integer);
var
  ColorIndex: Integer;
  PlannerColorArrayPointer: PPlannerColorArray;
begin
  if value <= 0 then
    Exit;

  if value = FPositions then
    Exit;

  FPositions := value;

  // If SelectionAlways = false, prevent that changes to grid cause invalid selection
  // v2.0.0.6
  SelectCells(1, 1, 0);

  // Force Sidebar & position update
  Sidebar.Position := Sidebar.Position;

  // Synchronize Header with nr of positions

  FPlannerHeader.Captions.BeginUpdate;
  while FPlannerHeader.Captions.Count <= FPositions do
    FPlannerHeader.Captions.Add('');
  FPlannerHeader.Captions.EndUpdate;

  FPlannerFooter.Captions.BeginUpdate;
  while FPlannerFooter.Captions.Count <= FPositions do
    FPlannerFooter.Captions.Add('');
  FPlannerFooter.Captions.EndUpdate;

  if PositionGroup > 0 then
  begin
    FPlannerHeader.GroupCaptions.BeginUpdate;
    while FPlannerHeader.GroupCaptions.Count <= (Positions div PositionGroup) do
      FPlannerHeader.GroupCaptions.Add('');
    FPlannerHeader.GroupCaptions.EndUpdate;
  end;

  FPlannerHeader.ItemsChanged(Self);

  // Synchronize the background Color list with the nr. of positions
  while FGrid.ColorList.Count < value do
  begin
    PlannerColorArrayPointer := FGrid.ColorList.Add;
    for ColorIndex := 0 to NumColors do
    begin
      PlannerColorArrayPointer^[ColorIndex].Color := clNone;
      PlannerColorArrayPointer^[ColorIndex].Selected := 0;
    end;
  end;

  while FGrid.ColorList.Count > value do
    FGrid.ColorList.Delete(FGrid.ColorList.Count - 1);

  if Footer.Visible and Footer.ShowCompletion then
    UpdateCompletion;
end;

procedure TCustomPlanner.SetPositionAutoSize(const value: Boolean);
begin
  FPositionAutoSize := value;
  if FPositionAutoSize then
    DoPositionAutoSize;
end;

function TCustomPlanner.HTMLDBReplace(APlannerItem: TPlannerItem;
  Data: TObject): string;
begin
end;

function TCustomPlanner.IsDBAware: Boolean;
begin
  Result := False;
end;

{$IFDEF DELPHIXE_LVL}
procedure TCustomPlanner.GridGesture(Sender: TObject; const EventInfo: TGestureEventInfo; var Handled: Boolean);
begin
   if Assigned(OnGesture) then
     OnGesture(Self, EventInfo, Handled);
end;

function TCustomPlanner.GetTouch: TTouchManager;
begin
  Result := FGrid.Touch;
end;

procedure TCustomPlanner.SetTouch(Avalue: TTouchManager);
begin
  FGrid.Touch.Assign(AValue);
end;
{$ENDIF}

procedure TCustomPlanner.DoPositionAutoSize;
var
  i, X: Integer;
begin
  if not PositionAutoSize then
    Exit;

  if PositionWidth <= 0 then
    Exit;

  for i := 1 to Positions do
  begin
    if PositionWidths[i - 1] <> PositionZoomWidth then
    begin
      X := Items.MaxItemsInPos(i - 1);
      PositionWidths[i - 1] := Max(X, 1) * PositionWidth;
    end;
  end;
end;

procedure TCustomPlanner.SetPositionWidth(const value: Integer);
begin
  if (value <> FPositionWidth) then
  begin
    FPositionWidth := value;
    FGrid.UpdatePositions;
  end;
end;

procedure TCustomPlanner.SetPlannerItems(const value: TPlannerItems);
begin
  FPlannerItems := value;
end;

procedure TCustomPlanner.SetCaption(const value: TPlannerCaption);
begin
  FCaption := value;
  FPanel.Repaint;
end;

procedure TCustomPlanner.SetDayNames(const value: TStringList);
begin
  if Assigned(value) then
    FDayNames.Assign(value);
  Self.Repaint;
end;

procedure TCustomPlanner.SetDisplay(const value: TPlannerDisplay);
begin
  FDisplay := value;
end;

procedure TCustomPlanner.SetHeader(const value: TPlannerHeader);
begin
  FPlannerHeader := value;
end;

procedure TCustomPlanner.SetFooter(const value: TPlannerFooter);
begin
  FPlannerFooter := value;
end;

procedure TCustomPlanner.SetMode(const value: TPlannerMode);
begin
  FMode := value;
end;

procedure TCustomPlanner.SetSideBar(const value: TPlannerSideBar);
begin
  FSidebar := value;
end;

procedure TCustomPlanner.WMEraseBkGnd(var Message: TWMEraseBkgnd);
begin
  Message.Result := 0;
end;

procedure TCustomPlanner.UpdateSizes;
begin
  if Sidebar.Orientation = soVertical then
  begin
    if FPlannerHeader.Visible then
    begin
      FHeader.Visible := True;
      FHeader.Top := FPanel.Height;
      FHeader.Height := FPlannerHeader.Height;
    end
    else
    begin
      FHeader.Height := 0;
      FHeader.Visible := False;
    end;

    if FPlannerFooter.Visible then
    begin
      FFooter.Visible := True;
      FFooter.Top := Height - FPlannerFooter.Height;
      FFooter.Left := 0;
      FFooter.Height := FPlannerFooter.Height;
    end
    else
    begin
      FFooter.Left := 0;
      FFooter.Height := 0;
      FFooter.Visible := False;
    end;

    if FNavigatorButtons.Visible then
      FHeader.Width := Self.Width - 2 * BtnWidth
    else
      FHeader.Width := Self.Width;

    FFooter.Width := Self.Width;

    FGrid.Top := FPanel.Height + FHeader.Height;
    FGrid.Left := 0;

    FGrid.Width := Self.Width;
    FGrid.Height := Self.Height - FPanel.Height - FHeader.Height - FFooter.Height;
    FPanel.Width := Self.Width;

    if FNavigatorButtons.Visible and FPlannerHeader.Visible then
    begin
      FHeader.Left := BtnWidth;
      FNext.Top := FPanel.Height;
      FNext.Left := Width - BtnWidth;

      FNext.Width := BtnWidth;
      FNext.Height := FHeader.Height;
      FPrev.Height := FHeader.Height;
      FPrev.Width := BtnWidth;
    end
    else
      FHeader.Left := 0;
  end
  else
  begin
    if FPlannerHeader.Visible then
    begin
      FHeader.Visible := True;
      FHeader.Top := FPanel.Height;
      FHeader.Left := 0;
      FHeader.Width := FPlannerHeader.Height;
      FHeader.Height := Self.Height - FPanel.Height;
    end
    else
    begin
      FHeader.Width := 0;
      FHeader.Visible := False;
    end;

    if FPlannerFooter.Visible then
    begin
      FFooter.Visible := True;
      FFooter.Top := FPanel.Height;
      FFooter.Left := Width - FPlannerFooter.Height;
      FFooter.Width := FPlannerFooter.Height;
      FFooter.Height := Self.Height - FPanel.Height;
    end
    else
    begin
      FFooter.Width := 0;
      FFooter.Visible := False;
    end;

    FGrid.Top := FPanel.Height;
    FGrid.Left := FHeader.Width;
    FGrid.Width := Self.Width - FHeader.Width - FFooter.Width;
    FGrid.Height := Self.Height - FPanel.Height;
    FPanel.Width := Self.Width;
  end;
end;

procedure TCustomPlanner.UpdateTimer;
begin
  if csLoading in ComponentState then
    Exit;
  if (FDisplay.ShowCurrent or FDisplay.ShowCurrentItem or FEnableAlarms or
      FEnableFlashing or FSidebar.TimeIndicator) and (FTimerID = 0) then
    FTimerID := SetTimer(Handle, 1, 500, nil);

  if not(FDisplay.ShowCurrent or FDisplay.ShowCurrentItem or FEnableAlarms or
      FEnableFlashing or FSidebar.TimeIndicator) and (FTimerID <> 0) then
  begin
    KillTimer(Handle, FTimerID);
    FTimerID := 0;
  end;
end;

function TCustomPlanner.IsSelected(AIndex, APosition: Integer): Boolean;
begin
  Result := (AIndex >= SelItemBegin) and (AIndex < SelItemEnd) and
    (APosition = SelPosition);
end;

function TCustomPlanner.IsVisibleCell(X, Y: integer): boolean;
var
  r: TRect;
begin
  r := FGrid.CellRect(X,Y);
  Result := (r.Left > 0) or (r.Top > 0) or (r.Right > 0) or (r.Bottom > 0);
end;

function TCustomPlanner.GetSelItemEnd: Integer;
begin
  if (Sidebar.Orientation = soVertical) then
    Result := FGrid.Selection.Bottom + 1
  else
    Result := FGrid.Selection.Right + 1;
end;

function TCustomPlanner.GetSelItemBegin: Integer;
begin
  if Sidebar.Orientation = soVertical then
    Result := FGrid.Selection.Top
  else
    Result := FGrid.Selection.Left;
end;

function TCustomPlanner.GetSelPosition: Integer;
begin
  case FSidebar.Position of
    spLeft, spLeftRight:
      Result := FGrid.Selection.Left - 1;
    spRight:
      Result := FGrid.Selection.Left;
    spTop:
      Result := FGrid.Selection.Top - 1;
  else
    Result := FGrid.Selection.Left - 1;
  end;
end;

function TCustomPlanner.XYToSelection(X, Y: Integer): TPoint;
begin
  case FSidebar.Position of
    spLeft, spLeftRight:
      Result.Y := X - 1;
    spRight:
      Result.Y := X;
    spTop:
      Result.Y := Y - 1;
  else
    Result.Y := X - 1;
  end;

  if Sidebar.Orientation = soVertical then
    Result.X := Y + 1
  else
    Result.X := X + 1;
end;

procedure TCustomPlanner.SetSelItemEnd(const value: Integer);
var
  GridRect: TGridRect;
begin
  GridRect := FGrid.Selection;

  if Sidebar.Orientation = soVertical then
    GridRect.Bottom := value
  else
    GridRect.Right := value;

  FGrid.Selection := GridRect;
end;

procedure TCustomPlanner.SetSelItemBegin(const value: Integer);
var
  GridRect: TGridRect;
begin
  GridRect := FGrid.Selection;

  if Sidebar.Orientation = soVertical then
    GridRect.Top := value
  else
    GridRect.Left := value;

  FGrid.Selection := GridRect;
end;

procedure TCustomPlanner.SetSelPosition(value: Integer);
var
  GridRect: TGridRect;
begin
  GridRect := FGrid.Selection;

  Inc(value);

  if Sidebar.Orientation = soVertical then
  begin
    GridRect.Left := value;
    GridRect.Right := value;
  end
  else
  begin
    GridRect.Top := value;
    GridRect.Bottom := value;
  end;

  if Mode.PlannerType = plMultiMonth then
  begin
    if GridRect.Bottom > 31 then
      GridRect.Bottom := 31;
    if GridRect.Right > 31 then
      GridRect.Right := 31;
  end;

  FGrid.Selection := GridRect;
end;

procedure TCustomPlanner.SetGradientSteps(const value: Integer);
begin
  if (value <> FGradientSteps) then
  begin
    FGradientSteps := value;
    Invalidate;
  end;
end;

procedure TCustomPlanner.SetGradientHorizontal(const value: Boolean);
begin
  if (value <> FGradientHorizontal) then
  begin
    FGradientHorizontal := value;
    Invalidate;
  end;
end;

procedure TCustomPlanner.SelChange(Sender: TObject);
begin
  if Assigned(FOnItemSelChange) then
    FOnItemSelChange(Sender, FRichEdit.FPlannerItem);
end;

function TCustomPlanner.XYToCell(X, Y: Integer): TPoint;
var
  GridCoord: TGridCoord;
begin
  GridCoord := FGrid.MouseCoord(X, Y);
  if {(FSidebar.Visible) and} (FSidebar.Position in [spLeft, spLeftRight]) then
    GridCoord.X := GridCoord.X - 1;
  if {(FSidebar.Visible) and} (FSidebar.Position = spTop) then
    GridCoord.Y := GridCoord.Y - 1;
  Result := Point(GridCoord.X, GridCoord.Y);
end;

function TCustomPlanner.XYToItem(X, Y: Integer): TPlannerItem;
var
  CellPoint: TPoint;
  GridRect: TRect;
  iBegin, iPos: Integer;

begin
  CellPoint := XYToCell(X, Y);

  //  Result := CellToItem(CellPoint.X, CellPoint.Y);

  if Sidebar.Orientation = soVertical then
  begin
    GridRect := FGrid.CellRectEx(CellPoint.X + Sidebar.FColOffset, CellPoint.Y);
    iBegin := CellPoint.Y;
    iPos := CellPoint.X;
    Result := Items.FindItemPos(iBegin, iPos, X - GridRect.Left);
  end
  else
  begin
    GridRect := FGrid.CellRectEx(CellPoint.X, CellPoint.Y + Sidebar.FRowOffset);
    iBegin := CellPoint.X;
    iPos := CellPoint.Y;
    Result := Items.FindItemPos(iBegin, iPos, Y - GridRect.Top);
  end;
end;

function TCustomPlanner.CellToItem(X, Y: Integer): TPlannerItem;
begin
  if Sidebar.Orientation = soVertical then
    Result := Items.FindItemPos(Y, X, 1)
  else
    Result := Items.FindItemPos(X, Y, 1);
end;

function TCustomPlanner.CellToItemIdx(X, Y, Index: Integer): TPlannerItem;
begin
  if Sidebar.Orientation = soVertical then
    Result := Items.FindItemPosIdx(Y, X, Index)
  else
    Result := Items.FindItemPosIdx(X, Y, Index);
end;

function TCustomPlanner.CellToItemNum(X, Y: Integer): Integer;
var
  APlannerItem: TPlannerItem;
begin
  if Sidebar.Orientation = soVertical then
    APlannerItem := Items.FindItem(Y, X)
  else
    APlannerItem := Items.FindItem(X, Y);

  if Assigned(APlannerItem) then
    Result := APlannerItem.FConflicts
  else
    Result := 0;
end;

procedure TCustomPlanner.SelectionToAbsTime(var dtStart, dtEnd: TDateTime);
var
  tdt: TDateTime;
begin
  CellToAbsTime(SelItemBegin, dtStart, dtEnd);

  if (Mode.PlannerType in [plDay, plHalfDayPeriod, plTimeLine]) then
    CellToAbsTime(SelItemEnd, dtEnd, tdt)
  else
    CellToAbsTime(SelItemEnd - 1, dtEnd, tdt);

  if (Mode.PlannerType = plDay) and (SelItemBegin <> SelItemEnd) and
    (dtEnd = dtStart) then
  begin
    dtEnd := dtEnd + 1;
  end;
end;

function TCustomPlanner.HasActiveDays: boolean;
var
  I: integer;
begin
  Result := False;

  for I := 1 to 7 do
  begin
    if (I in FInactive) then
      Result := true;
  end;
end;

function TCustomPlanner.AddActiveDays(ADate: TDateTime; Days: integer): TDateTime;
begin
  Result := ADate;

  if not HasActiveDays then
  begin
    Result := ADate + Days;
  end
  else
  begin

    if Days < 0 then
    begin
      while (Days < 0) do
      begin
        Result := Result - 1;
        if not (DayOfWeek(Result) in FInactive) then
          inc(Days);
      end;
    end
    else
      while (Days > 0) do
      begin
        Result := Result + 1;
        if not (DayOfWeek(Result) in FInactive) then
          dec(Days);
      end;
  end;
end;

function TCustomPlanner.DiffActiveDays(ADate1: TDateTime; ADate2: TDateTime): integer;
begin
  Result := 0;
  while Int(ADate1) <> Int(ADate2) do
  begin
    if ADate1 < ADate2 then
    begin
      ADate1 := ADate1 + 1;
      if not (DayOfWeek(ADate1) in FInactive) then
        inc(Result);
    end
    else
    begin
      ADate2 := ADate2 + 1;
      if not (DayOfWeek(ADate2) in FInactive) then
        inc(Result);
    end;
  end;
end;

procedure TCustomPlanner.CellToAbsTime(X: Integer; var dtStart, dtEnd: TDateTime);
var
  res: Integer;
  ANow: TDateTime;
  dday, dx: Integer;
  flgs,flge: Boolean;
begin
  case Mode.PlannerType of
    plDay:
      begin
        ANow := Now;
        if Assigned(FOnGetCurrentTime) then
          FOnGetCurrentTime(Self, ANow);

        res := ((X + Display.DisplayStart) * Display.DisplayUnit)
          + Display.DisplayOffset;

        flgs := False;
        flge := False;

        while res >= 1440 do
        begin
          res := res - 1440;
          flgs := True;
        end;

        if (res div 60 < 24) then
          dtStart := PosToDay(SelPosition) + EncodeTime(res div 60, res mod 60, 0, 0);

        res := res + Display.DisplayUnit;

        while res >= 1440 do
        begin
          res := res - 1440;
          flge := True;
        end;

        if (res div 60 < 24) then
          dtEnd := PosToDay(SelPosition) + EncodeTime(res div 60, res mod 60,
            0, 0);

        if flgs then
          dtStart := dtStart + 1;

        if flge then
          dtEnd := dtEnd + 1;

      end;
    plWeek:
      begin
        dtStart := Mode.StartOfMonth + X;
        dtEnd := dtStart + 1;
      end;
    plMonth:
      begin
        dtStart := Mode.StartOfMonth + X;
        dtEnd := dtStart + 1;
      end;
    plActiveDayPeriod:
      begin
        dtStart := AddActiveDays(Mode.PeriodStartDate, X);
        dtEnd := AddActiveDays(dtStart, 1);
      end;
    plDayPeriod:
      begin
        dtStart := Mode.PeriodStartDate + X;
        dtEnd := dtStart + 1;
      end;
    plHalfDayPeriod:
      begin
        dtStart := Mode.PeriodStartDate + X / 2;
        dtEnd := dtStart + 0.5;
      end;
    plMultiMonth:
      begin
        dtStart := EncodeDate(Mode.Year, Mode.Month, 1);

        if X < PlanUtil.DaysInMonth(Mode.Month, Mode.Year) then
          dtStart := EncodeDate(Mode.Year, Mode.Month, X + 1);
        dtEnd := dtStart;
      end;
    plCustom, plCustomList:
      begin
        dtStart := IndexToTime(X);
        dtEnd := IndexToTime(X + 1);
      end;
    plTimeLine:
      begin
        // # divisions / day
        dday := (MININDAY div Display.DisplayUnit)
          - Mode.TimeLineNVUBegin - Mode.TimeLineNVUEnd;

        dx := X;
        while (dday > 0) and (dx < 0) do
          dx := dx + dday;

        if dday = 0 then
          dday := 1;

        dtStart := int(Mode.TimeLineStart) + X div dday;
        res := ((dx mod dday) + Mode.TimeLineNVUBegin) * Display.DisplayUnit;

        if res >= MININDAY then
        begin
          dtStart := dtStart + (res div MININDAY);
          res := res mod MININDAY;
        end;

        dtStart := dtStart + EncodeTime(res div 60, res mod 60, 0, 0);
        dtEnd := int(Mode.TimeLineStart) + X div dday;

        res := ((dx mod dday) + Mode.TimeLineNVUBegin + 1)
          * Display.DisplayUnit;

        if res >= MININDAY then
        begin
          dtEnd := dtEnd + (res div MININDAY);
          res := res mod MININDAY;
        end;

        dtEnd := dtEnd + EncodeTime(res div 60, res mod 60, 0, 0);

        if (X < 0) and (dx mod dday <> 0) then
        begin
          dtStart := dtStart - 1;
          dtEnd := dtEnd - 1;
        end;

        {
        res := ((X + Display.DisplayStart) * Display.DisplayUnit) + Display.DisplayOffset;

        dtStart := int(Mode.TimeLineStart);

        if res >= MinInDay then
        begin
          dtStart := dtStart + (res div MinInDay);
        end;

        res := res mod MinInDay;

        dtStart :=  dtStart + EncodeTime(res div 60, res mod 60, 0, 0);

        res := Display.DisplayUnit;

        dtEnd := dtStart + EncodeTime(res div 60, res mod 60, 0, 0);
        }
      end;
  end;
end;

function TCustomPlanner.GetEditColor(AItem: TPlannerItem; Sel: Boolean): TColor;
begin
  if Sel then
    Result := AItem.SelectColor
  else
    Result := Color;
{$IFDEF TMSSKINS}
  if AItem.Shape = psSkin then
  begin
    if Sel then
    begin
      if Assigned(Skin.SkinSelectCenter) then
        if not Skin.SkinSelectCenter.Empty then
          Result := Skin.SkinSelectCenter.Canvas.Pixels
            [Skin.SkinSelectCenter.Width div 2,
            Skin.SkinSelectCenter.Height div 2];
    end
    else
    begin
      if Assigned(Skin.SkinCenter) then
        if not Skin.SkinCenter.Empty then
          Result := Skin.SkinCenter.Canvas.Pixels[Skin.SkinCenter.Width div 2,
            Skin.SkinCenter.Height div 2];
    end;
  end;
{$ENDIF}
end;

procedure TCustomPlanner.SetGroupGapOnly(AValue: Boolean);
begin
  FGroupGapOnly := AValue;
  Invalidate;
end;

function TCustomPlanner.GapAtColumn(ACol: Integer): Boolean;
var
  RCol: Integer;
begin
  if (Sidebar.Position in [spLeft, spLeftRight]) then
    RCol := ACol - 1
  else
    RCol := ACol;

  if (PositionProps.Count > RCol) and (RCol >= 0) then
    Result := PositionProps[RCol].ShowGap
  else
    Result := True;

  if GroupGapOnly and (PositionGroup > 0) then
    Result := (RCol mod PositionGroup) = 0;
end;

procedure TCustomPlanner.ItemDesignChange(Sender: TObject);
begin
  if Items.Count > 0 then
    Items[0].AssignEx(FDefaultItem);
end;

procedure TCustomPlanner.SetShowDesignHelper(const value: Boolean);
begin
  FShowDesignHelper := value;
  Invalidate;
end;

procedure TCustomPlanner.UpdateCompletion;
var
  i, j, C: Integer;
begin
  if not Footer.ShowCompletion then
    Exit;

  FFooter.BeginUpdate;

  while (Footer.Captions.Count <= Positions) do
    Footer.Captions.Add('');

  if Assigned(OnPlannerUpdateCompletion) then
    OnPlannerUpdateCompletion(Self);

  for i := 1 to Positions do
  begin
    if Sidebar.Position = spRight then
      j := i - 1
    else
      j := i;

    if (not Footer.CustomCompletionValue) then
    begin
      C := GetPositionCompletion(i - 1, Footer.CompletionType = ctActiveTime);
      Footer.Captions[j] := IntToStr(C);
    end;
  end;

  FFooter.EndUpdate;
end;

function TCustomPlanner.GetPositionCompletion(Position: Integer;
  Active: Boolean): Integer;
var
  i, R: Integer;
  plIt: TPlannerItem;
  StartIdx, EndIdx: Integer;
  ActiveStart, ActiveEnd: Integer;
  FoundNonHeader: Boolean;

begin
  R := 0;

  if (PositionProps.Count > Position) then
    ActiveStart := PositionProps[Position].ActiveStart
  else if (Display.ActiveStart < 0) or
    (Display.ActiveStart = Display.ActiveEnd) then
    ActiveStart := Display.DisplayStart
  else
    ActiveStart := Display.ActiveStart;

  if (PositionProps.Count > Position) then
    ActiveEnd := PositionProps[Position].ActiveEnd
  else if (Display.ActiveEnd < 0) or (Display.ActiveStart = Display.ActiveEnd)
    then
    ActiveEnd := Display.DisplayEnd
  else
    ActiveEnd := Display.ActiveEnd;

  if Active and (ActiveStart < ActiveEnd) then
  begin
    StartIdx := ActiveStart;
    EndIdx := ActiveEnd - 1;
  end
  else
  begin
    StartIdx := 0;
    EndIdx := Display.DisplayEnd - Display.DisplayStart;
  end;

  for i := StartIdx to EndIdx do
  begin
    plIt := Items.FindFirst(i, i + 1, Position);

    if Assigned(plIt) then
    begin
      if not plIt.InHeader then
        Inc(R)
      else
      begin
        FoundNonHeader := False;
        repeat
          plIt := Items.FindNext(i, i + 1, Position);
          if Assigned(plIt) then
            if not plIt.InHeader then
              FoundNonHeader := True;
        until not Assigned(plIt) or FoundNonHeader;
        if FoundNonHeader then
          Inc(R);
      end;
    end;
  end;

  Result := Round(100 * R / (EndIdx - StartIdx + 1));
end;

function TCustomPlanner.AbsTimeToCell(DateTime: TDateTime): Integer;
var
  Year, Month, Day, Hour, Minute, Second, Second100: Word;
  DateTimeStart: TDateTime;
  dday: Integer;

begin
  Result := 0;
  case Mode.PlannerType of
    plDay:
      begin
        DecodeTime(DateTime, Hour, Minute, Second, Second100);
        Minute := Minute + Hour * 60;
        Result := ((Minute - Display.DisplayOffset) div Display.DisplayUnit) - Display.DisplayStart;
      end;
    plWeek:
      begin
        Result := Trunc(DateTime - Mode.StartOfMonth);
      end;
    plMonth:
      begin
        DecodeDate(DateTime, Year, Month, Day);
        Result := Day - 1;
      end;
    plActiveDayPeriod:
      begin
        DateTimeStart := Mode.PeriodStartDate;
        Result := DiffActiveDays(DateTimeStart, DateTime);
      end;
    plDayPeriod:
      begin
        DateTimeStart := Mode.PeriodStartDate;
        if DateTime > DateTimeStart then
          Result := Round(DateTime - DateTimeStart);
      end;
    plHalfDayPeriod:
      begin
        DateTimeStart := Mode.PeriodStartDate;
        if DateTime > DateTimeStart then
          Result := Round(2 * (DateTime - DateTimeStart));
      end;
    plMultiMonth:
      begin
      end;
    plCustom, plCustomList:
      begin
        Result := TimeToIndex(DateTime);
      end;
    plTimeLine:
      begin
        // divisions / day
        dday := (MININDAY div Display.DisplayUnit) - Mode.TimeLineNVUBegin - Mode.TimeLineNVUEnd;

        // position based on day
        if (DateTime < Mode.TimeLineStart) and (frac(DateTime) <> 0) then
          Result := (Trunc(int(DateTime - Mode.TimeLineStart)) * dday) - dday
        else
          Result := Trunc(int(DateTime - Mode.TimeLineStart)) * dday;

        DecodeTime(DateTime, Hour, Minute, Second, Second100);
        Minute := Minute + Hour * 60;

        // check if time overflows nvu end

        if Minute > 1440 - Mode.TimeLineNVUEnd * Display.DisplayUnit then
          Minute := 1440 - Mode.TimeLineNVUEnd * Display.DisplayUnit;
        // max. value allowed

        if Minute >= Mode.TimeLineNVUBegin * Display.DisplayUnit then
          Minute := Minute - Mode.TimeLineNVUBegin * Display.DisplayUnit
        else
          Minute := 0;

        Result := Result + (Minute div Display.DisplayUnit);
        {
        DecodeTime(DateTime, Hour, Minute, Second, Second100);
        Minute := Minute + Hour * 60;
        Result := ((Minute - Display.DisplayOffset) div Display.DisplayUnit) - Display.DisplayStart;
        DecodeDate(DateTime, Year, Month, Day);
        Result := Result +  (MININDAY div Display.DisplayUnit) * Round((Int(DateTime - Mode.TimeLineStart)));
        }
      end;
  end;
end;

function TCustomPlanner.CellInCurrTime(X, Y: Integer): Boolean;
var
  DateTime: TDateTime;
  dtStart, dtEnd: TDateTime;
  BCurPos: Boolean;
  da, mo, ye: Word;
  dx: integer;
begin
  Result := False;

  CellToAbsTime(X, dtStart, dtEnd);

  if Mode.PlannerType = plMultiMonth then
  begin
    DecoDedate(dtStart, ye, mo, da);

    while (mo + Y - 1 > 12) do
    begin
      Inc(ye);
      Dec(Y, 12);
    end;
    mo := mo + Y - 1;

    if da <= PlanUtil.DaysInMonth(mo, ye) then
    begin
      dtStart := EncodeDate(ye, mo, da);
      dtEnd := dtStart + 1;
    end
    else
      Exit;
  end;

  DateTime := Now;

  if Assigned(FOnGetCurrentTime) then
  begin
    FOnGetCurrentTime(Self, DateTime);

    if (Mode.PlannerType = plDay) then
    begin
      dx := Round(Int(DateTime) - Int(Mode.Date));
      Display.CurrentPosFrom := dx;
      Display.CurrentPosTo := dx;
    end;
  end;

  if (Mode.PlannerType = plDay) then
  begin
//    if int(dtStart) = 0 then
    begin
      //DateTime := Frac(DateTime);
      dtStart := Int(Mode.Date) + Frac(dtstart);
      dtEnd := Int(Mode.Date) + Frac(dtEnd);
    end;
  end;


  if Sidebar.Orientation = soVertical then
    BCurPos := IsCurPos(Y - Sidebar.FColOffset)
  else
    BCurPos := IsCurPos(Y - Sidebar.FRowOffset);

  Result := ((DateTime >= dtStart) and (DateTime <= dtEnd)) and
    (FDisplay.ShowCurrent) and BCurPos;
end;

procedure TCustomPlanner.MovePosition(FromPos, ToPos: Integer);
var
  ItemIndex: Integer;
begin
  {Add extra Position}
  Items.BeginUpdate;

  if ToPos > FromPos then
    Inc(ToPos);

  InsertPosition(ToPos);
  if (ToPos < FromPos) then
    Inc(FromPos);
  with Self.Items do
    for ItemIndex := 0 to Count - 1 do
    begin
      if Items[ItemIndex].ItemPos = FromPos then
        Items[ItemIndex].ItemPos := ToPos;
    end;

  Header.Captions.Strings[ToPos + 1] := Header.Captions.Strings[FromPos + 1];
  Header.Captions.Objects[ToPos + 1] := Header.Captions.Objects[FromPos + 1];

  Footer.Captions.Strings[ToPos + 1] := Footer.Captions.Strings[FromPos + 1];
  Footer.Captions.Objects[ToPos + 1] := Footer.Captions.Objects[FromPos + 1];

  DeletePosition(FromPos);

  Items.EndUpdate;
end;

procedure TCustomPlanner.DefineProperties(Filer: TFiler);
begin
  inherited;
  Filer.DefineProperty('TMSStyle',ReadTMSStyle, WriteTMSStyle, True);
end;

procedure TCustomPlanner.DeletePosition(Position: Integer);
var
  ItemIndex: Integer;
begin
  Items.BeginUpdate;
  ItemIndex := 0;

  with Self.Items do
    while (ItemIndex < Count) do
    begin
      if Items[ItemIndex].ItemPos > Position then
      begin
        Items[ItemIndex].ItemPos := Items[ItemIndex].ItemPos - 1;
        Inc(ItemIndex);
      end
      else if Items[ItemIndex].ItemPos = Position then
        Items[ItemIndex].Free
      else
        Inc(ItemIndex);

    end;
  Positions := Positions - 1;
  Items.EndUpdate;
  Header.Captions.Delete(Position + 1);
  Footer.Captions.Delete(Position + 1);
end;

procedure TCustomPlanner.InsertPosition(Position: Integer);
var
  ItemIndex: Integer;
begin
  Items.BeginUpdate;
  Positions := Positions + 1;
  with Items do
    for ItemIndex := 0 to Count - 1 do
    begin
      if Items[ItemIndex].ItemPos >= Position then
        Items[ItemIndex].ItemPos := Items[ItemIndex].ItemPos + 1;
    end;
  Items.EndUpdate;
  Header.Captions.Insert(Position + 1, '');
  Footer.Captions.Insert(Position + 1, '');
end;

procedure TCustomPlanner.HideSelection;
begin
  FGrid.HideSelection;
end;

procedure TCustomPlanner.UnHideSelection;
begin
  FGrid.UnHideSelection;
end;

procedure TCustomPlanner.SetItemGap(const value: Integer);
begin
  if FItemGap <> value then
  begin
    FItemGap := value;
    Invalidate;
  end;
end;

{$IFDEF DELPHIXE2_LVL}
procedure TCustomPlanner.CMStyleChanged(var Message: TMessage);
begin
  InitVCLStyle(true);
end;
{$ENDIF}

procedure TCustomPlanner.WMTimer(var Message: TWMTimer);
var
  ac, i: Integer;
  ANow: TDateTime;
  Msg: string;
  CondA, CondB: Boolean;

begin
  inherited;

  if Assigned(FOnTimer) then
    FOnTimer(Self);
  ANow := Now;
  if Assigned(FOnGetCurrentTime) then
    FOnGetCurrentTime(Self, ANow);

  if not(csDesigning in ComponentState) and EnableFlashing then
  begin
    for i := 1 to Items.Count do
    begin
      if Items[i - 1].Flashing then
      begin
        Items[i - 1].FlashOn := not Items[i - 1].FlashOn;
        Items[i - 1].Repaint;
      end;
    end;
  end;

  if not(csDesigning in ComponentState) and EnableAlarms and
    (GetCapture <> FGrid.Handle) and not FHandlingAlarm then
  begin

    for i := 1 to Items.Count do
    begin
      with Items[i - 1].Alarm do

        if Active and (Assigned(Handler) or Assigned(FOnItemAlarm)) then
        begin
          if Items[i - 1].RealTime then
          begin
            CondB := (ANow + TimeBefore > Items[i - 1].ItemRealStartTime) and
              (ANow <= Items[i - 1].ItemRealStartTime);

            CondA := (ANow + TimeAfter > Items[i - 1].ItemRealEndTime);
          end
          else
          begin
            CondB := (Frac(ANow) + Frac(TimeBefore) > Frac
                (Items[i - 1].ItemStartTime)) and
              (Frac(ANow) <= Frac(Items[i - 1].ItemStartTime));

            if CondB then
            begin
              CondB := ((int(ANow) = int(Items[i - 1].FItemRealStartTime)) or
                  (int(Items[i - 1].FItemRealStartTime) = 0));
            end;

            CondA := (Frac(ANow) + Frac(TimeAfter) > Frac
                (Items[i - 1].ItemEndTime)) and
              (((int(ANow) >= int(Items[i - 1].ItemEndTime)) or
                  (int(Items[i - 1].ItemEndTime) = 0)));

            if CondA then
            begin
              CondA := ((int(ANow) >= int(Items[i - 1].FItemRealEndTime)) or
                  (int(Items[i - 1].FItemEndTime) = 0));
            end;

          end;

          if (CondB and (Items[i - 1].Alarm.Time in [atBefore, atBoth])) or
            (CondA and (Items[i - 1].Alarm.Time in [atAfter, atBoth])) then
          begin
            Active := False;
            FHandlingAlarm := True;

            case NotifyType of
              anCaption:
                Msg := HTMLStrip(Items[i - 1].CaptionText);
              anMessage:
                Msg := Items[i - 1].Alarm.Message;
              anNotes:
                Msg := HTMLStrip(Items[i - 1].Text.Text);
            end;

            if Assigned(FOnItemAlarm) then
              FOnItemAlarm(Self, Items[i - 1]);

            if Assigned(Handler) then
            begin
              if not Handler.HandleAlarm(Address, Msg, Tag, ID, Items[i - 1])
                then
                Active := True;
            end;
            FHandlingAlarm := False;
          end;
        end;
    end;
  end;

  ac := AbsTimeToCell(ANow);

  if (ac <> FTimerActiveCells) then
  begin
    if Sidebar.Orientation = soHorizontal then
    begin
      FGrid.InvalidateCol(FTimerActiveCells);
      FTimerActiveCells := ac;
      FGrid.InvalidateCol(FTimerActiveCells);
    end
    else
    begin
      FGrid.InvalidateRow(FTimerActiveCells);
      FTimerActiveCells := ac;
      FGrid.InvalidateRow(FTimerActiveCells);
    end;
  end;

  if FDisplay.ShowCurrentItem then
  begin
    Items.SetCurrent(ac);
  end;

  if FSidebar.TimeIndicator and (Mode.PlannerType in [plTimeLine, plDay]) then
  begin
    if Mode.PlannerType = plTimeLine then
      i := AbsTimeToCell(Now)
    else
      i := AbsTimeToCell(Frac(Now));

    if (i <> FTimerIdxCell) then
    begin
      FTimerIdxCell := i;
      if FSidebar.Position <> spTop then
      begin
        FGrid.InvalidateCell(0, i - 1);
        FGrid.InvalidateCell(0, i);
      end
      else
      begin
        FGrid.InvalidateCell(i - 1, 0);
        FGrid.InvalidateCell(i, 0);
      end;
    end;
  end;
end;

procedure TCustomPlanner.WndProc(var Message: TMessage);
{$IFDEF DELPHI6_LVL}
var
  ShiftState: TShiftState;
{$ENDIF}
begin
  if (Message.Msg = WM_THEMECHANGED) or (Message.Msg = WM_OFFICETHEMECHANGED) then
  begin
    if FAutoThemeAdapt then
      ThemeAdapt;
  end;

  if (Message.Msg = WM_DESTROY) then
  begin
    if Assigned(FDisplay) then
    begin
      if ((FDisplay.ShowCurrent) or (FDisplay.ShowCurrentItem)) and
        (FTimerID <> 0) then
        KillTimer(Handle, FTimerID);
    end
    else if (FTimerID <> 0) then
      KillTimer(Handle, FTimerID);

    FTimerID := 0;
  end;
{$IFDEF DELPHI6_LVL}
  if (Message.Msg = CM_CHILDKEY) then
  begin
    ShiftState := KeyDataToShiftState(Message.LParam);
    if (Message.wParam = VK_INSERT) and (ShiftState = []) then
      Message.Result := 0;
  end;
{$ENDIF}
  inherited;
end;

procedure TCustomPlanner.WriteTMSStyle(Writer: TWriter);
begin
  Writer.WriteInteger(integer(FTMSStyle));
end;

function TCustomPlanner.GetMemo: TMemo;
begin
  Result := FGrid.FMemo;
end;

function TCustomPlanner.GetMaskEdit: TMaskEdit;
begin
  Result := FGrid.FMaskEdit;
end;

procedure TCustomPlanner.InactiveChanged(Sender: TObject);
begin
  FInactive := [];
  if FInactiveDays.FSun then
    FInactive := FInactive + [1];
  if FInactiveDays.FMon then
    FInactive := FInactive + [2];
  if FInactiveDays.FTue then
    FInactive := FInactive + [3];
  if FInactiveDays.FWed then
    FInactive := FInactive + [4];
  if FInactiveDays.FThu then
    FInactive := FInactive + [5];
  if FInactiveDays.FFri then
    FInactive := FInactive + [6];
  if FInactiveDays.FSat then
    FInactive := FInactive + [7];
  Invalidate;
end;

procedure TCustomPlanner.PreviewPaint(APlannerItem: TPlannerItem;
  Canvas: TCanvas; R: TRect; Direction, Print: Boolean);
begin
  APlannerItem.Repainted := false;
  if not Direction then
    FGrid.PaintItemCol(Canvas, R, APlannerItem, Print, False)
  else
    FGrid.PaintItemRow(Canvas, R, APlannerItem, Print, False);
end;

procedure TCustomPlanner.SetDefaultItem(const value: TPlannerItem);
begin
  FDefaultItem.Assign(value);
end;

procedure TCustomPlanner.SetSelectColor(const value: TColor);
begin
  if FSelectColor <> value then
  begin
    FSelectColor := value;
    Invalidate;
  end;
end;

procedure TCustomPlanner.SetShowSelection(const value: Boolean);
begin
  if FShowSelection <> value then
  begin
    FShowSelection := value;
    Invalidate;
  end;
end;

procedure TCustomPlanner.SetFlat(const value: Boolean);
begin
  if value <> FFlat then
  begin
    if value then
    begin
      FGrid.BorderStyle := bsNone;
      FGrid.Ctl3D := False;
    end
    else
    begin
      FGrid.BorderStyle := bsSingle;
      FGrid.Ctl3D := True;
    end;
    FFlat := value;
  end;
  FGrid.UpdatePositions;
end;

procedure TCustomPlanner.ClearImageCache;
begin
  FImageCache.ClearPictures;
end;

procedure TCustomPlanner.AutoSizeHeader;
var
  PositionIndex, MaxItemPerPosition: Integer;
  MaxItemOverAll: Integer;
  APlannerItem: TPlannerItem;

begin
  MaxItemOverAll := 0;

  for PositionIndex := 0 to Positions - 1 do
  begin
    MaxItemPerPosition := 0;
    APlannerItem := Items.HeaderFirst(PositionIndex);

    while Assigned(APlannerItem) do
    begin
      Inc(MaxItemPerPosition);
      APlannerItem := Items.HeaderNext(PositionIndex);
    end;

    if (MaxItemPerPosition > MaxItemOverAll) then
      MaxItemOverAll := MaxItemPerPosition;
  end;

  FNoPositionSize := True;
  Header.Height := Header.TextHeight + MaxItemOverAll * Header.ItemHeight + 2;
  FNoPositionSize := False;
end;

procedure TCustomPlanner.SetPositionGap(const value: Integer);
begin
  if FPositionGap <> value then
  begin
    FPositionGap := value;
    FGrid.Invalidate;
  end;
end;

procedure TCustomPlanner.SetPositionGapColor(const value: TColor);
begin
  if FPositionGapColor <> value then
  begin
    FPositionGapColor := value;
    FGrid.Invalidate;
  end;
end;

procedure TCustomPlanner.Notification(AComponent: TComponent; AOperation: TOperation);
var
  i: Integer;
begin
  inherited;

  if csDestroying in ComponentState then
    Exit;

  if (AOperation = opRemove) and (AComponent = FPlannerImages) then
    FPlannerImages := nil;
  if (AOperation = opRemove) and (AComponent = FContainer) then
    FContainer := nil;
  if (AOperation = opRemove) and (AComponent = FPlanChecker) then
    FPlanChecker := nil;

  if (AOperation = opRemove) and Assigned(DefaultItem) then
  begin
    if DefaultItem.Alarm.Handler = AComponent then
      DefaultItem.Alarm.Handler := nil;
    if DefaultItem.Editor = AComponent then
      DefaultItem.Editor := nil;
    if DefaultItem.PopupMenu = AComponent then
      DefaultItem.PopupMenu := nil;
    if DefaultItem.DrawTool = AComponent then
      DefaultItem.DrawTool := nil;
  end;

  if (AOperation = opRemove) and Assigned(Items) then
  begin
    for i := 1 to Items.Count do
    begin
      if Items[i - 1].Alarm.Handler = AComponent then
        Items[i - 1].Alarm.Handler := nil;

      if Items[i - 1].Editor = AComponent then
        Items[i - 1].Editor := nil;

      if Items[i - 1].PopupMenu = AComponent then
        Items[i - 1].PopupMenu := nil;

      if Items[i - 1].DrawTool = AComponent then
        Items[i - 1].DrawTool := nil;

    end;
  end;

  if not (csDestroying in ComponentState) then
  begin
    if Assigned(FSyncPlanner) and (AOperation = opRemove) and (AComponent = FSyncPlanner.Planner) then
      FSyncPlanner.Planner := nil;
  end;

end;

procedure TCustomPlanner.ItemMoved(APlannerItem: TPlannerItem;
  FromBegin, FromEnd, FromPos, ToBegin, ToEnd, ToPos: Integer);
var
  i: Integer;
  NewBegin, NewEnd, NewPos: Integer;

begin
  if (FromBegin = ToBegin) and (FromEnd = ToEnd) and (FromPos = ToPos) then
    Exit;

  if not Assigned(APlannerItem) then
    Exit;

  if Assigned(FOnItemMove) then
    FOnItemMove(Self, APlannerItem, FromBegin, FromEnd, FromPos, ToBegin,
      ToEnd, ToPos);

  Items.Changing := True;
  if Assigned(APlannerItem) then
  begin
    if APlannerItem.ParentIndex >= 0 then
    begin
      i := 0;
      while i < Items.Count do
      begin
        if (Items[i] <> APlannerItem) and
          (Items[i].ParentIndex = APlannerItem.ParentIndex) then
        begin
          NewBegin := Items[i].ItemBegin + ToBegin - FromBegin;
          NewEnd := Items[i].ItemEnd + ToEnd - FromEnd;
          NewPos := Items[i].ItemPos + ToPos - FromPos;

          if (NewPos < 0) or (NewPos >= Positions) or
            (NewBegin < Display.DisplayStart) or
            (NewEnd > Display.DisplayEnd + 1) then
          begin
            if Items[i].RelationShip = irParent then
              APlannerItem.RelationShip := irParent;
            Items[i].Free;
          end
          else
          begin
            Items[i].ItemBegin := NewBegin;
            Items[i].ItemEnd := NewEnd;
            Items[i].ItemPos := NewPos;
            Inc(i);
          end;
        end
        else
          Inc(i);
      end;
    end;
  end;

  Items.Changing := False;
end;

procedure TCustomPlanner.ItemSized(APlannerItem: TPlannerItem;
  FromBegin, FromEnd, ToBegin, ToEnd: Integer);
var
  i: Integer;
  NewBegin, NewEnd: Integer;

begin
  if (FromBegin = ToBegin) and (FromEnd = ToEnd) then
    Exit;

  if not Assigned(APlannerItem) then
    Exit;

  if Assigned(FOnItemSize) then
    FOnItemSize(Self, APlannerItem, APlannerItem.ItemPos, FromBegin, FromEnd,
      ToBegin, ToEnd);

  Items.Changing := True;

  if Assigned(APlannerItem) then
  begin
    if APlannerItem.ParentIndex >= 0 then
    begin
      i := 0;
      while i < Items.Count do
      begin
        if (Items[i] <> APlannerItem) and
          (Items[i].ParentIndex = APlannerItem.ParentIndex) then
        begin

          NewBegin := Items[i].ItemBegin + ToBegin - FromBegin;

          NewEnd := Items[i].ItemEnd + ToEnd - FromEnd;

          if (NewBegin < Display.DisplayStart) or
            (NewEnd > Display.DisplayEnd + 1) then
          begin
            if Items[i].RelationShip = irParent then
              Items.Selected.RelationShip := irChild;
            Items[i].Free;
          end
          else
          begin
            Items[i].ItemBegin := NewBegin;
            Items[i].ItemEnd := NewEnd;
            Inc(i);
          end
        end
        else
          Inc(i);
      end;
    end;
  end;

  Items.Changing := False;
end;

procedure TCustomPlanner.ItemEdited(Item: TPlannerItem);
begin
  if Assigned(ItemChecker) then
  begin
    if ItemChecker.AutoCorrect then
      Item.Text.Text := ItemChecker.Correct(Item.Text.Text);

    if ItemChecker.AutoMarkError then
      Item.Text.Text := ItemChecker.MarkError(Item.Text.Text);
  end;

  if Assigned(FOnItemEndEdit) then
  begin
    FOnItemEndEdit(Self, Item);
    // Workaround for hanging selection when OnItemEndEdit takes focus away
    // from the Planner. Set Planner.GridControl.MouseRelease := true from event code
    if FGrid.MouseRelease then
    begin
      PostMessage(FGrid.Handle, WM_LBUTTONUP, 0, 0);
    end;
  end;

  FEditMode := False;
end;

function TCustomPlanner.CreateItem: TPlannerItem;
begin
  Result := Items.Add;
  FGrid.UpdateNVI;
end;

function TCustomPlanner.FindItemLinkedTo(Item: TPlannerItem): TPlannerItem;
var
  i: integer;
begin
  Result := nil;

  for I := 0 to Items.Count - 1 do
  begin
    if (Items[I].LinkedItem = Item) then
    begin
      Result := Items[I];
      Break;
    end;
  end;
end;

procedure TCustomPlanner.SelectLinkedItems(Item: TPlannerItem);
var
  AItem: TPlannerItem;
begin
  if Assigned(Item) then
  begin
    Item.Selected := true;

    AItem := Item;

    repeat
      AItem := FindItemLinkedTo(AItem);
      if Assigned(AItem) then
        AItem.Selected := true;
    until (AItem = nil);

    while Assigned(Item.LinkedItem) do
    begin
      Item := Item.LinkedItem;
      Item.Selected := true;
    end;
  end;
end;

procedure TCustomPlanner.UnLinkItems(Items: TPlannerItemArray);
var
  I: Integer;
begin
  for I := 0 to Length(Items) - 1 do
  begin
    Items[I].LinkedItem := nil;
    Items[I].LinkType := ltLinkNone;
  end;
  Invalidate;
end;

procedure TCustomPlanner.LinkItems(Items: TPlannerItemArray; Circular: boolean = false; LinkType: TPlannerLinkType = ltLinkNone);
var
  i: integer;
begin
  for I := 0 to Length(Items) - 2 do
  begin
    Items[I].LinkedItem := Items[I + 1];
    Items[I].LinkType := LinkType;
  end;

  if Circular then
  begin
    Items[Length(Items) - 1].LinkedItem := Items[0];
    Items[Length(Items) - 1].LinkType := LinkType;
  end;
  Invalidate;
end;

function TCustomPlanner.CloneItem(Item: TPlannerItem): TPlannerItem;
begin
  Result := Items.Add;
  Result.Assign(Item);
  Result.RelationShip := irChild;
  Item.RelationShip := irParent;
  Item.ParentIndex := Item.Index;
  Result.ParentIndex := Item.Index;
end;

procedure TCustomPlanner.RemoveClones(Item: TPlannerItem);
var
  i, Idx: Integer;
begin
  Idx := Item.ParentIndex;
  i := 0;
  while (i < Items.Count) do
  begin
    if (Items[i].ParentIndex = Idx) and (Items[i].RelationShip = irChild) then
      Items[i].Free
    else
      Inc(i);
  end;

end;

procedure TCustomPlanner.FreeItem(APlannerItem: TPlannerItem);
var
  i: Integer;
  DBKey: string;

begin
  if (APlannerItem.Recurrent) and (APlannerItem.DBKey <> '') then
  begin
    DBKey := APlannerItem.DBKey;

    for i := Items.Count - 1 downto 0 do
    begin
      if (Items[i].DBKey = DBKey) and (Items[i] <> APlannerItem) then
        Items[i].Free;
    end;
  end;

  if Items.FSelected = APlannerItem then
    Items.FSelected := nil;

  APlannerItem.ParentItem.Free;

  if ShowLinks then
    Invalidate;

  FGrid.UpdateNVI;


  if AutoDeleteLinkedItems then
  begin
    if Assigned(APlannerItem.LinkedItem) then
      FreeItem(APlannerItem.LinkedItem);
  end;

  I := 0;
  while I < Items.Count do
  begin
    if (Items[I].LinkedItem = APlannerItem) then
    begin
      Items[I].LinkedItem := nil;
      Items[I].LinkType := ltLinkNone;
      if AutoDeleteLinkedItems then
        FreeItem(Items[I]);
    end;
    inc(I);
  end;
end;

procedure TCustomPlanner.StopEditing;
begin
  FGrid.SetFocus;
end;

procedure TCustomPlanner.UpdateItem(APlannerItem: TPlannerItem);
begin
  // only used by DBPlanner
end;

procedure TCustomPlanner.RefreshItem(APlannerItem: TPlannerItem);
begin
  // only used by DBPlanner
end;

procedure TCustomPlanner.MapItemTimeOnPlanner(APlannerItem: TPlannerItem);
begin

end;

procedure TCustomPlanner.SetTrackWidth(const value: Integer);
begin
  if FTrackWidth <> value then
  begin
    FTrackWidth := value;
    Invalidate;
  end;
end;

procedure TCustomPlanner.PlanTimeToStrings(MinutesValue: Integer;
  var HoursString: string; var MinutesString: string;
  var AmPmString: string);
var
  Hours, Minutes: Integer;

  function ChooseNonEmpty(s1, s2: string): string;
  begin
    if s2 = '' then
      Result := s1
    else
      Result := s2;
  end;

begin
  while MinutesValue < 0 do
    MinutesValue := MinutesValue + MININDAY;

  Hours := MinutesValue div 60;
  Minutes := MinutesValue mod 60;
  Hours := Hours mod 24;

  MinutesString := Format('%.2d', [Minutes]);

  case HourType of
    ht24hrs:
      AmPmString := '';
    ht12hrs:
      if Hours > 12 then
        Hours := Hours - 12;
    htAMPM0:
      begin
        if Hours >= 12 then
          AmPmString := ChooseNonEmpty('PM', TimePMString)
        else
          AmPmString := ChooseNonEmpty('AM', TimeAMString);
        if Hours > 12 then
          Hours := Hours - 12
      end;
    htAMPM1:
      begin
        if Hours in [1 .. 12] then
          AmPmString := ChooseNonEmpty('AM', TimePMString)
        else
          AmPmString := ChooseNonEmpty('PM', TimeAMString);
        if Hours > 12 then
          Hours := Hours - 12
      end;
    htAMPMOnce:
      begin
        If Minutes = 0 then
        begin
          AmPmString := '';
          if Hours >= 12 then
            MinutesString := ChooseNonEmpty('PM', TimePMString)
          else
            MinutesString := ChooseNonEmpty('AM', TimeAMString);
        end;
        if Hours > 12 then
          Hours := Hours - 12
      end;
  end;

  HoursString := Format('%d', [Hours]);

  if Assigned(OnPlanTimeToStrings) then
    OnPlanTimeToStrings(Self, MinutesValue, HoursString, MinutesString,
      AmPmString);
end;

function TCustomPlanner.PlanTimeToStr(MinutesValue: Integer): string;
// Result: "HH:MM" (24 hr format) or "HH:MM ZZ" (12 hr format) where ZZ is TimePMString or TimeAMString
var
  HoursString, MinutesString, AmPmString: string;
begin
  while MinutesValue < 0 do
    MinutesValue := MinutesValue + MININDAY;

  PlanTimeToStrings(MinutesValue, HoursString, MinutesString, AmPmString);
  Result := Format('%s%s%s', [HoursString, TimeSeparator, MinutesString]);
  if AmPmString <> '' then
    Result := Format('%s %s', [Result, AmPmString]);
end;

procedure TCustomPlanner.ItemUnSelected(Item: TPlannerItem);
begin
  if Assigned(OnItemUnSelect) then
    OnItemUnSelect(Self, Item);
end;

procedure TCustomPlanner.ItemSelected(Item: TPlannerItem);
begin
  if Assigned(OnItemSelect) then
    OnItemSelect(Self, Item);
end;

procedure TCustomPlanner.SetShadowColor(const value: TColor);
begin
  if FShadowColor <> value then
  begin
    FShadowColor := value;
    Invalidate;
  end;
end;

procedure TCustomPlanner.SetURLColor(const value: TColor);
begin
  if FURLColor <> value then
  begin
    FURLColor := value;
    Invalidate;
  end;
end;

procedure TCustomPlanner.SetURLGlyph(const value: TBitmap);
begin
  FURLGlyph.Assign(value);
  Invalidate;
end;

procedure TCustomPlanner.SetDeleteGlyph(const value: TBitmap);
begin
  FDeleteGlyph.Assign(value);
  Invalidate;
end;

procedure TCustomPlanner.SetAttachementGlyph(const value: TBitmap);
begin
  FAttachementGlyph.Assign(value);
  Invalidate;
end;

procedure TCustomPlanner.SetAutoThemeAdapt(const Value: Boolean);
begin
  if (Value <> FAutoThemeAdapt) then
  begin
    FAutoThemeAdapt := Value;
    if FAutoThemeAdapt then
    begin
      ThemeAdapt;
      Invalidate;
    end;

    if not (csDesigning in ComponentState) and
       HandleAllocated and not (csLoading in ComponentState) then
    begin
      if FAutoThemeAdapt then
        ThemeNotifier(Self).RegisterWindow(Handle)
      else
        ThemeNotifier(Self).UnRegisterWindow(Handle)
    end;
  end;
end;

procedure TCustomPlanner.HeaderSized(Sender: TObject;
  ASection, AWidth: Integer);
begin
  if ASection = 0 then
  begin
    if Sidebar.Position = spTop then
      AWidth := FGrid.RowHeights[0]
    else
    begin
      if not NavigatorButtons.Visible then
        AWidth := FGrid.ColWidths[0]
      else
        AWidth := FGrid.ColWidths[0] - BtnWidth;
    end;

    if FFlat then
      FHeader.SectionWidth[0] := AWidth
    else
      FHeader.SectionWidth[0] := AWidth + 2;

    if FFlat then
      FFooter.SectionWidth[0] := AWidth
    else
      FFooter.SectionWidth[0] := AWidth + 2;

  end
  else
  begin
    if Header.ResizeAll then
    begin
      //      if FNavigatorButtons.Visible then
      //        PositionWidth := AWidth// + BtnWidth
      //      else
      PositionWidth := AWidth;
    end
    else
      PositionWidths[ASection - 1] := AWidth;

    if Assigned(OnHeaderSized) then
      OnHeaderSized(Self, ASection - 1, AWidth);
  end;
end;

function TCustomPlanner.CreateItemAtSelection: TPlannerItem;
begin
  Result := Items.Add;
  Result.ItemBegin := SelItemBegin;
  Result.ItemEnd := SelItemEnd;
  Result.ItemPos := SelPosition;

  FGrid.UpdateNVI;
end;

function TCustomPlanner.CloneItemAtSelection(Item: TPlannerItem): TPlannerItem;
begin
  Result := CloneItem(Item);
  Result.ItemBegin := SelItemBegin;
  Result.ItemEnd := SelItemEnd;
  Result.ItemPos := SelPosition;
end;

procedure TCustomPlanner.SetEnableAlarms(const value: Boolean);
begin
  FEnableAlarms := value;
  UpdateTimer;
end;

procedure TCustomPlanner.SetEnableFlashing(const value: Boolean);
begin
  FEnableFlashing := value;
  UpdateTimer;
end;

procedure TCustomPlanner.SetPositionProps(const value: TPositionProps);
begin
  FPositionProps.Assign(value);
end;

function TCustomPlanner.CreateItems: TPlannerItems;
begin
  Result := TPlannerItems.Create(Self);
end;

procedure TCustomPlanner.ReadTMSStyle(Reader: TReader);
begin
  FTMSStyle := TTMSStyle(Reader.ReadInteger);
end;

procedure TCustomPlanner.Refresh;
begin
end;

function TCustomPlanner.IndexToTime(Index: Integer): TDateTime;
begin
  Result := 0;

  if Mode.PlannerType = plCustomList then
  begin
    if Index < FDTList.Count then
      Result := FDTList.Items[Index];
  end;

  if Assigned(FOnCustomITEvent) then
    FOnCustomITEvent(Self, Index, Result);
end;

procedure TCustomPlanner.InitVCLStyle(init: boolean);
{$IFDEF DELPHIXE2_LVL}
var
  LStyle: TCustomStyleServices;
  LDetails: TThemedElementDetails;
  clr: TColor;
{$ENDIF}
begin
  FUseVCLStyles := False;

{$IFDEF DELPHIXE2_LVL}
  LStyle := StyleServices;

  if LStyle.Enabled and (LStyle.Name <> 'Windows') then
  begin
    FUseVCLStyles := True;
    Header.Flat := true;
    LStyle.GetElementColor(LStyle.GetElementDetails(tgCellNormal), ecFillColor, clr);
    Color := clr;
    Display.ColorActive := clr;
    Display.ColorNonActive := clr;

    LStyle.GetElementColor(LStyle.GetElementDetails(tgCellNormal), ecBorderColor, clr);

    GridLineColor := clr;
    Display.HourLineColor := clr;
    SideBar.LineColor := clr;
    Header.LineColor := clr;
    SideBar.BorderColor := clr;

    LStyle.GetElementColor(LStyle.GetElementDetails(tgFixedCellNormal), ecBorderColor, clr);
    //GridFixedLineColor := clr;

    //Options := Options - [goFixedVertLine] - [goFixedHorzLine];

    LStyle.GetElementColor(LStyle.GetElementDetails(tgCellNormal), ecTextColor, clr);

    LDetails := LStyle.GetElementDetails(tgCellNormal);
    if LStyle.GetElementColor(LDetails, ecTextColor, clr) and (clr <> clNone) then
      Font.Color := clr;

    LDetails := LStyle.GetElementDetails(tgCellSelected);

    if LStyle.GetElementColor(LDetails, ecTextColor, clr) and (clr <> clNone) then
    begin
      //SelectionTextColor := clr;
    end;

    if LStyle.GetElementColor(LDetails, ecFillColor, clr) and (clr <> clNone) then
    begin
      SelectColor := clr;
    end;

    LDetails := LStyle.GetElementDetails(tgFixedCellNormal);
    if LStyle.GetElementColor(LDetails, ecFillColor, clr) and (clr <> clNone) then
    begin
    //  FixedFont.Color := clr;
      SideBar.Background := clr;
      SideBar.BackgroundTo := clNone;
      SideBar.ActiveColor := clNone;

      Header.Color := clr;
      Header.ColorTo := clNone;
      Header.ActiveColor := clNone;
      Caption.Background := clr;
      Caption.BackgroundTo := clr;
    end;

    if LStyle.GetElementColor(LDetails, ecTextColor, clr) and (clr <> clNone) then
    begin
      if Sidebar.Background = clWhite then
        clr := clBlack;

      Caption.Font.Color := clr;
      SideBar.Font.Color := clr;
      Header.Font.Color := clr;
    end;

  end
  else
  begin
    if init then
    begin
      Color := clWindow;
      GridLineColor := clSilver;
      Header.Flat := false;

      Display.ColorActive := $00FCEBDC;
      Display.ColorNonActive := clWhite;
      Display.HourLineColor := $00CEA27D;
      SideBar.ActiveColor := $00FCEBDC;
      SideBar.ActiveColorTo := $00FCDBC1;

      SideBar.Background := $00FDFBFA;
      SideBar.BackgroundTo := $00FDF3EB;
      Header.ActiveColor := $00FCEBDC;
      Header.ActiveColorTo := $00FCDBC1;

      Header.Color := $00FDFBFA;
      Header.ColorTo := $00FDF3EB;
      Header.LineColor := clGray;
      Caption.Background := $00FCEBDC;
      Caption.BackgroundTo := $00FCDBC1;

      //GridFixedLineColor := clGray;
      //Options := Options + [goFixedVertLine] + [goFixedHorzLine];
      Font.Color := clBlack;
    end;
  end;
{$ENDIF}

end;

{$IFNDEF DELPHI7_LVL}
function CompareDateTime(dt1,dt2: TDateTime): integer;
begin
  Result := -1;

  if (dt1 = dt2) then
    Result := 0
  else
    if (dt1 > dt2) then
      Result := 1;
end;
{$ENDIF}

function TCustomPlanner.TimeToIndex(DT: TDateTime): Integer;
var
  Idx,cr: Integer;

begin
  Result := 0;
  if Mode.PlannerType = plCustomList then
  begin
    Idx := 0;
    while Idx < FDTList.Count do
    begin
      cr := CompareDateTime(FDTList.Items[Idx], DT);

      case cr of
      0: Result := Idx;
      1: Result := Idx - 1;
      -1: Inc(Idx);
      end;
      if (cr in [0, 1]) then
        Break;
    end;
  end;

  if Assigned(FOnCustomTIEvent) then
    FOnCustomTIEvent(Self, DT, Result);
end;

function TCustomPlanner.PosToDay(Pos: Integer): TDateTime;
begin
  Result := 0;

  if (Mode.PlannerType = plDay) and (Mode.Year > 0) and (Mode.Month > 0) and (Mode.Month < 13) and (Mode.Day > 0) and (Mode.Day < 32) then
  begin
    Result := EncodeDate(Mode.Year, Mode.Month, Mode.Day);

    if not Mode.MultiResource then
      Result := Result + Pos;
  end;

  if Assigned(FOnPositionToDay) then
    FOnPositionToDay(Self, Pos, Result);
end;

procedure TCustomPlanner.SetFlashColor(const value: TColor);
begin
  if FFlashColor <> value then
  begin
    FFlashColor := value;
    Invalidate;
  end;
end;

procedure TCustomPlanner.SetFlashFontColor(const value: TColor);
begin
  if FFlashFontColor <> value then
  begin
    FFlashFontColor := value;
    Invalidate;
  end;
end;

procedure TCustomPlanner.ExportItem(APlannerItem: TPlannerItem);
begin
  APlannerItem.DoExport := True;
end;

procedure TCustomPlanner.ExportItems;
var
  i: Integer;
begin
  for i := 1 to Items.Count do
    Items.Items[i - 1].DoExport := True;
end;

procedure TCustomPlanner.ExportClear;
var
  i: Integer;
begin
  for i := 1 to Items.Count do
    Items.Items[i - 1].DoExport := False;
end;

procedure TCustomPlanner.ExportLayer(Layer: Integer);
var
  i: Integer;
begin
  for i := 1 to Items.Count do
    if Items.Items[i - 1].Layer and Layer = Layer then
      Items.Items[i - 1].DoExport := True;
end;

procedure TCustomPlanner.ExportPosition(Pos: Integer);
var
  i: Integer;
begin
  for i := 1 to Items.Count do
    if Items.Items[i - 1].ItemPos = Pos then
      Items.Items[i - 1].DoExport := True;
end;

procedure TCustomPlanner.HilightInItem(APlannerItem: TPlannerItem;
  AText: string; DoCase: Boolean);
begin
  APlannerItem.Text.Text := Hilight(APlannerItem.Text.Text, AText, 'hi',
    DoCase);
end;

procedure TCustomPlanner.HilightInItems(AText: string; DoCase: Boolean);
var
  i: Integer;
begin
  for i := 1 to Items.Count do
    Items.Items[i - 1].Text.Text := Hilight(Items.Items[i - 1].Text.Text,
      AText, 'hi', DoCase);
end;

procedure TCustomPlanner.HilightInPositon(Pos: Integer; AText: string;
  DoCase: Boolean);
var
  i: Integer;
begin
  for i := 1 to Items.Count do
    if Items.Items[i - 1].ItemPos = Pos then
      Items.Items[i - 1].Text.Text := Hilight(Items.Items[i - 1].Text.Text,
        AText, 'hi', DoCase);
end;

procedure TCustomPlanner.MarkInItem(APlannerItem: TPlannerItem; AText: string;
  DoCase: Boolean);
begin
  APlannerItem.Text.Text := Hilight(APlannerItem.Text.Text, AText, 'e', DoCase);
end;

procedure TCustomPlanner.MarkInItems(AText: string; DoCase: Boolean);
var
  i: Integer;
begin
  for i := 1 to Items.Count do
    Items.Items[i - 1].Text.Text := Hilight(Items.Items[i - 1].Text.Text,
      AText, 'e', DoCase);
end;

procedure TCustomPlanner.MarkInPositon(Pos: Integer; AText: string;
  DoCase: Boolean);
var
  i: Integer;
begin
  for i := 1 to Items.Count do
    if Items.Items[i - 1].ItemPos = Pos then
      Items.Items[i - 1].Text.Text := Hilight(Items.Items[i - 1].Text.Text,
        AText, 'e', DoCase);
end;

procedure TCustomPlanner.UnHilightInItem(APlannerItem: TPlannerItem);
begin
  APlannerItem.Text.Text := UnHilight(APlannerItem.Text.Text, 'hi');
end;

procedure TCustomPlanner.UnHilightInItems;
var
  i: Integer;
begin
  for i := 1 to Items.Count do
    Items.Items[i - 1].Text.Text := UnHilight(Items.Items[i - 1].Text.Text,
      'hi');
end;

procedure TCustomPlanner.UnHilightInPositon(Pos: Integer);
var
  i: Integer;
begin
  for i := 1 to Items.Count do
    if Items.Items[i - 1].ItemPos = Pos then
      Items.Items[i - 1].Text.Text := UnHilight(Items.Items[i - 1].Text.Text,
        'hi');
end;

procedure TCustomPlanner.UnMarkInItem(APlannerItem: TPlannerItem);
begin
  APlannerItem.Text.Text := UnHilight(APlannerItem.Text.Text, 'e');
end;

procedure TCustomPlanner.UnMarkInItems;
var
  i: Integer;
begin
  for i := 1 to Items.Count do
    Items.Items[i - 1].Text.Text := UnHilight(Items.Items[i - 1].Text.Text,
      'e');
end;

procedure TCustomPlanner.UnMarkInPositon(Pos: Integer);
var
  i: Integer;
begin
  for i := 1 to Items.Count do
    if Items.Items[i - 1].ItemPos = Pos then
      Items.Items[i - 1].Text.Text := UnHilight(Items.Items[i - 1].Text.Text,
        'e');
end;

function TCustomPlanner.GetDragCopy: Boolean;
begin
  Result := GetKeyState(VK_CONTROL) and $8000 = $8000;
end;

function TCustomPlanner.GetDragMove: Boolean;
begin
  Result := GetKeyState(VK_MENU) and $8000 = $8000;
end;

procedure TCustomPlanner.SetPositionGroup(const value: Integer);
begin
  FPositionGroup := value;
  FHeader.Invalidate;
end;

procedure TCustomPlanner.SetTrackBump(const value: Boolean);
begin
  FTrackBump := value;
  Invalidate;
end;

function TCustomPlanner.GetPositionWidths(Position: Integer): Integer;
begin
  if Sidebar.Visible then
    Inc(Position);

  if Sidebar.Position <> spTop then
    Result := FGrid.ColWidths[Position]
  else
    Result := FGrid.RowHeights[Position];
end;

procedure TCustomPlanner.SetPositionWidths(Position: Integer;
  const value: Integer);
begin
  if Sidebar.Visible then
    Inc(Position);

  if Sidebar.Position <> spTop then
  begin
    if Position >= FGrid.ColCount then
      Exit;
    FGrid.FPosResizing := True;
    FGrid.ColWidths[Position] := value
  end
  else
  begin
    if Position >= FGrid.RowCount then
      Exit;
    FGrid.FPosResizing := True;
    FGrid.RowHeights[Position] := value;
  end;

  if Header.Visible then
    if FHeader.Sections.Count > Position then
      FHeader.SectionWidth[Position] := value;

  if Footer.Visible then
    if FFooter.Sections.Count > Position then
      FFooter.SectionWidth[Position] := value;

  FGrid.FPosResizing := False;
end;

procedure TCustomPlanner.SetPositionZoomWidth(const value: Integer);
begin
  FPositionZoomWidth := value;
  FHeader.Zoom := (FPositionZoomWidth > 0) and
    (PositionZoomWidth > PositionWidth);
  if FHeader.Zoom then
    Header.AllowPositionResize := False
  else
    FHeader.Cursor := crDefault;
end;

procedure TCustomPlanner.SetScrollBars(const Value: TScrollStyle);
begin
  if (FScrollbars <> Value) then
  begin
    if Assigned(FGrid) and FGrid.HandleAllocated then
      FGrid.ScrollBars := Value;
  end;
end;

procedure TCustomPlanner.SetSelectBlend(const value: Integer);
begin
  if (value > 100) or (value < 0) then
    raise Exception.Create('Illegal blend factor');
  FSelectBlend := value;
  Invalidate;
end;

procedure TCustomPlanner.SelectCells(SelBegin, SelEnd, SelPos: Integer);
begin
  SelPosition := SelPos;
  SelItemEnd := SelEnd;
  SelItemBegin := SelBegin;
  SelItemEnd := SelEnd;
  SelItemBegin := SelBegin;

  FGrid.FOldSelection := FGrid.Selection;

  if Sidebar.ActiveColor <> clNone then
    FGrid.Invalidate;

  if Header.ActiveColor <> clNone then
    FHeader.Invalidate;
end;

function TCustomPlanner.ItemInSel(ItemBegin, ItemEnd, ItemPos: integer): boolean;
var
  smi,sma: integer;
begin
  Result := true;
  if GetSelMinMax(ItemPos + 1, smi,sma) then
  begin
    Result := (ItemBegin >= smi) and (ItemEnd <= sma);
  end;
end;

function TCustomPlanner.GetSelMinMax(Pos: Integer; var SelMin, SelMax: Integer): Boolean;
var
  y,m: word;
begin
  Result := False;

  if (PositionProps.Count >= Pos) and (Pos > 0) then
  begin
    if PositionProps[Pos - 1].Use then
    begin
      SelMin := PositionProps[Pos - 1].MinSelection;
      SelMax := PositionProps[Pos - 1].MaxSelection;
      Result := (SelMin <> 0) or (SelMax <> 0);
    end;
  end;

  if (Mode.PlannerType = plMultiMonth) then
  begin
    y := Mode.Year;
    m := Mode.Month + Pos - 1;
    while m > 12 do
    begin
      inc(y);
      m := m - 12;
    end;

    Result := True;
    SelMin := 0;

    SelMax := PlanUtil.DaysInMonth(m,y);
  end;
end;

procedure TCustomPlanner.SetShowHint(const value: Boolean);
begin
  FShowHint := value;
  FGrid.ShowHint := value;
end;

procedure TCustomPlanner.SetShowLinks(const Value: Boolean);
begin
  if (FShowLinks <> Value) then
  begin
    FShowLinks := Value;
    Repaint;
  end;
end;

procedure TCustomPlanner.UnZoomPosition(Pos: Integer);
var
  X: Integer;
begin
  if (Pos >= 0) and (Pos < Positions) and (PositionWidth > 0) and
    (PositionZoomWidth > 0) then
  begin
    if PositionAutoSize and (PositionWidth > 0) then
    begin
      X := Items.MaxItemsInPos(Pos);
      PositionWidths[Pos] := Max(X, 1) * PositionWidth;
    end
    else
      PositionWidths[Pos] := PositionWidth
  end;
end;

procedure TCustomPlanner.ZoomPosition(Pos: Integer);
begin
  if (Pos >= 0) and (Pos < Positions) and (PositionWidth > 0) and
    (PositionZoomWidth > 0) then
  begin
    PositionWidths[Pos] := PositionZoomWidth;
  end;
end;

procedure TCustomPlanner.UpdateNVI;
begin
  FGrid.UpdateNVI;
end;

function TCustomPlanner.GetVersionNr: Integer;
begin
  Result := MakeLong(MakeWord(BLD_VER, REL_VER), MakeWord(MIN_VER, MAJ_VER));
end;

function TCustomPlanner.GetVersion: string;
var
  vn: Integer;
begin
  vn := GetVersionNr;
  Result := IntToStr(Hi(Hiword(vn))) + '.' + IntToStr(Lo(Hiword(vn)))
    + '.' + IntToStr(Hi(Loword(vn))) + '.' + IntToStr(Lo(Loword(vn)));
end;

procedure TCustomPlanner.SetVersion(const value: string);
begin
end;

function TCustomPlanner.GetVersionString: string;
var
  vn: Integer;
begin
  vn := GetVersionNr;
  Result := IntToStr(Hi(Hiword(vn))) + '.' + IntToStr(Lo(Hiword(vn)))
    + '.' + IntToStr(Hi(Loword(vn))) + '.' + IntToStr(Lo(Loword(vn)))
    + ' ' + DATE_VER;
end;

function TCustomPlanner.GetCellTime(i, j: Integer): TDateTime;
var
  res, ID, Y: Integer;
  DT: TDateTime;
begin
  Result := 0;

  case Mode.PlannerType of
    plDay:
      begin
        res := (i + Display.DisplayStart) * Display.DisplayUnit +
          Display.DisplayOffset;
        ID := 0;
        while (res >= 24 * 60) do
        begin
          res := res - 60 * 24;
          Inc(ID);
        end;

        Result := EncodeTime(res div 60, res mod 60, 0, 0);
        Result := Result + PosToDay(j) + ID;
      end;
    plTimeLine:
      begin
        CellToAbsTime(i, Result, DT);
      end;
    plMonth, plWeek:
      begin
        Result := Mode.StartOfMonth + i;
      end;
    plActiveDayPeriod:
      begin
        Result := AddActiveDays(Mode.PeriodStartDate, i);
      end;
    plDayPeriod:
      begin
        Result := Mode.PeriodStartDate + i;
      end;
    plHalfDayPeriod:
      begin
        Result := Mode.PeriodStartDate + i / 2;
      end;
    plMultiMonth:
      begin
        res := Mode.Month + j;
        Y := Mode.Year;
        while (res > 12) do
        begin
          res := res - 12;
          Inc(Y);
        end;
        Result := EncodeDate(Y, res, i + 1);
      end;
    plCustom, plCustomList:
      begin
        Result := IndexToTime(i);
      end;
  end;
end;

function TCustomPlanner.GetComponentStyle: TTMSStyle;
begin
  Result := FTMSStyle;
end;

function TCustomPlanner.CellRect(X, Y: Integer): TRect;
begin
  Result := FGrid.CellRect(X, Y);
end;

function TCustomPlanner.CellToTime(X, Y: Integer): TDateTime;
begin
  if (X < 0) or (Y < 0) then
    raise Exception.Create('Invalid cell coordinates')
  else
  begin
    if Sidebar.Position = spTop then
      Result := GetCellTime(X, Y)
    else
      Result := GetCellTime(Y, X);
  end;
end;

{ TPlannerGrid }

constructor TPlannerGrid.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  ColCount := 2;
  FixedCols := 1;
  FixedRows := 0;
  RowCount := 49;
  ColWidths[0] := 40;
  GridLineWidth := 0;
  FUpdateCount := 0;
  FSaveCellExtents := False;
  Options := [goRangeSelect];
  Width := 200;
  Height := 250;
  DefaultDrawing := False;
  FAutoFocus := true;
  FMoveForm := nil;

  FEraseBkGnd := False;
  FPlanner := AOwner as TCustomPlanner;

  FMemo := TPlannerMemo.Create(Self);
  FMemo.Parent := Self;
  FMemo.Visible := False;
  FMemo.Width := 0;
  FMemo.Height := 0;
  FMemo.Planner := FPlanner;
  FMaskEdit := TPlannerMaskEdit.Create(Self);
  FMaskEdit.Parent := Self;
  FMaskEdit.Visible := False;
  FMaskEdit.Width := 0;
  FMaskEdit.Height := 0;
{$IFNDEF DELPHI_UNICODE}
  FUniMemo := TPlannerUniMemo.Create(Self);
  FUniMemo.Parent := Self;
  FUniMemo.Visible := False;
  FUniMemo.Width := 0;
  FUniMemo.Height := 0;
  FUniMemo.Planner := FPlanner;
{$ENDIF}
  FMouseDownMove := False;
  FMouseDownSizeUp := False;
  FMouseDownSizeDown := False;
  FMouseDownMoveFirst := False;
  FMouseStart := False;

  FColorList := TPlannerColorArrayList.Create;

  FScrollHintWindow := THintWindow.Create(Self);
  FOldSelection := Selection;

  BorderStyle := bsNone;
  Ctl3D := False;
  FInplaceEdit := TEdit.Create(Self);
  FInplaceEdit.Parent := Self;
  FInplaceEdit.Width := 0;
  FInplaceEdit.Height := 0;
  FInplaceEdit.Visible := False;
  FInplaceCombo := TPlanCombobox.Create(Self);
  FInplaceCombo.Parent := Self;
  FInplaceCombo.Width := 0;
  FInplaceCombo.Height := 0;
  FInplaceCombo.Visible := False;
  FInplaceCombo.IsWinXP := IsWinXP;
end;

procedure TPlannerGrid.CreateWnd;
begin
  inherited;
  FPlanner.FRichEdit.Parent := Self;
  FPlanner.FRichEdit.Left := 0;
  FPlanner.FRichEdit.Width := 0;
  FPlanner.FRichEdit.Visible := False;
  FPlanner.FRichEdit.BorderStyle := bsNone;
  FPlanner.FRichEdit.OnSelectionChange := FPlanner.SelChange;
end;

destructor TPlannerGrid.Destroy;
begin
  FPlanner.Items.Clear;
  FMemo.Free;
  FMaskEdit.Free;
  FColorList.Free;
  FScrollHintWindow.Free;
{$IFNDEF DELPHI_UNICODE}
  FUniMemo.Free;
{$ENDIF}
  FInplaceEdit.Free;
  FInplaceCombo.Free;
  inherited Destroy;
end;

procedure TPlannerGrid.SetActiveCellShow(AValue: TActiveCellShow);
begin
  FActiveCellShow := AValue;
  Invalidate;
end;

procedure TPlannerGrid.SetColEx(const Value: Integer);
var
  dosync: boolean;
begin
  dosync := inherited Col <> Value;

  inherited Col := Value;

  if Assigned(FPlanner.FSyncPlanner.Planner) and dosync then
  begin
    if FPlanner.FSyncPlanner.SelectionColumn then
      FPlanner.FSyncPlanner.Planner.GridControl.Col := inherited Col;
  end;
end;

procedure TPlannerGrid.WMPaint(var Message: TWMPaint);
var
  DC, MemDC: hdc;
  MemBitmap, OldBitmap: HBITMAP;
  PS: TPaintStruct;
begin
  if not FDoubleBuffered or (Message.DC <> 0) then
  begin
    if not (csCustomPaint in ControlState) and (ControlCount = 0) then
      inherited
    else
      PaintHandler(Message);
  end
  else
  begin
    DC := GetDC(0);
    MemBitmap := CreateCompatibleBitmap(DC, ClientRect.Right,
      ClientRect.Bottom);
    ReleaseDC(0, DC);
    MemDC := CreateCompatibleDC(0);
    OldBitmap := SelectObject(MemDC, MemBitmap);
    try
      DC := BeginPaint(Handle, PS);
      Perform(WM_ERASEBKGND, MemDC, MemDC);
      Message.DC := MemDC;
      WMPaint(Message);
      Message.DC := 0;
      BitBlt(DC, 0, 0, ClientRect.Right, ClientRect.Bottom, MemDC, 0, 0,
        SRCCOPY);
      EndPaint(Handle, PS);
    finally
      SelectObject(MemDC, OldBitmap);
      DeleteDC(MemDC);
      DeleteObject(MemBitmap);
    end;
  end;
end;


procedure TPlannerGrid.WMRButtonDown(var Msg: TWMLButtonDown);
var
  x,y: integer;
begin

  inherited;

  if not Assigned(FPlanner) then
    Exit;

  if FPlanner.SelectOnRightClick then
  begin
    MouseToCell(Msg.xpos,Msg.ypos,x,y);

    if (x > 0) and (y > 0) then
    begin
      Selection := TGridRect(Rect(x,y,x,y));
    end;
  end;
end;

procedure TPlannerGrid.Resize;
begin
  inherited;

  if not Assigned(FPlanner) then
    Exit;

  if FPosResizing then
    Exit;

  //  FPlanner.FNoPositionSize := True;

  if FPlanner.PositionWidth = 0 then
    UpdatePositions;

  //  FPlanner.FNoPositionSize := True;

  if FPlanner.Display.ScaleToFit then
  begin
    FPosResizing := true;
    FPlanner.Display.AutoScale;
    FPosResizing := false;
  end;
end;

procedure TPlannerGrid.Loaded;
begin
  inherited Loaded;
end;

procedure TPlannerGrid.HideSelection;
begin
  FHiddenSelection := Selection;
  if HandleAllocated then
    Self.Selection := TGridRect(Rect(ColCount, RowCount, ColCount, RowCount))
  else
    Self.Selection := TGridRect(Rect(-1, -1, -1, -1))
end;

procedure TPlannerGrid.UnHideSelection;
begin
  Selection := FHiddenSelection;
end;

procedure TPlannerGrid.BeginUpdate;
begin
  Perform(WM_SETREDRAW, Integer(False), 0);
end;

procedure TPlannerGrid.EndUpdate;
begin
  Perform(WM_SETREDRAW, Integer(True), 0);
  Repaint;
end;


procedure TPlannerGrid.RTFPaint(ACanvas: TCanvas; ARect: TRect;
  const rtf: string; Background: TColor);
const
  RTF_OFFSET = 2;
  TWIPS_FACTOR = 1440;

type
  TFormatRange = record
    hdcSrc: hdc;
    hdcTarget: hdc;
    rc: TRect;
    rcPage: TRect;
    chrg: TCharRange;
  end;
var
  FormatRange: TFormatRange;
  nLogPixelsX, nLogPixelsY: Integer;
  SaveMapMode: Integer;
  SaveText: string;
  SaveSelStart, SaveSelLength: Integer;

begin
  SaveText := FPlanner.RichToText;
  SaveSelStart := FPlanner.RichEdit.SelStart;
  SaveSelLength := FPlanner.RichEdit.SelLength;
  try
    FPlanner.TextToRich(rtf);

    SendMessage(FPlanner.RichEdit.Handle, EM_SETBKGNDCOLOR, 0,
      ColorToRGB(Background));
    FillChar(FormatRange, SizeOf(TFormatRange), 0);

    lptodp(Canvas.Handle, ARect.TopLeft, 1);
    lptodp(Canvas.Handle, ARect.BottomRight, 1);
    nLogPixelsX := GetDeviceCaps(ACanvas.Handle, LOGPIXELSX);
    nLogPixelsY := GetDeviceCaps(ACanvas.Handle, LOGPIXELSY);

    with FormatRange do
    begin
      FormatRange.hdcSrc := ACanvas.Handle;
      FormatRange.hdcTarget := ACanvas.Handle;
      {convert to twips}{ 1440 TWIPS = 1 inch. }
      FormatRange.rcPage.Left := Round
        (((ARect.Left + RTF_OFFSET) / nLogPixelsX) * TWIPS_FACTOR);
      FormatRange.rcPage.Top := Round(((ARect.Top + RTF_OFFSET) / nLogPixelsY)
          * TWIPS_FACTOR);
      FormatRange.rcPage.Right := FormatRange.rcPage.Left + Round
        (((ARect.Right - ARect.Left - RTF_OFFSET) / nLogPixelsX)
          * TWIPS_FACTOR);
      FormatRange.rcPage.Bottom := (FormatRange.rcPage.Top + Round
          (((ARect.Bottom - ARect.Top - RTF_OFFSET) / nLogPixelsY)
            * TWIPS_FACTOR));
      FormatRange.rc := FormatRange.rcPage;
      FormatRange.chrg.cpMin := 0;
      FormatRange.chrg.cpMax := -1;
    end;

    SaveMapMode := GetMapMode(ACanvas.Handle);
    try
      SetMapMode(Canvas.Handle, mm_text);
      SendMessage(FPlanner.FRichEdit.Handle, EM_FORMATRANGE, 1,
        LParam(@FormatRange));
      {clear the richtext cache}
      SendMessage(FPlanner.FRichEdit.Handle, EM_FORMATRANGE, 0, 0);
    finally
      SetMapMode(ACanvas.Handle, SaveMapMode);
    end;

  finally
    FPlanner.TextToRich(SaveText);
    FPlanner.RichEdit.SelStart := SaveSelStart;
    FPlanner.RichEdit.SelLength := SaveSelLength;
  end;
end;
(*
procedure PrintBitmap(Canvas:  TCanvas; DestRect:  TRect;  Bitmap:  TBitmap);
var
  BitmapHeader:  pBitmapInfo;
  BitmapImage:  POINTER;
  HeaderSize :  DWORD;
  ImageSize  :  DWORD;
begin
  GetDIBSizes(Bitmap.Handle, HeaderSize, ImageSize);
  GetMem(BitmapHeader, HeaderSize);
  GetMem(BitmapImage,  ImageSize);
  try
    GetDIB(Bitmap.Handle, Bitmap.Palette, BitmapHeader^, BitmapImage^);
    StretchDIBits(Canvas.Handle,
                  DestRect.Left, DestRect.Top,     // Destination Origin
                  DestRect.Right  - DestRect.Left, // Destination Width
                  DestRect.Bottom - DestRect.Top,  // Destination Height
                  0, 0,                            // Source Origin
                  Bitmap.Width, Bitmap.Height,     // Source Width & Height
                  BitmapImage,
                  TBitmapInfo(BitmapHeader^),
                  DIB_RGB_COLORS,
                  SRCCOPY)
  finally
    FreeMem(BitmapHeader);
    FreeMem(BitmapImage)
  end;
end; {PrintBitmap};
*)

const
  DefaultPixelsPerInch = 96;

function TrackBarWidth(TrackBarLogicalPixels: Integer;
  Canvas: TCanvas): Integer;
begin
  Result := Round(TrackBarLogicalPixels * GetDeviceCaps(Canvas.Handle,
      LOGPIXELSX) / DefaultPixelsPerInch);
end;

function TrackBarHeight(TrackBarLogicalPixels: Integer;
  Canvas: TCanvas): Integer;
begin
  Result := Round(TrackBarLogicalPixels * GetDeviceCaps(Canvas.Handle,
      LOGPIXELSY) / DefaultPixelsPerInch);
end;

function ConcatenateTextStrings(Text: TStrings): string;
var
  Index: Integer;
begin
  Result := '';
  for Index := 0 to Text.Count - 1 do
    Result := Result + Text.Strings[Index];
end;

function StripLineBreaks(s: string): string;
var
  i: integer;
begin
  Result := '';

  for i := 1 to length(s) do
  begin
    if (s[i] <> #13) and (s[i] <> #10) then
      Result := Result + s[i];
  end;
end;


procedure TPlannerGrid.CreateToolTip;
begin
  FHToolTip := CreateWindowEx(0, 'Tooltips_Class32', nil,
    TTS_ALWAYSTIP or TTS_BALLOON or TTS_NOPREFIX, Integer(CW_USEDEFAULT),
    Integer(CW_USEDEFAULT), Integer(CW_USEDEFAULT), Integer(CW_USEDEFAULT),
    Handle, 0, HInstance, nil);

  if FHToolTip <> 0 then
    SetWindowPos(FHToolTip, HWND_TOPMOST, 0, 0, 0, 0,
      SWP_NOMOVE or SWP_NOSIZE or SWP_NOACTIVATE);
end;

procedure TPlannerGrid.DestroyToolTip;
begin
  DestroyWindow(FHToolTip);
end;

procedure TPlannerGrid.AddToolTip(IconType: Integer; Text, Title: string);
var
  Item: THandle;
  Rect: TRect;
  ti: TToolInfo;
  buffer: array [0 .. 255] of Char;
begin
  Item := Self.Handle;

  if (Item <> 0) AND (Windows.GetClientRect(Item, Rect)) then
  begin
    ti.cbSize := SizeOf(TToolInfo);
    ti.uFlags := TTF_SUBCLASS or TTF_IDISHWND;
    ti.hInst := HInstance;

    ti.hwnd := Item;
    ti.Rect := Rect;
    ti.uId := Handle;
    ti.lpszText := LPSTR_TEXTCALLBACK;
    SendMessage(FHToolTip, TTM_ADDTOOL, 0, LParam(@ti));
    FillChar(buffer, SizeOf(buffer), #0);
    lstrcpy(buffer, PChar(Title));
    if (IconType > 3) or (IconType < 0) then
      IconType := 0;
    SendMessage(FHToolTip, TTM_SETTITLE, IconType, LParam(@buffer));
  end;
end;

function TPlannerGrid.MouseOverDesignChoice(X, Y: Integer): Integer;
var
  R: TRect;
  fh: Integer;
begin
  Result := -1;
  R := ClientRect;
  Canvas.Font.Name := 'Tahoma';
  Canvas.Font.Size := 8;

  fh := Canvas.TextHeight('gh') + 2;
  if (X > R.Right - 150) and (X < R.Right - 150 + Canvas.TextWidth(s_HTimeAxis)
    ) and (Y > R.Bottom - 70 + fh + 4) and (Y < R.Bottom - 70 + 2 * fh + 4)
    then
    Result := 1;

  if (X > R.Right - 150) and (X < R.Right - 150 + Canvas.TextWidth
      (s_ShowDesignItem)) and (Y > R.Bottom - 70 + 2 * fh + 4) and
    (Y < R.Bottom - 70 + 3 * fh + 4) then
    Result := 2;

  if (X > R.Right - 150) and (X < R.Right - 150 + Canvas.TextWidth(s_Modes[0]))
    and (Y > R.Bottom - 70 + 3 * fh + 4) and (Y < R.Bottom - 70 + 4 * fh + 4)
    then
    Result := 3;
end;

procedure TPlannerGrid.PaintItemCol(Canvas: TCanvas; ARect: TRect;
  APlannerItem: TPlannerItem; Print, SelColor: Boolean);
var
  PaintString, Anchor, StrippedHTMLString, CaptionPaintString, FocusAnchor: string;
  WideCaptionPaintString: widestring;
  R, ro, hr, CR, sr: TRect;
  ColumnHeight, i, iw, ih, pw, ph, ImageIndex, ml, hl: Integer;
  MultiImage: Boolean;
  HorizontalAlign, DrawFlags: dword;
  rr, dr, XSize, YSize: Integer;
  PlannerImagePoint: TPoint;
  Bitmap: TBitmap;
  Background: TColor;
  BackgroundTo: TColor;
  pt: TPoint;
  tmpBegin, tmpEnd: Integer;
  CellColor, OldColor: TColor;
  CID, CV, CT: string;
  HRGN: THandle;
  gs: TGaugeSettings;
  ch: Integer;

label BackGroundOnly;
begin
  if APlannerItem.Repainted then
    Exit;

  if (APlannerItem.ItemBegin = APlannerItem.ItemEnd) and not APlannerItem.InHeader then
    Exit;

  CellColor := Canvas.Brush.Color;

  if not (csDesigning in FPlanner.ComponentState) and not Print then
    APlannerItem.Repainted := True;

  if not APlannerItem.Background and not APlannerItem.InHeader then
    ARect.Right := ARect.Right - FPlanner.FItemGap;

  if Assigned(APlannerItem.FPlanner.OnPlannerItemDraw) then
  begin
    try
      APlannerItem.FPlanner.OnPlannerItemDraw(APlannerItem.FPlanner,
        APlannerItem, Canvas, ARect, False);
      Exit;
    except
      on e: EAbort do
        {nothing};
    end;
  end;

  if (APlannerItem.Shape = psTool) and Assigned(APlannerItem.DrawTool) then
  begin
    APlannerItem.DrawTool.DrawItem(APlannerItem, Canvas, ARect, APlannerItem.Selected, Print);
    Exit;
  end;

  if APlannerItem.Shadow and not APlannerItem.Background and
    (APlannerItem.Shape = psRect) and not FPlanner.TrackOnly then
  begin
    Canvas.Brush.Color := FPlanner.ShadowColor;
    Canvas.Pen.Color := Canvas.Brush.Color;
    Canvas.Rectangle(ARect.Right - 3, ARect.Top + 3, ARect.Right, ARect.Bottom);
    Canvas.Rectangle(ARect.Left + 3, ARect.Bottom - 3, ARect.Right, ARect.Bottom);
    Canvas.Brush.Color := CellColor;
    Canvas.Pen.Color := CellColor;
    Canvas.Rectangle(ARect.Right - 3, ARect.Top, ARect.Right, ARect.Top + 3);
    Canvas.Rectangle(ARect.Left, ARect.Bottom - 4, ARect.Left + 3, ARect.Bottom - 1);
    ARect.Right := ARect.Right - 3;
    ARect.Bottom := ARect.Bottom - 3;
  end;

  if APlannerItem.Background then
    ARect.Bottom := ARect.Bottom - 1;

  ro := ARect;
  R := ARect;

  APlannerItem.FClipped := False;

  Background := APlannerItem.Color;
  BackgroundTo := APlannerItem.ColorTo;

  if APlannerItem.Selected and APlannerItem.ShowSelection {and
   not APlannerItem.InHeader} then
  begin
    Background := APlannerItem.SelectColor;
    BackgroundTo := APlannerItem.SelectColorTo;
  end;

  if (APlannerItem.Background) then
  begin
    if APlannerItem.BrushStyle <> bsSolid then
    begin
      Canvas.Brush.Color := Background;
      Canvas.Brush.Style := APlannerItem.BrushStyle;
      SetBkMode(Canvas.Handle, Transparent);
      SetBkColor(Canvas.Handle, ColorToRGB(FPlanner.Color));
    end;

    goto BackGroundOnly;
  end;

  // Draw the item trackbar
  R.Right := R.Left + TrackBarWidth(APlannerItem.FPlanner.TrackWidth, Canvas);

  if {not APlannerItem.InHeader and} APlannerItem.TrackVisible and (APlannerItem.Shape = psRect) then
  begin
    if (FPlanner.TrackProportional) then
    begin
      Canvas.Brush.Color := FPlanner.Display.ColorActive;
      Canvas.FillRect(R);

      dr := APlannerItem.FItemBeginPrecis -
        (APlannerItem.FItemBegin + FPlanner.Display.DisplayStart)
        * FPlanner.Display.DisplayUnit - FPlanner.Display.DisplayOffset;

      dr := Round(dr / FPlanner.Display.DisplayUnit *
          FPlanner.Display.DisplayScale);

      rr := Round
        ((APlannerItem.FItemEndPrecis - APlannerItem.FItemBeginPrecis +
            FPlanner.Display.DisplayOffset)
          / FPlanner.Display.DisplayUnit * FPlanner.Display.DisplayScale);
      rr := dr + rr;

      //      rr := Round((APlannerItem.FItemEndPrecis - APlannerItem.FItemBeginPrecis) /
      //        FPlanner.Display.DisplayUnit * FPlanner.Display.DisplayScale) + FPlanner.Display.DisplayOffset;
    end
    else
    begin
      dr := 0;
      rr := R.Bottom - R.Top;
    end;

    R.Bottom := R.Top + rr;
    R.Top := R.Top + dr;

    if APlannerItem.Focus then
      Canvas.Brush.Color := APlannerItem.TrackSelectColor
    else
      Canvas.Brush.Color := APlannerItem.TrackColor;

    if APlannerItem.LinkSelect then
      Canvas.Brush.Color := APlannerItem.TrackLinkColor;

    if (APlannerItem.TrackBrushStyle <> bsSolid) then
    begin
      Canvas.Brush.Style := APlannerItem.TrackBrushStyle;
      Canvas.Brush.Color := clWhite;
      SetBkColor(Canvas.Handle, ColorToRGB(APlannerItem.TrackColor));
    end;

    Canvas.FillRect(R);

    if FPlanner.TrackBump then
      DrawBumpVert(Canvas, R, Canvas.Brush.Color);

    ARect.Left := ARect.Left + TrackBarWidth(APlannerItem.FPlanner.TrackWidth, Canvas);

    for i := 0 to APlannerItem.BarItems.Count - 1 do
    begin
      with APlannerItem.BarItems[i] do
      begin
        tmpBegin := BarBegin;
        tmpEnd := BarEnd;
        if BarBegin = -1 then
          tmpBegin := 0;
        if BarEnd = -1 then
          tmpEnd := APlannerItem.ItemEnd - APlannerItem.ItemBegin;

        rr := (R.Bottom - R.Top) div
          (APlannerItem.ItemEnd - APlannerItem.ItemBegin);
        sr.Top := R.Top + (tmpBegin * rr);
        sr.Bottom := R.Top + (tmpEnd * rr);
        sr.Left := R.Left;
        sr.Right := ARect.Left;
        Canvas.Brush.Color := BarColor;
        Canvas.Pen.Color := APlannerItem.TrackColor;
        Canvas.Brush.Style := BarStyle;
        Canvas.Rectangle(sr.Left, sr.Top, sr.Right, sr.Bottom);
      end;
    end;
  end;

  if FPlanner.TrackOnly then
    Exit;

  if APlannerItem.FIsCurrent and not Print then
  begin
    Background := FPlanner.FDisplay.FColorCurrentItem;
    Canvas.Brush.Color := Background;
  end
  else
  begin
    if APlannerItem.BrushStyle <> bsSolid then
    begin
      Background := APlannerItem.Color;

      Canvas.Brush.Color := Background;
      Canvas.Brush.Style := APlannerItem.BrushStyle;
      SetBkMode(Canvas.Handle, Transparent);
      SetBkColor(Canvas.Handle, ColorToRGB(FPlanner.Color));
    end
    else
      Canvas.Brush.Color := Background;
  end;

  if APlannerItem.Flashing and APlannerItem.FlashOn then
    Canvas.Brush.Color := FPlanner.FlashColor;

  case APlannerItem.Shape of
    psRect:
      begin
        if BackgroundTo <> clNone then
          DrawGradient(Canvas, Canvas.Brush.Color, BackgroundTo, 64, ARect, APlannerItem.ColorDirection <> gdVertical)
        else
          Canvas.FillRect(ARect);

        Canvas.Pen.Color := APlannerItem.BorderColor;
        Canvas.Brush.Style := bsClear;
        Canvas.Polygon([Point(ARect.Left, ARect.Top), Point(ARect.Right - 1, ARect.Top), Point(ARect.Right - 1, ARect.Bottom - 1),
          Point(ARect.Left, ARect.Bottom - 1)]);
      end;
    psRounded:
      begin
        //ARect.Right := ARect.Right - 1;
        //ARect.Bottom := ARect.Bottom - 1;
        ARect.Top := ARect.Top + 1;

        OldColor := Canvas.Brush.Color;
        FPlanner.GetCellBrush(APlannerItem.ItemPos, APlannerItem.ItemBegin, Canvas.Brush);

        if FPlanner.IsSelected(APlannerItem.ItemBegin, APlannerItem.ItemPos) then
          Canvas.Brush.Color := FPlanner.SelectColor;

        Canvas.Pen.Color := Canvas.Brush.Color;
        Canvas.Rectangle(ARect.Left, ARect.Top , ARect.Left + 6, ARect.Top + 6);
        Canvas.Rectangle(ARect.Right - 6, ARect.Top , ARect.Right, ARect.Top + 6);

        FPlanner.GetCellBrush(APlannerItem.ItemPos, APlannerItem.ItemEnd, Canvas.Brush);
        if FPlanner.IsSelected(APlannerItem.ItemEnd - 1, APlannerItem.ItemPos) then
          Canvas.Brush.Color := FPlanner.SelectColor;
        Canvas.Pen.Color := Canvas.Brush.Color;
        Canvas.Rectangle(ARect.Left, ARect.Bottom - 6 , ARect.Left + 6, ARect.Bottom);
        Canvas.Rectangle(ARect.Right - 6, ARect.Bottom - 6, ARect.Right, ARect.Bottom);

        Canvas.Brush.Color := OldColor;

        if APlannerItem.Shadow then
        begin
          ARect.Right := ARect.Right - 1;
          ARect.Bottom := ARect.Bottom - 1;

          Canvas.Pen.Color := FPlanner.ShadowColor;
          Canvas.Pen.Width := 2;
          OldColor := Canvas.Brush.Color;
          Canvas.Brush.Color := FPlanner.ShadowColor;
          Canvas.RoundRect(ARect.Left + 2, ARect.Top + 2, ARect.Right + 2,
            ARect.Bottom + 2, CORNER_EFFECT, CORNER_EFFECT);
          Canvas.Brush.Color := OldColor;
        end;

        if APlannerItem.TrackVisible and APlannerItem.FFocus then
        begin
          ARect.Left := ARect.Left + 1;
          Canvas.Pen.Color := APlannerItem.TrackSelectColor;
          Canvas.Pen.Width := 2;
        end
        else
        begin
          Canvas.Pen.Color := APlannerItem.BorderColor;
          Canvas.Pen.Width := 1;
        end;

        if APlannerItem.BrushStyle <> bsSolid then
        begin
          SetBkMode(Canvas.Handle, Transparent);
          SetBkColor(Canvas.Handle, ColorToRGB(CellColor));
          InflateRect(ARect, -(CORNER_EFFECT shr 2), -(CORNER_EFFECT shr 2));
          Canvas.FillRect(ARect);
          InflateRect(ARect, +(CORNER_EFFECT shr 2), +(CORNER_EFFECT shr 2));
        end;

        Canvas.RoundRect(ARect.Left, ARect.Top, ARect.Right, ARect.Bottom,
          CORNER_EFFECT, CORNER_EFFECT);
        InflateRect(ARect, -(CORNER_EFFECT shr 2), -(CORNER_EFFECT shr 2));

      end;
{$IFDEF TMSSKINS}
    psSkin:
      begin
        if APlannerItem.Selected then
        begin
          BitmapStretch(FPlanner.Skin.SkinSelectTop, Canvas, ARect.Left,
            ARect.Top, ARect.Right - ARect.Left);

          BitmapStretch(FPlanner.Skin.SkinSelectBottom, Canvas, ARect.Left,
            ARect.Bottom - FPlanner.Skin.SkinBottom.Height,
            ARect.Right - ARect.Left);

          BitmapStretchHeight(FPlanner.Skin.SkinSelectCenter, Canvas,
            ARect.Left, ARect.Top + FPlanner.Skin.SkinTop.Height - 1,
            ARect.Bottom - ARect.Top - FPlanner.Skin.SkinBottom.Height -
              FPlanner.Skin.SkinTop.Height + 1, ARect.Right - ARect.Left);
        end
        else
        begin
          BitmapStretch(FPlanner.Skin.SkinTop, Canvas, ARect.Left, ARect.Top,
            ARect.Right - ARect.Left);

          BitmapStretch(FPlanner.Skin.SkinBottom, Canvas, ARect.Left,
            ARect.Bottom - FPlanner.Skin.SkinBottom.Height,
            ARect.Right - ARect.Left);

          BitmapStretchHeight(FPlanner.Skin.SkinCenter, Canvas, ARect.Left,
            ARect.Top + FPlanner.Skin.SkinTop.Height - 1,
            ARect.Bottom - ARect.Top - FPlanner.Skin.SkinBottom.Height -
              FPlanner.Skin.SkinTop.Height + 1, ARect.Right - ARect.Left);
        end;

      end;
{$ENDIF}
    psHexagon:
      begin
        InflateRect(ARect, -1, -1);

        if APlannerItem.Shadow then
        begin
          InflateRect(ARect, -2, -2);
          Canvas.Pen.Color := FPlanner.ShadowColor;
          Canvas.Pen.Width := 2;
          OldColor := Canvas.Brush.Color;
          Canvas.Brush.Color := FPlanner.ShadowColor;

          Canvas.Polygon([Point(2 + ARect.Left + CORNER_EFFECT, 2 + ARect.Top),
            Point(2 + ARect.Right - 1 - CORNER_EFFECT, 2 + ARect.Top),
            Point(2 + ARect.Right - 1,
              2 + ARect.Top + ((ARect.Bottom - ARect.Top) shr 1)),
            Point(2 + ARect.Right - 1 - CORNER_EFFECT, 2 + ARect.Bottom - 2),
            Point(2 + ARect.Left + CORNER_EFFECT, 2 + ARect.Bottom - 2),
            Point(2 + ARect.Left,
              2 + ARect.Top + ((ARect.Bottom - ARect.Top) shr 1))]);

          Canvas.Brush.Color := OldColor;
        end;

        if APlannerItem.TrackVisible and APlannerItem.FFocus then
        begin
          Canvas.Pen.Color := APlannerItem.TrackSelectColor;
          Canvas.Pen.Width := 2;
        end
        else
        begin
          Canvas.Pen.Color := APlannerItem.BorderColor;
          Canvas.Pen.Width := 1;
        end;

        Canvas.Polygon([Point(ARect.Left + CORNER_EFFECT, ARect.Top),
          Point(ARect.Right - 1 - CORNER_EFFECT, ARect.Top),
          Point(ARect.Right - 1,
            ARect.Top + ((ARect.Bottom - ARect.Top) shr 1)),
          Point(ARect.Right - 1 - CORNER_EFFECT, ARect.Bottom - 2),
          Point(ARect.Left + CORNER_EFFECT, ARect.Bottom - 2),
          Point(ARect.Left, ARect.Top + ((ARect.Bottom - ARect.Top) shr 1))]
          );
        InflateRect(ARect, -CORNER_EFFECT, 0);
      end;
  end;

  Canvas.Brush.Style := bsSolid;

  if APlannerItem.FFocus and not Print and APlannerItem.FTrackVisible and
    (APlannerItem.Shape = psRect) and not APlannerItem.InHeader then
  begin
    Canvas.Brush.Color := APlannerItem.TrackSelectColor;
    R := ARect;
    R.Bottom := R.Top + 3;
    Canvas.FillRect(R);
    R := ARect;
    R.Top := ARect.Bottom - 4;
    R.Bottom := ARect.Bottom;
    Canvas.FillRect(R);
  end;

BackGroundOnly :

  if APlannerItem.FIsCurrent and not Print then
    Canvas.Brush.Color := FPlanner.FDisplay.FColorCurrentItem
  else
    Canvas.Brush.Color := APlannerItem.Color;

  InflateRect(ARect, -2, -EDITOFFSET);

{$IFDEF TMSSKINS}
  if APlannerItem.Shape = psSkin then
    InflateRect(ARect, -FPlanner.Skin.SkinX, -FPlanner.Skin.SkinY);
{$ENDIF}

  if APlannerItem.Background then
  begin
    if APlannerItem.Transparent and SelColor then
    begin
      Canvas.Brush.Color := BlendColor(CellColor, APlannerItem.Color, FPlanner.SelectBlend);
    end;

    if not (Print and APlannerItem.Transparent) then
    begin
      if BackgroundTo <> clNone then
        DrawGradient(Canvas,Background, BackgroundTo, 128, R, APlannerItem.ColorDirection <> gdVertical)
      else
        Canvas.FillRect(R);

      Canvas.Pen.Color := APlannerItem.FPlanner.GridLineColor;
      Canvas.MoveTo(R.Left, R.Bottom);
      Canvas.LineTo(R.Right - 1, R.Bottom);
    end;
  end;

  ch := 0;
  ih := 0;
  iw := 0;
  ColumnHeight := 0;
  MultiImage := False;

  if (APlannerItem.FBeginOffset <> 0) or (APlannerItem.FEndOffset <> 0) then
    ARect.Right := ARect.Right - 8;

  PlannerImagePoint := Point(0, 0);

  if Assigned(APlannerItem.FPlanner.PlannerImages) and
    ((APlannerItem.ImageID >= 0) or (APlannerItem.ImageIndexList.Count > 0))
    then
  begin
    PlannerImagePoint.X := Round((APlannerItem.FPlanner.PlannerImages.Width + 2) * GetDeviceCaps(Canvas.Handle, LOGPIXELSX) / 96);
    PlannerImagePoint.Y := Round((APlannerItem.FPlanner.PlannerImages.Height) * GetDeviceCaps(Canvas.Handle, LOGPIXELSY) / 96);
    ih := PlannerImagePoint.Y;
  end;

  if APlannerItem.CaptionType in [ctTime, ctText, ctTimeText] then
  begin
    Canvas.Font.Assign(APlannerItem.CaptionFont);

    if APlannerItem.Selected and APlannerItem.ShowSelection then
      Canvas.Font.Color := APlannerItem.SelectFontColor;

    ColumnHeight := Canvas.TextHeight('gh');

    if APlannerItem.Flashing and APlannerItem.FlashOn and APlannerItem.UniformBkg then
      Canvas.Font.Color := FPlanner.FlashFontColor;

    ih := Max(ih, ColumnHeight);

    ch := ih;
{$IFDEF TMSSKINS}
    if APlannerItem.Shape <> psSkin then
    begin
{$ENDIF}
      // Draw line under Caption
      if (ARect.Top + ih + 1 < ARect.Bottom) and APlannerItem.CaptionDivider then
      begin
        if (APlannerItem.ImagePosition = ipVertical) and Assigned
          (APlannerItem.FPlanner.PlannerImages) and
          (APlannerItem.ImageIndexList.Count > 0) then
          Canvas.MoveTo(ARect.Left + APlannerItem.FPlanner.PlannerImages.Width, ARect.Top + ih + 1)
        else
          Canvas.MoveTo(ARect.Left, ARect.Top + ih + 1);

        Canvas.LineTo(ARect.Right, ARect.Top + ih + 1);
      end;
{$IFDEF TMSSKINS}
    end;
{$ENDIF}

    if APlannerItem.Focus and not APlannerItem.Background then
      ih := Min(ARect.Bottom - ARect.Top -  2, ih)
    else
      ih := Min(ARect.Bottom - ARect.Top, ih);

    if not APlannerItem.UniformBkg then
    begin
      if APlannerItem.Selected and (APlannerItem.SelectCaptionBkg <> clNone) then
      begin
        Canvas.Brush.Color := APlannerItem.SelectCaptionBkg;
        Canvas.Pen.Color := APlannerItem.SelectCaptionBkg;
      end
      else
      begin
        Canvas.Brush.Color := APlannerItem.CaptionBkg;
        Canvas.Pen.Color := APlannerItem.CaptionBkg;
      end;
    end
    else
    begin
      if APlannerItem.Flashing and APlannerItem.FlashOn then
        Canvas.Brush.Color := FPlanner.FlashColor
      else
        Canvas.Brush.Color := Background;
    end;

    R := ARect;

    R.Left := ARect.Left + iw;
    R.Bottom := R.Top + ih;
    InflateRect(R, 1, 1);

    //if not APlannerItem.Focus or APlannerItem.Background then
    //begin
    //  R.Top := R.Top - 2;
    //end;

    if APlannerItem.Focus and not APlannerItem.Background then
    begin
      R.Top := R.Top + 2;
    end;
{$IFDEF TMSSKINS}
    if (APlannerItem.Shape <> psSkin) then
    begin
{$ENDIF}
      if APlannerItem.Selected and (APlannerItem.SelectCaptionBkg <> clNone) then
      begin
        DrawGradient(Canvas, APlannerItem.SelectCaptionBkg, APlannerItem.SelectCaptionBkgTo, FPlanner.GradientSteps, R,
            APlannerItem.CaptionBkgDirection <> gdVertical);
      end
      else
        DrawGradient(Canvas, APlannerItem.CaptionBkg, APlannerItem.CaptionBkgTo, FPlanner.GradientSteps, R,
            APlannerItem.CaptionBkgDirection <> gdVertical);
      end;
{$IFDEF TMSSKINS}
    end;
{$ENDIF}

  ih := 0;

  if Assigned(APlannerItem.FPlanner.PlannerImages) then
  begin
    if (APlannerItem.ImageID >= 0) then
    begin
      if ARect.Left + APlannerItem.FPlanner.PlannerImages.Width < ARect.Right then
      begin
        iw := PlannerImagePoint.X;
        ih := PlannerImagePoint.Y;
        if Print then
        begin
          Bitmap := TBitmap.Create;

          Bitmap.Width := APlannerItem.FPlanner.PlannerImages.Width;
          Bitmap.Height := APlannerItem.FPlanner.PlannerImages.Height;
          Bitmap.Canvas.Brush.Color := APlannerItem.Color;
          Bitmap.Canvas.Pen.Color := APlannerItem.Color;
          Bitmap.Canvas.FillRect(Rect(0,0,Bitmap.Width, Bitmap.Height));
          APlannerItem.FPlanner.PlannerImages.Draw(Bitmap.Canvas,0,0,APlannerItem.ImageID);

          PrintBitmap(Canvas, Rect(ARect.Left, ARect.Top, ARect.Left + iw, ARect.Top + ih), Bitmap);

          Bitmap.Free;
        end
        else
          APlannerItem.FPlanner.PlannerImages.Draw(Canvas,
            ARect.Left + APlannerItem.FPlanner.ImageOffsetX,
            ARect.Top + APlannerItem.FPlanner.ImageOffsetY,
            APlannerItem.ImageID);
      end;
    end;

    for ImageIndex := 0 to APlannerItem.FImageIndexList.Count - 1 do
    begin
      if APlannerItem.ImagePosition = ipHorizontal then
      begin
        if ARect.Left + iw + APlannerItem.FPlanner.PlannerImages.Width < ARect.Right then
        begin
          if Print then
          begin
            Bitmap := TBitmap.Create;
            Bitmap.Width := APlannerItem.FPlanner.PlannerImages.Width;
            Bitmap.Height := APlannerItem.FPlanner.PlannerImages.Height;
            Bitmap.Canvas.Brush.Color := APlannerItem.Color;
            Bitmap.Canvas.Pen.Color := APlannerItem.Color;
            Bitmap.Canvas.FillRect(Rect(0,0,Bitmap.Width, Bitmap.Height));
            APlannerItem.FPlanner.PlannerImages.Draw(Bitmap.Canvas,0,0,APlannerItem.FImageIndexList.Items[ImageIndex]);

            PrintBitmap(Canvas, Rect(ARect.Left + iw, ARect.Top, ARect.Left + iw + PlannerImagePoint.X,
              ARect.Top + PlannerImagePoint.Y), Bitmap);

            Bitmap.Free;
          end
          else
            APlannerItem.FPlanner.PlannerImages.Draw(Canvas, ARect.Left + iw,
              ARect.Top, APlannerItem.FImageIndexList.Items[ImageIndex]);

          iw := iw + PlannerImagePoint.X;
          ih := PlannerImagePoint.Y;
        end;
      end
      else
      begin
        if ARect.Top + ih + APlannerItem.FPlanner.PlannerImages.Height < ARect.Bottom + 4 then
        begin
          if Print then
          begin
            Bitmap := TBitmap.Create;
            Bitmap.Width := APlannerItem.FPlanner.PlannerImages.Width;
            Bitmap.Height := APlannerItem.FPlanner.PlannerImages.Height;
            Bitmap.Canvas.Brush.Color := APlannerItem.Color;
            Bitmap.Canvas.Pen.Color := APlannerItem.Color;
            Bitmap.Canvas.FillRect(Rect(0,0,Bitmap.Width, Bitmap.Height));
            APlannerItem.FPlanner.PlannerImages.Draw(Bitmap.Canvas,0,0,APlannerItem.FImageIndexList.Items[ImageIndex]);

            PrintBitmap(Canvas, Rect(ARect.Left, ARect.Top + ih,
                ARect.Left + PlannerImagePoint.X,
                ARect.Top + PlannerImagePoint.Y + ih), Bitmap);
            Bitmap.Free;
          end
          else
            APlannerItem.FPlanner.PlannerImages.Draw(Canvas, ARect.Left,
              ARect.Top + ih, APlannerItem.FImageIndexList.Items[ImageIndex]);

          ih := ih + PlannerImagePoint.Y;
          iw := PlannerImagePoint.X;
        end;
      end;
      MultiImage := True;
    end;

    if (APlannerItem.ImagePosition = ipHorizontal) and
      (APlannerItem.FImageIndexList.Count > 0) and
      (APlannerItem.CaptionType = ctNone) then
      ARect.Top := ARect.Top + ih;
  end;

  //if APlannerItem.ImagePosition = ipVertical then
  ih := Max(ch, ColumnHeight);

  if APlannerItem.CaptionType in [ctTime, ctText, ctTimeText] then
  begin
    R := ARect;
    R.Bottom := R.Top + ih;
    R.Left := ARect.Left + iw;
{$IFDEF TMSSKINS}
    if APlannerItem.Shape = psSkin then
    begin
      R.Top := R.Top + FPlanner.Skin.SkinCaptionY;
      R.Left := R.Left + FPlanner.Skin.SkinCaptionX;
    end;
{$ENDIF}

    //ih := ih + 2;

    if (APlannerItem.URL <> '') and (R.Right - R.Left > 32) then
      R.Right := R.Right - APlannerItem.FPlanner.URLGlyph.Width;

    if (APlannerItem.Attachement <> '') and (R.Right - R.Left > 32) then
      R.Right := R.Right - APlannerItem.FPlanner.AttachementGlyph.Width;

    if (APlannerItem.ShowDeleteButton) and (R.Right - R.Left > 32) then
      R.Right := R.Right - APlannerItem.FPlanner.DeleteGlyph.Width;

    if (APlannerItem.URL <> '') or (APlannerItem.Attachement <> '') or
      (APlannerItem.ShowDeleteButton) then
      R.Right := R.Right - 2;

    CaptionPaintString := APlannerItem.GetCaptionString;

    HorizontalAlign := AlignToFlag(APlannerItem.CaptionAlign);
    SetBkMode(Canvas.Handle, Transparent);
    if APlannerItem.Unicode then
    begin
      WideCaptionPaintString := APlannerItem.GetWideCaptionString;
      DrawFlags := DT_NOPREFIX or DT_END_ELLIPSIS or HorizontalAlign;
      DrawTextExW(Canvas.Handle, PWideChar(WideCaptionPaintString),
        Length(WideCaptionPaintString), R, DrawFlags, nil);
    end
    else
    begin
      if IsHtml(APlannerItem, CaptionPaintString, True) then
        HTMLDrawEx(Canvas, CaptionPaintString, R, FPlanner.PlannerImages, 0, 0,
          -1, -1, 1, False, False, Print, False, True, False, False
          , False
          , FPlanner.FHTMLFactor, FPlanner.URLColor, clNone, clNone, clGray,
          Anchor, StrippedHTMLString, FocusAnchor, XSize, YSize, ml, hl, hr
          , CR, CID, CV, CT, FPlanner.FImageCache, FPlanner.FContainer, Handle
        )
      else
      begin
        DrawFlags := DT_NOPREFIX or DT_END_ELLIPSIS or HorizontalAlign;

        //DrawFlags := FPlanner.DrawTextBiDiModeFlags(DrawFlags);

        if (BiDiMode = bdRightToLeft) then
          SwapLR(R);
        DrawText(Canvas.Handle, PChar(CaptionPaintString),
          Length(CaptionPaintString), R, DrawFlags);
      end;

    end;

    R.Right := ARect.Right;
    R.Top := R.Top - 2;

    if (APlannerItem.ShowDeleteButton) and (R.Right - R.Left > 32) then
    begin
      APlannerItem.FPlanner.DeleteGlyph.TransparentColor := APlannerItem.FPlanner.DeleteGlyph.Canvas.Pixels[0, 0];
      APlannerItem.FPlanner.DeleteGlyph.Transparent := True;

      if Print then
      begin
        pw := Round(16 * GetDeviceCaps(Canvas.Handle, LOGPIXELSX) / 96);
        ph := Round(16 * GetDeviceCaps(Canvas.Handle, LOGPIXELSY) / 96);
        PrintBitmap(Canvas, Rect(R.Right - pw, R.Top, R.Right, R.Top + ph), APlannerItem.FPlanner.DeleteGlyph);
        R.Right := R.Right - pw;
      end
      else
      begin
        Canvas.Draw(R.Right - APlannerItem.FPlanner.DeleteGlyph.Width, R.Top, APlannerItem.FPlanner.DeleteGlyph);
        R.Right := R.Right - APlannerItem.FPlanner.DeleteGlyph.Width;
      end;
    end;

    if (APlannerItem.Attachement <> '') and (R.Right - R.Left > 32) then
    begin
      APlannerItem.FPlanner.AttachementGlyph.TransparentColor := APlannerItem.FPlanner.AttachementGlyph.Canvas.Pixels[0, 0];
      APlannerItem.FPlanner.AttachementGlyph.Transparent := True;

      if Print then
      begin
        pw := Round(16 * GetDeviceCaps(Canvas.Handle, LOGPIXELSX) / 96);
        ph := Round(16 * GetDeviceCaps(Canvas.Handle, LOGPIXELSY) / 96);
        PrintBitmap(Canvas, Rect(R.Right - pw, R.Top, R.Right, R.Top + ph), APlannerItem.FPlanner.AttachementGlyph);
        R.Right := R.Right - pw;
      end
      else
      begin
        Canvas.Draw(R.Right - APlannerItem.FPlanner.AttachementGlyph.Width, R.Top, APlannerItem.FPlanner.AttachementGlyph);
        R.Right := R.Right - APlannerItem.FPlanner.AttachementGlyph.Width;
      end;
    end;

    if (APlannerItem.URL <> '') and (R.Right - R.Left > 32) then
    begin
      APlannerItem.FPlanner.URLGlyph.TransparentColor := APlannerItem.FPlanner.URLGlyph.Canvas.Pixels[0, 0];
      APlannerItem.FPlanner.URLGlyph.Transparent := True;

      if Print then
      begin
        pw := Round(16 * GetDeviceCaps(Canvas.Handle, LOGPIXELSX) / 96);
        ph := Round(16 * GetDeviceCaps(Canvas.Handle, LOGPIXELSY) / 96);
        PrintBitmap(Canvas, Rect(R.Right - pw, R.Top, R.Right, R.Top + ph), APlannerItem.FPlanner.URLGlyph);
      end
      else
      begin
        Canvas.Draw(R.Right - APlannerItem.FPlanner.URLGlyph.Width, R.Top, APlannerItem.FPlanner.URLGlyph);
      end;
    end;

    iw := 0;
  end;

  if MultiImage then
  begin
    iw := 0;
    {
    if (APlannerItem.ImagePosition = ipHorizontal) then
      ih := PlannerImagePoint.Y
    else
      ih := 0;
    }
  end;

  APlannerItem.FCaptionHeight := ch;

  if (APlannerItem.ImagePosition = ipVertical) and Assigned
    (APlannerItem.FPlanner.PlannerImages) and
    (APlannerItem.ImageIndexList.Count > 0) then
    ARect.Left := ARect.Left + APlannerItem.FPlanner.PlannerImages.Width + EDITOFFSET;

  ARect.Top := ARect.Top + ch + 2 + FPlanner.PaintMarginTY {+ ih};
  ARect.Left := ARect.Left + iw + FPlanner.PaintMarginLX;

  ARect.Bottom := ARect.Bottom - FPlanner.PaintMarginBY;
  ARect.Right := ARect.Right - FPlanner.PaintMarginRX;

  if APlannerItem.CompletionDisplay = cdVertical then
  begin
    gs.Level0Color := FPlanner.CompletionColor1;
    gs.Level0ColorTo := clWhite;
    gs.Level1Perc := 101;
    gs.BackgroundColor := FPlanner.CompletionColor2;
    gs.Font := Canvas.Font;
    gs.Steps := 8;
    gs.Stacked := False;
    gs.ShowPercentage := False;
    gs.BorderColor := clGray;
    gs.ShowBorder := True;
    gs.Orientation := goVertical;
    gs.CompletionFormat := '%d%%';
    FPlanner.DoItemGaugeSettings(APlannerItem,gs);
    DrawGauge(Canvas, Rect(ARect.Left, ARect.Top, ARect.Left + 10,
      ARect.Bottom), APlannerItem.Completion, gs);

    ARect.Left := ARect.Left + 11;
  end;

  if APlannerItem.CompletionDisplay = cdHorizontal then
  begin
    gs.Level0Color := FPlanner.CompletionColor1;
    gs.Level0ColorTo := clWhite;
    gs.Level1Perc := 101;
    gs.Level2Color := FPlanner.CompletionColor1;
    gs.Level2ColorTo := clNone;
    gs.Level3Color := FPlanner.CompletionColor1;
    gs.Level3ColorTo := clNone;
    gs.BackgroundColor := FPlanner.CompletionColor2;
    gs.Font := Canvas.Font;
    gs.Steps := 8;
    gs.Stacked := False;
    gs.ShowPercentage := False;
    gs.BorderColor := clGray;
    gs.ShowBorder := True;
    gs.Orientation := goHorizontal;
    gs.ShowGradient := True;
    gs.CompletionFormat := '%d%%';
    FPlanner.DoItemGaugeSettings(APlannerItem,gs);
    DrawGauge(Canvas, Rect(ARect.Left, ARect.Top, ARect.Right, ARect.Top + 10),
      APlannerItem.Completion, gs);

    ARect.Top := ARect.Top + 11;
  end;


  PaintString := APlannerItem.ItemText;

  if Assigned(FPlanner.OnItemText) then
    FPlanner.OnItemText(FPlanner, APlannerItem, PaintString);

  Canvas.Font.Assign(APlannerItem.Font);

  if APlannerItem.Selected and APlannerItem.ShowSelection then
    Canvas.Font.Color := APlannerItem.SelectFontColor;

  if APlannerItem.Flashing and APlannerItem.FlashOn then
    Canvas.Font.Color := FPlanner.FlashFontColor;

  HorizontalAlign := AlignToFlag(APlannerItem.Alignment);
  if IsRtf(PaintString) then
    RTFPaint(Canvas, ARect, PaintString, Background)
  else
  if APlannerItem.Unicode then
  begin
    SetBkMode(Canvas.Handle, Transparent);
    DrawFlags := DT_NOPREFIX or DT_EDITCONTROL or HorizontalAlign;
    if APlannerItem.FWordWrap then
      DrawFlags := DrawFlags or DT_WORDBREAK
    else
      DrawFlags := DrawFlags or DT_SINGLELINE or DT_END_ELLIPSIS;

    YSize := DrawTextExW(Canvas.Handle, PWideChar(APlannerItem.WideText),
      Length(APlannerItem.WideText), ARect, DrawFlags, nil);

    APlannerItem.FClipped := YSize > (ARect.Bottom - ARect.Top);
  end
  else
  begin
    if IsHtml(APlannerItem, PaintString, False) then
    begin
      PaintString := StripLineBreaks(PaintString);

      HRGN := 0;

      GetCursorPos(pt);
      pt := ScreenToClient(pt);
      if not APlannerItem.Preview then
      begin
        HRGN := CreateRectRgn(ARect.Left, ARect.Top, ARect.Right, ARect.Bottom);
        SelectClipRgn(Canvas.Handle, HRGN);
      end;
      HTMLDrawEx(Canvas, PaintString, ARect, FPlanner.PlannerImages, pt.X,
        pt.Y, -1, -1, 1, False, False, Print, False, True, False,
        APlannerItem.FWordWrap
        , FMouseDown
        , FPlanner.FHTMLFactor, FPlanner.URLColor, clNone, clNone, clGray,
        Anchor, StrippedHTMLString, FocusAnchor, XSize, YSize, ml, hl, hr
        , CR, CID, CV, CT, FPlanner.FImageCache, FPlanner.FContainer, Handle
      );
      if not APlannerItem.Preview then
      begin
        SelectClipRgn(Canvas.Handle, 0);
        DeleteObject(HRGN);
      end;
      APlannerItem.FClipped := YSize > (ARect.Bottom - ARect.Top);
    end
    else
    begin
      SetBkMode(Canvas.Handle, Transparent);

      DrawFlags := DT_NOPREFIX or DT_EDITCONTROL or HorizontalAlign;

      if APlannerItem.FWordWrap then
        DrawFlags := DrawFlags or DT_WORDBREAK
      else
        DrawFlags := DrawFlags or DT_SINGLELINE or DT_END_ELLIPSIS;

      //      DrawFlags := FPlanner.DrawTextBiDiModeFlags(DrawFlags);

      if (BiDiMode = bdRightToLeft) then
        SwapLR(ARect);
      YSize := DrawTextEx(Canvas.Handle, PChar(PaintString),
        Length(PaintString), ARect, DrawFlags, nil);
      APlannerItem.FClipped := YSize > (ARect.Bottom - ARect.Top);
    end;

  end;

  if (APlannerItem.FBeginOffset <> 0) and not APlannerItem.InHeader then
  begin
    DrawArrow(Canvas, clBlue, ro.Right - 4 - FPlanner.TrackWidth,
      ro.Top + FPlanner.TrackWidth, adUp);
  end;

  if (APlannerItem.FEndOffset <> 0) and not APlannerItem.InHeader then
  begin
    DrawArrow(Canvas, clBlue, ro.Right - 4 - FPlanner.TrackWidth,
      ro.Bottom - 8 - FPlanner.TrackWidth, adDown);
  end;

  if APlannerItem.HintIndicator and (APlannerItem.Hint <> '') then
  begin
    Canvas.Pen.Color := APlannerItem.HintIndicatorColor;
    Canvas.Brush.Color := Canvas.Pen.Color;
    Canvas.Polygon([Point(ro.Right-5,ro.Top),Point(ro.Right,ro.Top),Point(ro.Right,ro.Top + 5)]);
    Canvas.Brush.Color := APlannerItem.Color;
  end;

  FPlanner.DoItemAfterPaint(APlannerItem, Canvas, ARect);
end;

procedure TPlannerGrid.PaintItemRow(Canvas: TCanvas; ARect: TRect;
  APlannerItem: TPlannerItem; Print, SelColor: Boolean);
var
  PaintString, Anchor, StrippedHTMLString, CaptionPaintString, FocusAnchor: string;
  R, ro, hr, CR, sr: TRect;
  ColumnHeight, iw, ih, ImageIndex, ml, hl, i: Integer;
  MultiImage: Boolean;
  HorizontalAlign, DrawFlags: dword;
  rr, dr, XSize, YSize: Integer;
  PlannerImagePoint: TPoint;
  Bitmap: TBitmap;
  Background: TColor;
  BackgroundTo: TColor;
  pt: TPoint;
  tmpBegin, tmpEnd: Integer;
  CellColor, OldColor: TColor;
  CID, CV, CT: string;
  HRGN: THandle;
  ch, pw, ph: Integer;
  rcorner, lcorner: Integer;

label BackGroundOnly;
begin
  if APlannerItem.Repainted then
    Exit;

  if (APlannerItem.ItemBegin = APlannerItem.ItemEnd)
    and not APlannerItem.InHeader then
    Exit;

  if not(csDesigning in FPlanner.ComponentState) and not Print then
    APlannerItem.Repainted := True;

  if not APlannerItem.Background then
    ARect.Bottom := ARect.Bottom - FPlanner.FItemGap;

  ARect.Bottom := ARect.Bottom - APlannerItem.VMargin;
  ARect.Top := ARect.Top + APlannerItem.VMargin;

  if Assigned(APlannerItem.FPlanner.OnPlannerItemDraw) then
  begin
    try
      APlannerItem.FPlanner.OnPlannerItemDraw(APlannerItem.FPlanner,
        APlannerItem, Canvas, ARect, False);
      Exit;
    except
      on e: EAbort do
        {nothing};
    end;
  end;

  if (APlannerItem.Shape = psTool) and Assigned(APlannerItem.DrawTool) then
  begin
    APlannerItem.DrawTool.DrawItem(APlannerItem, Canvas, ARect, APlannerItem.Selected, Print);
    Exit;
  end;

  if APlannerItem.ConflictPos = 0 then
    ARect.Top := ARect.Top + 1;

  CellColor := Canvas.Brush.Color;

  if APlannerItem.Shadow and not APlannerItem.Background and
    (APlannerItem.Shape = psRect) and not FPlanner.TrackOnly then
  begin
    Canvas.Brush.Color := FPlanner.ShadowColor;
    Canvas.Pen.Color := Canvas.Brush.Color;
    Canvas.Rectangle(ARect.Right - 3, ARect.Top + 3, ARect.Right, ARect.Bottom - 1);
    Canvas.Rectangle(ARect.Left + 3, ARect.Bottom - 4, ARect.Right, ARect.Bottom - 1);
    Canvas.Brush.Color := CellColor;
    Canvas.Pen.Color := CellColor;
    Canvas.Rectangle(ARect.Right - 3, ARect.Top, ARect.Right, ARect.Top + 3);
    Canvas.Rectangle(ARect.Left, ARect.Bottom - 4, ARect.Left + 3, ARect.Bottom - 1);

    ARect.Right := ARect.Right - 3;
    ARect.Bottom := ARect.Bottom - 3;
  end;

  Canvas.Font.Assign(APlannerItem.Font);

  ro := ARect;
  R := ARect;
  Background := APlannerItem.Color;
  BackgroundTo := APlannerItem.ColorTo;

  if APlannerItem.Selected and APlannerItem.ShowSelection and not APlannerItem.InHeader then
  begin
    Background := APlannerItem.SelectColor;
    BackgroundTo := APlannerItem.SelectColorTo;
  end;

  APlannerItem.FClipped := False;

  if APlannerItem.Background then
  begin
    if APlannerItem.BrushStyle <> bsSolid then
    begin
      Canvas.Brush.Color := Background;
      Canvas.Brush.Style := APlannerItem.BrushStyle;
      SetBkMode(Canvas.Handle, Transparent);
      SetBkColor(Canvas.Handle, ColorToRGB(FPlanner.Color));
    end;
    goto BackGroundOnly;
  end;

  // Draw the item trackbar
  R.Bottom := R.Top + TrackBarHeight(APlannerItem.FPlanner.TrackWidth, Canvas);

  if not APlannerItem.InHeader and APlannerItem.TrackVisible and (APlannerItem.Shape = psRect) then
  begin
    if FPlanner.TrackProportional then
    begin
      Canvas.Brush.Color := FPlanner.Display.ColorActive;
      Canvas.FillRect(R);
      dr := APlannerItem.FItemBeginPrecis - (APlannerItem.FItemBegin + FPlanner.Display.DisplayStart) * FPlanner.Display.DisplayUnit - FPlanner.Display.DisplayOffset;
      dr := Round(dr / FPlanner.Display.DisplayUnit * FPlanner.Display.DisplayScale);
      rr := Round((APlannerItem.FItemEndPrecis - APlannerItem.FItemBeginPrecis + FPlanner.Display.DisplayOffset) / FPlanner.Display.DisplayUnit * FPlanner.Display.DisplayScale);
      rr := dr + rr;
      //      rr := Round((APlannerItem.FItemEndPrecis - APlannerItem.FItemBeginPrecis) /
      //        FPlanner.Display.DisplayUnit * FPlanner.Display.DisplayScale) + FPlanner.Display.DisplayOffset;
    end
    else
    begin
      dr := 0;
      rr := R.Right - R.Left;
    end;

    R.Right := R.Left + rr;
    R.Left := R.Left + dr;

    if APlannerItem.Selected then
      Canvas.Brush.Color := APlannerItem.TrackSelectColor
    else
      Canvas.Brush.Color := APlannerItem.TrackColor;

    if APlannerItem.LinkSelect then
      Canvas.Brush.Color := APlannerItem.TrackLinkColor;

    if (APlannerItem.TrackBrushStyle <> bsSolid) then
    begin
      Canvas.Brush.Style := APlannerItem.TrackBrushStyle;
      Canvas.Brush.Color := clWhite;
      SetBkColor(Canvas.Handle, ColorToRGB(APlannerItem.TrackColor));
    end;

    Canvas.FillRect(R);

    if FPlanner.TrackBump then
      DrawBumpHorz(Canvas, R, APlannerItem.TrackColor);

    ARect.Top := ARect.Top + TrackBarHeight(APlannerItem.FPlanner.TrackWidth, Canvas);

    for i := 0 to APlannerItem.BarItems.Count - 1 do
    begin
      with APlannerItem.BarItems[i] do
      begin
        tmpBegin := BarBegin;
        tmpEnd := BarEnd;
        if BarBegin = -1 then
          tmpBegin := 0;
        if BarEnd = -1 then
          tmpEnd := APlannerItem.ItemEnd - APlannerItem.ItemBegin;

        rr := (R.Right - R.Left) div
          (APlannerItem.ItemEnd - APlannerItem.ItemBegin);
        sr.Left := R.Left + (tmpBegin * rr);
        sr.Right := R.Left + (tmpEnd * rr);
        sr.Top := R.Top + 2;
        sr.Bottom := R.Bottom - 1;
        Canvas.Brush.Color := BarColor;
        Canvas.Pen.Color := APlannerItem.TrackColor;
        Canvas.Brush.Style := BarStyle;
        Canvas.Rectangle(sr.Left, sr.Top, sr.Right, sr.Bottom);
      end;
    end;
  end;

  if FPlanner.TrackOnly then
    Exit;

  if APlannerItem.FIsCurrent and not Print then
  begin
    Background := FPlanner.FDisplay.FColorCurrentItem;
    Canvas.Brush.Color := Background;
  end
  else
  begin
    if APlannerItem.BrushStyle <> bsSolid then
    begin
      Background := APlannerItem.Color;
      Canvas.Brush.Color := Background;
      Canvas.Brush.Style := APlannerItem.BrushStyle;
      SetBkMode(Canvas.Handle, Transparent);
      SetBkColor(Canvas.Handle, ColorToRGB(FPlanner.Color));
    end
    else
      Canvas.Brush.Color := Background;
  end;

  if APlannerItem.Flashing and APlannerItem.FlashOn then
    Canvas.Brush.Color := FPlanner.FlashColor;

  case APlannerItem.Shape of
    psRect:
      begin
        hr := ARect;
        hr.Bottom := hr.Bottom - 1;

        if hr.Bottom > hr.Top then
        begin
          DrawGradient(Canvas, Canvas.Brush.Color, BackgroundTo, 64, hr, APlannerItem.ColorDirection <> gdVertical)
        end;

        Canvas.Brush.Style := bsClear;
        Canvas.Pen.Color := APlannerItem.BorderColor;
        Canvas.Polygon([Point(ARect.Left, ARect.Top), Point(ARect.Right - 1, ARect.Top),
          Point(ARect.Right - 1, ARect.Bottom - 2), Point(ARect.Left, ARect.Bottom - 2)]);
      end;
    psRounded:
      begin
        ARect.Bottom := ARect.Bottom - 1;
        ARect.Left := ARect.Left + 1;
        ARect.Right := ARect.Right - 1;

        if APlannerItem.Shadow then
        begin
          ARect.Bottom := ARect.Bottom - 1;
          ARect.Left := ARect.Left + 1;
          ARect.Right := ARect.Right - 1;

          Canvas.Pen.Color := FPlanner.ShadowColor;
          Canvas.Pen.Width := 2;
          OldColor := Canvas.Brush.Color;
          Canvas.Brush.Color := FPlanner.ShadowColor;
          Canvas.RoundRect(ARect.Left + 2, ARect.Top + 2, ARect.Right + 2, ARect.Bottom + 2, CORNER_EFFECT, CORNER_EFFECT);
          Canvas.Brush.Color := OldColor;
        end;

        if APlannerItem.TrackVisible and APlannerItem.FFocus then
        begin
          ARect.Top := ARect.Top + 1;
          Canvas.Pen.Color := APlannerItem.TrackColor;
          Canvas.Pen.Width := 2;
        end
        else
        begin
          Canvas.Pen.Color := APlannerItem.BorderColor;
          Canvas.Pen.Width := 1;
        end;

        if APlannerItem.BrushStyle <> bsSolid then
        begin
          SetBkMode(Canvas.Handle, Transparent);
          SetBkColor(Canvas.Handle, ColorToRGB(CellColor));
          InflateRect(ARect, -(CORNER_EFFECT shr 2), -(CORNER_EFFECT shr 2));
          Canvas.FillRect(ARect);
          InflateRect(ARect, +(CORNER_EFFECT shr 2), +(CORNER_EFFECT shr 2));
        end;

        Canvas.RoundRect(ARect.Left, ARect.Top, ARect.Right, ARect.Bottom, CORNER_EFFECT, CORNER_EFFECT);
        InflateRect(ARect, -(CORNER_EFFECT shr 2), -(CORNER_EFFECT shr 2));
      end;
    psHexagon:
      begin
        //InflateRect(ARect,-1,-1);

        lcorner := CORNER_EFFECT;
        rcorner := CORNER_EFFECT;

        if APlannerItem.BeginOffset <> 0 then
          lcorner := 0;
        if APlannerItem.EndOffset <> 0 then
          rcorner := 0;

        if APlannerItem.Shadow then
        begin
          //InflateRect(ARect,-2,-2);
          Canvas.Pen.Color := FPlanner.ShadowColor;
          Canvas.Pen.Width := 2;
          OldColor := Canvas.Brush.Color;
          Canvas.Brush.Color := FPlanner.ShadowColor;
          Canvas.Polygon([Point(2 + ARect.Left + lcorner, 2 + ARect.Top),
            Point(2 + ARect.Right - 1 - rcorner, 2 + ARect.Top),
            Point(2 + ARect.Right - 1,
              2 + ARect.Top + ((ARect.Bottom - ARect.Top) shr 1)),
            Point(2 + ARect.Right - 1 - rcorner, 2 + ARect.Bottom - 2),
            Point(2 + ARect.Left + lcorner, 2 + ARect.Bottom - 2),
            Point(2 + ARect.Left,
              2 + ARect.Top + ((ARect.Bottom - ARect.Top) shr 1))]);

          Canvas.Brush.Color := OldColor;
        end;

        if APlannerItem.TrackVisible and APlannerItem.FFocus then
        begin
          Canvas.Pen.Color := APlannerItem.TrackColor;
          Canvas.Pen.Width := 2;
        end
        else
        begin
          Canvas.Pen.Color := APlannerItem.BorderColor;
          Canvas.Pen.Width := 1;
        end;

        Canvas.Polygon([Point(ARect.Left + lcorner, ARect.Top),
          Point(ARect.Right - 1 - rcorner, ARect.Top), Point(ARect.Right - 1,
            ARect.Top + ((ARect.Bottom - ARect.Top) shr 1)),
          Point(ARect.Right - 1 - rcorner, ARect.Bottom - 2),
          Point(ARect.Left + lcorner, ARect.Bottom - 2),
          Point(ARect.Left, ARect.Top + ((ARect.Bottom - ARect.Top) shr 1))]);
        InflateRect(ARect, -CORNER_EFFECT, 0);
      end;
{$IFDEF TMSSKINS}
    psSkin:
      begin
        if APlannerItem.Selected then
        begin
          BitmapStretch(FPlanner.Skin.SkinSelectTop, Canvas, ARect.Left,
            ARect.Top, ARect.Right - ARect.Left);

          BitmapStretch(FPlanner.Skin.SkinSelectBottom, Canvas, ARect.Left,
            ARect.Bottom - FPlanner.Skin.SkinBottom.Height,
            ARect.Right - ARect.Left);

          BitmapStretchHeight(FPlanner.Skin.SkinSelectCenter, Canvas,
            ARect.Left, ARect.Top + FPlanner.Skin.SkinTop.Height - 1,
            ARect.Bottom - ARect.Top - FPlanner.Skin.SkinBottom.Height -
              FPlanner.Skin.SkinTop.Height + 1, ARect.Right - ARect.Left);
        end
        else
        begin
          BitmapStretch(FPlanner.Skin.SkinTop, Canvas, ARect.Left, ARect.Top,
            ARect.Right - ARect.Left);

          BitmapStretch(FPlanner.Skin.SkinBottom, Canvas, ARect.Left,
            ARect.Bottom - FPlanner.Skin.SkinBottom.Height,
            ARect.Right - ARect.Left);

          BitmapStretchHeight(FPlanner.Skin.SkinCenter, Canvas, ARect.Left,
            ARect.Top + FPlanner.Skin.SkinTop.Height - 1,
            ARect.Bottom - ARect.Top - FPlanner.Skin.SkinBottom.Height -
              FPlanner.Skin.SkinTop.Height + 1, ARect.Right - ARect.Left);
        end;

      end;
{$ENDIF}
  end;

  Canvas.Brush.Style := bsSolid;

  if APlannerItem.FFocus and not Print and APlannerItem.FTrackVisible and
    (APlannerItem.Shape = psRect) and not APlannerItem.InHeader then
  begin
    if APlannerItem.Selected then
      Canvas.Brush.Color := APlannerItem.TrackSelectColor
    else
      Canvas.Brush.Color := APlannerItem.TrackColor;

    R := ARect;
    R.Right := R.Left + 3;
    Canvas.FillRect(R);

    R := ARect;
    R.Left := ARect.Right - 3;
    Canvas.FillRect(R);
  end;

BackGroundOnly :

  //ARect.Top := ARect.Top + 2;

  if APlannerItem.FIsCurrent and not Print then
    Canvas.Brush.Color := FPlanner.FDisplay.FColorCurrentItem
  else
    Canvas.Brush.Color := APlannerItem.Color;

  InflateRect(ARect, -4, 0);
{$IFDEF TMSSKINS}
  if APlannerItem.Shape = psSkin then
    InflateRect(ARect, -FPlanner.Skin.SkinX, -FPlanner.Skin.SkinY);
{$ENDIF}
  if APlannerItem.Background then
  begin
    if APlannerItem.Transparent and SelColor then
      Canvas.Brush.Color := BlendColor(CellColor, APlannerItem.Color,
        FPlanner.SelectBlend);

    if not(Print and APlannerItem.Transparent) then
    begin
      if BackgroundTo <> clNone then
        DrawGradient(Canvas, Background, BackgroundTo, 64, R, APlannerItem.ColorDirection = gdVertical)
      else
        Canvas.FillRect(R);
      Canvas.Pen.Color := APlannerItem.FPlanner.GridLineColor;
      Canvas.MoveTo(R.Right - 1, R.Top);
      Canvas.LineTo(R.Right - 1, R.Bottom);
    end;
  end;

  ColumnHeight := 0;
  ch := 0;
  ih := 0;
  iw := 0;
  MultiImage := False;
  PlannerImagePoint := Point(0, 0);

  if Assigned(APlannerItem.FPlanner.PlannerImages) and
    ((APlannerItem.ImageID >= 0) or (APlannerItem.ImageIndexList.Count > 0))
    then
  begin
    PlannerImagePoint.X := Round
      ((APlannerItem.FPlanner.PlannerImages.Width + 2) * GetDeviceCaps
        (Canvas.Handle, LOGPIXELSX) / 96);
    PlannerImagePoint.Y := Round
      ((APlannerItem.FPlanner.PlannerImages.Height) * GetDeviceCaps
        (Canvas.Handle, LOGPIXELSY) / 96);
    ih := PlannerImagePoint.Y;
  end;

  if (APlannerItem.CaptionType in [ctTime, ctText, ctTimeText]) then
  begin
    Canvas.Font.Assign(APlannerItem.CaptionFont);

    if APlannerItem.Selected and APlannerItem.ShowSelection then
      Canvas.Font.Color := APlannerItem.SelectFontColor;

    if APlannerItem.Flashing and APlannerItem.FlashOn and APlannerItem.
      UniformBkg then
      Canvas.Font.Color := FPlanner.FlashFontColor;
    SetBkMode(Canvas.Handle, Transparent);
    ColumnHeight := Canvas.TextHeight('gh') + 4;

    if APlannerItem.Flashing and APlannerItem.FlashOn and APlannerItem.
      UniformBkg then
      Canvas.Font.Color := FPlanner.FlashFontColor;

    ih := Max(ColumnHeight, ih);

    ch := ih;
{$IFDEF TMSSKINS}
    if APlannerItem.Shape <> psSkin then
{$ENDIF}
      // Draw line under Caption
      if (ARect.Top + ih + 1 < ARect.Bottom) and (APlannerItem.CaptionDivider) then
      begin
        if (APlannerItem.ImagePosition = ipVertical) and Assigned
          (APlannerItem.FPlanner.PlannerImages) and
          (APlannerItem.ImageIndexList.Count > 0) then
          Canvas.MoveTo
            (ARect.Left - 2 + APlannerItem.FPlanner.PlannerImages.Width,
            ARect.Top + ih + 1)
        else
          Canvas.MoveTo(ARect.Left - 2, ARect.Top + ih + 1);

        Canvas.LineTo(ARect.Right + 2, ARect.Top + ih + 1);
      end;

    ih := Min(ARect.Bottom - ARect.Top - 1, ih);
    {
     Canvas.MoveTo(ARect.Left, ARect.Top + ih + 1);
     Canvas.LineTo(ARect.Right, ARect.Top + ih + 1);
    }
    if not APlannerItem.UniformBkg then
    begin
      if APlannerItem.Selected and (APlannerItem.SelectCaptionBkg <> clNone) then
      begin
        Canvas.Brush.Color := APlannerItem.SelectCaptionBkg;
        Canvas.Pen.Color := APlannerItem.SelectCaptionBkg;
      end
      else
      begin
        Canvas.Brush.Color := APlannerItem.CaptionBkg;
        Canvas.Pen.Color := APlannerItem.CaptionBkg;
      end;
      Canvas.Brush.Style := bsSolid;
    end
    else
    begin
      if APlannerItem.Flashing and APlannerItem.FlashOn then
        Canvas.Brush.Color := FPlanner.FlashColor
      else
        Canvas.Brush.Color := Background;
    end;

    R := ARect;
    R.Left := ARect.Left + iw;
    R.Bottom := R.Top + ih;

    InflateRect(R, 1, 1);

    if not APlannerItem.Focus then
    begin
      R.Left := R.Left - 2;
      R.Right := R.Right + 2;
    end;
{$IFDEF TMSSKINS}
    if APlannerItem.Shape <> psSkin then
    begin
{$ENDIF}
      if APlannerItem.Selected and (APlannerItem.SelectCaptionBkg <> clNone) then
      begin
        DrawGradient(Canvas, APlannerItem.SelectCaptionBkg, APlannerItem.SelectCaptionBkgTo, FPlanner.GradientSteps, R,
          APlannerItem.CaptionBkgDirection <> gdVertical)
      end
      else
      begin
        DrawGradient(Canvas, APlannerItem.CaptionBkg, APlannerItem.CaptionBkgTo, FPlanner.GradientSteps, R,
            APlannerItem.CaptionBkgDirection <> gdVertical);
      end;
{$IFDEF TMSSKINS}
    end;
{$ENDIF}
    if not APlannerItem.Focus then
    begin
      R.Left := R.Left + 2;
      R.Right := R.Right - 2;
    end;
  end;

  ih := 0;

  if Assigned(APlannerItem.FPlanner.PlannerImages) then
  begin
    if (APlannerItem.ImageID >= 0) and Assigned
      (APlannerItem.FPlanner.PlannerImages) then
    begin
      if ARect.Left + APlannerItem.FPlanner.PlannerImages.Width <
        ARect.Right then
      begin
        iw := PlannerImagePoint.X;
        ih := PlannerImagePoint.Y;
        if Print then
        begin
          Bitmap := TBitmap.Create;
          Bitmap.Width := APlannerItem.FPlanner.PlannerImages.Width;
          Bitmap.Height := APlannerItem.FPlanner.PlannerImages.Height;
          Bitmap.Canvas.Brush.Color := APlannerItem.Color;
          Bitmap.Canvas.Pen.Color := APlannerItem.Color;
          Bitmap.Canvas.FillRect(Rect(0,0,Bitmap.Width, Bitmap.Height));
          APlannerItem.FPlanner.PlannerImages.Draw(Bitmap.Canvas,0,0,APlannerItem.ImageID);

          PrintBitmap(Canvas, Rect(ARect.Left, ARect.Top, ARect.Left + iw,
              ARect.Top + ih), Bitmap);
          Bitmap.Free;
        end
        else
          APlannerItem.FPlanner.PlannerImages.Draw(Canvas,
            ARect.Left + APlannerItem.FPlanner.ImageOffsetX,
            ARect.Top + APlannerItem.FPlanner.ImageOffsetY,
            APlannerItem.ImageID);
      end;
    end;

    for ImageIndex := 0 to APlannerItem.FImageIndexList.Count - 1 do
    begin
      if APlannerItem.ImagePosition = ipHorizontal then
      begin
        if ARect.Left + iw + APlannerItem.FPlanner.PlannerImages.Width <
          ARect.Right then
        begin
          if Print then
          begin
            Bitmap := TBitmap.Create;
            Bitmap.Width := APlannerItem.FPlanner.PlannerImages.Width;
            Bitmap.Height := APlannerItem.FPlanner.PlannerImages.Height;
            Bitmap.Canvas.Brush.Color := APlannerItem.Color;
            Bitmap.Canvas.Pen.Color := APlannerItem.Color;
            Bitmap.Canvas.FillRect(Rect(0,0,Bitmap.Width, Bitmap.Height));
            APlannerItem.FPlanner.PlannerImages.Draw(Bitmap.Canvas,0,0,ImageIndex);

            PrintBitmap(Canvas, Rect(ARect.Left + iw, ARect.Top,
                  ARect.Left + iw + PlannerImagePoint.X,
                  ARect.Top + PlannerImagePoint.Y), Bitmap);

            Bitmap.Free;
          end
          else
            APlannerItem.FPlanner.PlannerImages.Draw(Canvas, ARect.Left + iw,
              ARect.Top, APlannerItem.FImageIndexList.Items[ImageIndex]);

          iw := iw + PlannerImagePoint.X;
          ih := PlannerImagePoint.Y;
        end;
      end
      else
      begin
        if ARect.Top + iw + APlannerItem.FPlanner.PlannerImages.Height < ARect.Bottom then
        begin
          if Print then
          begin
            Bitmap := TBitmap.Create;
            Bitmap.Width := APlannerItem.FPlanner.PlannerImages.Width;
            Bitmap.Height := APlannerItem.FPlanner.PlannerImages.Height;
            Bitmap.Canvas.Brush.Color := APlannerItem.Color;
            Bitmap.Canvas.Pen.Color := APlannerItem.Color;
            Bitmap.Canvas.FillRect(Rect(0,0,Bitmap.Width, Bitmap.Height));

            APlannerItem.FPlanner.PlannerImages.Draw(Bitmap.Canvas,0,0,ImageIndex);

            PrintBitmap(Canvas, Rect(ARect.Left, ARect.Top + ih,
                ARect.Left + PlannerImagePoint.X,
                ARect.Top + PlannerImagePoint.Y + ih), Bitmap);

            Bitmap.Free;
          end
          else
            APlannerItem.FPlanner.PlannerImages.Draw(Canvas, ARect.Left,
              ARect.Top + ih, APlannerItem.FImageIndexList.Items[ImageIndex]);

          ih := ih + PlannerImagePoint.Y;
          iw := PlannerImagePoint.X;
        end;
      end;
      MultiImage := True;
    end;

    if (APlannerItem.ImagePosition = ipHorizontal) and
      (APlannerItem.FImageIndexList.Count > 0) and
      (APlannerItem.CaptionType = ctNone) then
      ARect.Top := ARect.Top + ih;

  end;

  //  if APlannerItem.ImagePosition = ipVertical then
  ih := Max(ch, ColumnHeight);

  if (APlannerItem.CaptionType in [ctTime, ctText, ctTimeText]) then
  begin
    //ih := ih + 2;

    R := ARect;
    R.Left := ARect.Left + iw;
    R.Bottom := R.Top + ih;
{$IFDEF TMSSKINS}
    if APlannerItem.Shape = psSkin then
    begin
      R.Top := R.Top + FPlanner.Skin.SkinCaptionY;
      R.Left := R.Left + FPlanner.Skin.SkinCaptionX;
    end;
{$ENDIF}
    if (APlannerItem.ShowDeleteButton) and (R.Right - R.Left > 32) then
      R.Right := R.Right - APlannerItem.FPlanner.DeleteGlyph.Width;

    if (APlannerItem.URL <> '') and (R.Right - R.Left > 32) then
      R.Right := R.Right - APlannerItem.FPlanner.URLGlyph.Width;

    if (APlannerItem.Attachement <> '') and (R.Right - R.Left > 32) then
      R.Right := R.Right - APlannerItem.FPlanner.AttachementGlyph.Width;

    if (APlannerItem.ShowDeleteButton) or (APlannerItem.URL <> '') or
      (APlannerItem.Attachement <> '') then
      R.Right := R.Right - 2;

    CaptionPaintString := APlannerItem.GetCaptionString;

    HorizontalAlign := AlignToFlag(APlannerItem.CaptionAlign);
    SetBkMode(Canvas.Handle, Transparent);
    if APlannerItem.Unicode then
    begin
      DrawFlags := DT_NOPREFIX or DT_END_ELLIPSIS or HorizontalAlign;
      DrawTextExW(Canvas.Handle, PWideChar(APlannerItem.WideCaption),
        Length(APlannerItem.WideCaption), R, DrawFlags, nil);
    end
    else
    begin

      if IsHtml(APlannerItem, CaptionPaintString, True) then

        HTMLDrawEx(Canvas, CaptionPaintString, R, FPlanner.PlannerImages, 0, 0,
          -1, -1, 1, False, False, Print, False, True, False,
          APlannerItem.WordWrap
          , False
          , FPlanner.FHTMLFactor, FPlanner.URLColor, clNone, clNone, clGray,
          Anchor, StrippedHTMLString, FocusAnchor, XSize, YSize, ml, hl, hr
          , CR, CID, CV, CT, FPlanner.FImageCache, FPlanner.FContainer, Handle
        )

      else
      begin
        DrawFlags := DT_NOPREFIX or DT_END_ELLIPSIS or HorizontalAlign;
        //DrawFlags := FPlanner.DrawTextBiDiModeFlags(DrawFlags);
        if BiDiMode = bdRightToLeft then
          SwapLR(R);
        DrawText(Canvas.Handle, PChar(CaptionPaintString),
          Length(CaptionPaintString), R, DrawFlags);
      end;
    end;

    R.Right := ARect.Right;
    R.Top := R.Top - 2;

    if (APlannerItem.ShowDeleteButton) and (R.Right - R.Left > 32) then
    begin
      APlannerItem.FPlanner.DeleteGlyph.TransparentColor :=
        APlannerItem.FPlanner.DeleteGlyph.Canvas.Pixels[0, 0];
      APlannerItem.FPlanner.DeleteGlyph.Transparent := True;

      if Print then
      begin
        pw := Round(16 * GetDeviceCaps(Canvas.Handle, LOGPIXELSX) / 96);
        ph := Round(16 * GetDeviceCaps(Canvas.Handle, LOGPIXELSY) / 96);
        PrintBitmap(Canvas, Rect(R.Right - pw, R.Top, R.Right, R.Top + ph),
          APlannerItem.FPlanner.DeleteGlyph);
        R.Right := R.Right - pw;
      end
      else
      begin
        Canvas.Draw(R.Right - APlannerItem.FPlanner.DeleteGlyph.Width, R.Top,
          APlannerItem.FPlanner.DeleteGlyph);
        R.Right := R.Right - APlannerItem.FPlanner.DeleteGlyph.Width;
      end;
    end;

    if (APlannerItem.Attachement <> '') and (R.Right - R.Left > 32) then
    begin
      APlannerItem.FPlanner.AttachementGlyph.TransparentColor :=
        APlannerItem.FPlanner.AttachementGlyph.Canvas.Pixels[0, 0];
      APlannerItem.FPlanner.AttachementGlyph.Transparent := True;

      if Print then
      begin
        pw := Round(16 * GetDeviceCaps(Canvas.Handle, LOGPIXELSX) / 96);
        ph := Round(16 * GetDeviceCaps(Canvas.Handle, LOGPIXELSY) / 96);
        PrintBitmap(Canvas, Rect(R.Right - pw, R.Top, R.Right, R.Top + ph),
          APlannerItem.FPlanner.AttachementGlyph);
        R.Right := R.Right - pw;
      end
      else
      begin
        Canvas.Draw(R.Right - APlannerItem.FPlanner.AttachementGlyph.Width,
          R.Top, APlannerItem.FPlanner.AttachementGlyph);
        R.Right := R.Right - APlannerItem.FPlanner.AttachementGlyph.Width;
      end;
    end;

    if (APlannerItem.URL <> '') and (R.Right - R.Left > 32) then
    begin
      APlannerItem.FPlanner.URLGlyph.TransparentColor :=
        APlannerItem.FPlanner.URLGlyph.Canvas.Pixels[0, 0];
      APlannerItem.FPlanner.URLGlyph.Transparent := True;

      if Print then
      begin
        pw := Round(16 * GetDeviceCaps(Canvas.Handle, LOGPIXELSX) / 96);
        ph := Round(16 * GetDeviceCaps(Canvas.Handle, LOGPIXELSY) / 96);
        PrintBitmap(Canvas, Rect(R.Right - pw, R.Top, R.Right, R.Top + ph),
          APlannerItem.FPlanner.URLGlyph);
      end
      else
      begin
        Canvas.Draw(R.Right - APlannerItem.FPlanner.URLGlyph.Width, R.Top,
          APlannerItem.FPlanner.URLGlyph);
      end;
    end;

    iw := 0;
  end
  else
    ih := 0;

  if MultiImage then
  begin
    iw := 0;
    //ih := PlannerImagePoint.Y;
  end;

  Canvas.Font.Assign(APlannerItem.Font);

  if APlannerItem.Selected and APlannerItem.ShowSelection then
    Canvas.Font.Color := APlannerItem.SelectFontColor;

  if APlannerItem.Flashing and APlannerItem.FlashOn then
    Canvas.Font.Color := FPlanner.FlashFontColor;

  APlannerItem.FCaptionHeight := ch;

  if (APlannerItem.ImagePosition = ipVertical) and Assigned
    (APlannerItem.FPlanner.PlannerImages) and
    (APlannerItem.ImageIndexList.Count > 0) then
    ARect.Left := ARect.Left + APlannerItem.FPlanner.PlannerImages.Width +
      EDITOFFSET;

  ARect.Top := ARect.Top + ih + 2 + FPlanner.PaintMarginTY;
  ARect.Left := ARect.Left + iw + FPlanner.PaintMarginLX;

  ARect.Bottom := ARect.Bottom - FPlanner.PaintMarginBY;
  ARect.Right := ARect.Right - FPlanner.PaintMarginRX;

  if APlannerItem.CompletionDisplay = cdVertical then
  begin
    Canvas.Brush.Color := FPlanner.CompletionColor1;
    Canvas.Pen.Color := FPlanner.CompletionColor1;

    Canvas.Rectangle(ARect.Left, ARect.Top - 1 + Round((100 - APlannerItem.Completion) / 100 *
          (ARect.Bottom - ARect.Top - 4)), ARect.Left + 10, ARect.Bottom - 4);

    Canvas.Brush.Color := FPlanner.CompletionColor2;
    Canvas.Pen.Color := FPlanner.CompletionColor2;

    Canvas.Rectangle(ARect.Left, ARect.Top - 1, ARect.Left + 10,  ARect.Top - 2 + Round((100 - APlannerItem.Completion) / 100 * (ARect.Bottom - ARect.Top - 4)));

    Canvas.Brush.Style := bsClear;
    Canvas.Pen.Color := clBlack;
    Canvas.Rectangle(ARect.Left, ARect.Top - 1, ARect.Left + 10, ARect.Bottom - 4);

    ARect.Left := ARect.Left + 11;
  end;

  if APlannerItem.CompletionDisplay = cdHorizontal then
  begin
    Canvas.Brush.Color := FPlanner.CompletionColor1;
    Canvas.Pen.Color := FPlanner.CompletionColor1;
    Canvas.Rectangle(ARect.Left, ARect.Top,
      ARect.Left + Round((APlannerItem.Completion) / 100 *
          (ARect.Right - ARect.Left + 2)), ARect.Top + 10);

    Canvas.Brush.Color := FPlanner.CompletionColor2;
    Canvas.Pen.Color := FPlanner.CompletionColor2;
    Canvas.Rectangle(ARect.Left + Round((APlannerItem.Completion) / 100 *
          (ARect.Right - ARect.Left + 2)), ARect.Top, ARect.Right,
      ARect.Top + 10);

    Canvas.Brush.Style := bsClear;
    Canvas.Pen.Color := clBlack;
    Canvas.Rectangle(ARect.Left, ARect.Top, ARect.Right, ARect.Top + 10);

    ARect.Top := ARect.Top + 11;
  end;

  PaintString := APlannerItem.ItemText;

  if Assigned(FPlanner.OnItemText) then
    FPlanner.OnItemText(FPlanner, APlannerItem, PaintString);

  HorizontalAlign := AlignToFlag(APlannerItem.Alignment);
  if IsRtf(PaintString) then
    RTFPaint(Canvas, ARect, PaintString, Background)
  else
  if APlannerItem.Unicode then
  begin
    SetBkMode(Canvas.Handle, Transparent);

    DrawFlags := DT_NOPREFIX or DT_EDITCONTROL or HorizontalAlign;

    if APlannerItem.FWordWrap then
      DrawFlags := DrawFlags or DT_WORDBREAK
    else
      DrawFlags := DrawFlags or DT_SINGLELINE or DT_END_ELLIPSIS;

    YSize := DrawTextExW(Canvas.Handle, PWideChar(APlannerItem.WideText),
      Length(APlannerItem.WideText), ARect, DrawFlags, nil);
    APlannerItem.FClipped := YSize > (ARect.Bottom - ARect.Top);

  end
  else

  begin
    if IsHtml(APlannerItem, PaintString, False) then
    begin
      PaintString := StripLineBreaks(PaintString);

      GetCursorPos(pt);
      pt := ScreenToClient(pt);
      pt.Y := pt.Y + 2;
      HRGN := CreateRectRgn(ARect.Left, ARect.Top, ARect.Right, ARect.Bottom);
      SelectClipRgn(Canvas.Handle, HRGN);
      HTMLDrawEx(Canvas, PaintString, ARect, FPlanner.PlannerImages, pt.X,
        pt.Y, -1, -1, 1, False, False, Print, False, True, False,
        APlannerItem.FWordWrap
        , False
        , FPlanner.FHTMLFactor, FPlanner.URLColor, clNone, clNone, clGray,
        Anchor, StrippedHTMLString, FocusAnchor, XSize, YSize, ml, hl, hr
        , CR, CID, CV, CT, FPlanner.FImageCache, FPlanner.FContainer, Handle
      );
      SelectClipRgn(Canvas.Handle, 0);
      DeleteObject(HRGN);
      APlannerItem.FClipped := YSize > (ARect.Bottom - ARect.Top);
    end
    else
    begin
      SetBkMode(Canvas.Handle, Transparent);

      DrawFlags := DT_NOPREFIX or DT_EDITCONTROL or HorizontalAlign;

      if APlannerItem.FWordWrap then
        DrawFlags := DrawFlags or DT_WORDBREAK
      else
        DrawFlags := DrawFlags or DT_SINGLELINE or DT_END_ELLIPSIS;

      //DrawFlags := FPlanner.DrawTextBiDiModeFlags(DrawFlags);

      if (BiDiMode = bdRightToLeft) then
        SwapLR(ARect);
      YSize := DrawTextEx(Canvas.Handle, PChar(PaintString),
        Length(PaintString), ARect, DrawFlags, nil);
      APlannerItem.FClipped := YSize > (ARect.Bottom - ARect.Top);
    end;
  end;

  if (APlannerItem.FBeginOffset <> 0) and not APlannerItem.InHeader then
  begin
    DrawArrow(Canvas, clBlue, ro.Left + FPlanner.TrackWidth,
      ro.Bottom - 8 - FPlanner.TrackWidth, adLeft);
  end;

  if (APlannerItem.FEndOffset <> 0) and not APlannerItem.InHeader then
  begin
    DrawArrow(Canvas, clBlue, ro.Right - 8 - FPlanner.FTrackWidth,
      ro.Bottom - 8 - FPlanner.TrackWidth, adRight);
  end;

  if APlannerItem.HintIndicator and (APlannerItem.Hint <> '') then
  begin
    Canvas.Pen.Color := APlannerItem.HintIndicatorColor;
    Canvas.Brush.Color := Canvas.Pen.Color;
    Canvas.Polygon([Point(ro.Right-5,ro.Top),Point(ro.Right,ro.Top),Point(ro.Right,ro.Top + 5)]);
    Canvas.Brush.Color := APlannerItem.Color;
  end;

  FPlanner.DoItemAfterPaint(APlannerItem, Canvas, ARect);
end;

procedure TPlannerGrid.PaintSideCol(Canvas: TCanvas; ARect: TRect;
  ARow, APos, Offs: Integer; Occupied, Print: Boolean);
var
  Line1, Line2, Line3, DT: string;
  HorizontalAlign: Integer;
  MinutesWidth, HoursWidth, MinutesHeight: Integer;
  OldSize: Integer;
  OnTheHour: Boolean;
  HS, IsDay: Boolean;
  DNum, delta: Integer;
  DRect: TRect;
  HOldFont, HNewFont: THandle;
  LFont: TLogFont;
  dday: Integer;
  BTM: dword;
  t1, t2: TDateTime;
  p: double;
  PRect: TRect;
  ORow: Integer;

  procedure DrawTimeIndicator(ARect: TRect; po: double);
  var
    offset: integer;
  begin
    offset := round(po);
    if (FPlanner.Sidebar.TimeIndicatorType in [tiLine, tiLineGlyph]) then
    begin
      Canvas.Pen.Color := FPlanner.Sidebar.TimeIndicatorColor;
      Canvas.Pen.Width := 3;
      Canvas.MoveTo(ARect.Left, ARect.Top + offset);
      Canvas.LineTo(ARect.Right, ARect.Top + offset);
      Canvas.Pen.Width := 1;
    end;

    if (FPlanner.Sidebar.TimeIndicatorType in [tiLineGlyph, tiGlyph]) and not FPlanner.Sidebar.TimeIndicatorGlyph.Empty then
    begin
      FPlanner.Sidebar.TimeIndicatorGlyph.Transparent := true;
      Canvas.Draw(ARect.Left, ARect.Top + offset - (FPlanner.Sidebar.TimeIndicatorGlyph.Height div 2),FPlanner.Sidebar.TimeIndicatorGlyph);
    end;
  end;

begin
  // Initialize
  HS := False;

  PRect := ARect;
  ORow := ARow;

  if (FPlanner.Display.DisplayText > 0) then
  begin
    delta := (FPlanner.Display.DisplayStart + ARow) mod FPlanner.Display.DisplayText;

    if (delta <> 0) then
    begin
      ARow := ARow - delta;

      if Print then
        ARect.Top := ARect.Top - delta * (ARect.Bottom - ARect.Top + 2)
      else
        ARect.Top := ARect.Top - delta * FPlanner.Display.DisplayScale;
    end;
  end;

  GetSideBarLines(ARow + Offs, APos, Line1, Line2, Line3, HS);
  //  Canvas.Font.Assign(FPlanner.Sidebar.Font);

  MinutesWidth := Canvas.TextWidth(Line2);
  MinutesHeight := Canvas.TextHeight(Line2);

  if Occupied then
    Canvas.Font.Color := FPlanner.Sidebar.OccupiedFontColor;

  HorizontalAlign := AlignToFlag(FPlanner.Sidebar.Alignment);

  if (FPlanner.FMode.FPlannerType = plHalfDayPeriod) then
  begin
    DRect := ARect;

    if not Odd(ARow) then
      ARect.Bottom := ARect.Bottom + DefaultRowHeight
    else
      ARect.Top := ARect.Top - DefaultRowHeight;

    //Canvas.Pen.Color := FPlanner.GridLineColor;

    Canvas.Pen.Color := FPlanner.Sidebar.SeparatorLineColor;

    Canvas.MoveTo(ARect.Left - 1, ARect.Bottom);
    Canvas.LineTo(ARect.Right, ARect.Bottom);

    if FPlanner.Sidebar.AMPMPos = apNone then
      Line3 := '';
    if Odd(ARow) then
      BTM := DT_BOTTOM
    else
      BTM := 0;
    SetBkMode(Canvas.Handle, Transparent);
    DrawText(Canvas.Handle, PChar(Line3), Length(Line3), DRect,
      DT_RIGHT or DT_SINGLELINE or BTM);
    Line3 := '';
  end;

  if (FPlanner.FMode.FPlannerType = plTimeLine) then
  begin
    if Line2 <> '' then
      Line1 := Line1 + TimeSeparator + Line2;

    dday := (MININDAY div FPlanner.Display.DisplayUnit) -
      (FPlanner.Mode.TimeLineNVUEnd + FPlanner.Mode.TimeLineNVUBegin);

    if dday = 0 then
      dday := 1;

    delta := ARow mod dday;
    DNum := ARow div dday;

    {
    delta := ARow mod ((MININDAY div (FPlanner.Display.DisplayUnit)));
    DNum := ((ARow * FPlanner.Display.DisplayUnit) div MININDAY);
    }

    begin
      if FPlanner.Sidebar.DateTimeFormat <> '' then
        DT := FormatDateTime(FPlanner.Sidebar.DateTimeFormat,
          FPlanner.Mode.TimeLineStart + DNum)
      else
        DT := DateToStr(FPlanner.Mode.TimeLineStart + DNum);

      DRect := PRect;

      if Print then
        DRect.Top := PRect.Top - delta * (PRect.Bottom - PRect.Top + 2)
      else
        DRect.Top := PRect.Top - delta * DefaultRowHeight;

      //DRect.Bottom := DRect.Top + (MININDAY div (FPlanner.Display.DisplayUnit)) * DefaultRowHeight;

      if Print then
        DRect.Bottom := DRect.Top + dday * (PRect.Bottom - PRect.Top + 2)
      else
        DRect.Bottom := DRect.Top + dday * DefaultRowHeight;

      SetBkMode(Canvas.Handle, Transparent);

      // do font rotation here
      GetObject(Canvas.Font.Handle, SizeOf(LFont), Addr(LFont));
      LFont.lfEscapement := 90 * 10;
      LFont.lfOrientation := 90 * 10;

      if Print and FPlanner.FPrinterDriverFix then
      begin
        LFont.lfEscapement := -LFont.lfEscapement;
        LFont.lfOrientation := -LFont.lfEscapement;
      end;

      HNewFont := CreateFontIndirect(LFont);
      HOldFont := SelectObject(Canvas.Handle, HNewFont);

      //if Print then
        Canvas.TextOut(DRect.Left, DRect.Bottom - 4, DT);
      //else
      //  DrawText(Canvas.Handle, PChar(DT), Length(DT), DRect,
      //    DT_NOPREFIX or DT_BOTTOM or DT_LEFT or DT_SINGLELINE);

      HNewFont := SelectObject(Canvas.Handle, HOldFont);
      DeleteObject(HNewFont);
    end;

    if (delta = 0) and (ARow > 0) then
    begin
      DRect.Top := ARow * DefaultRowHeight;
      Canvas.Pen.Color := FPlanner.GridLineColor;
      Canvas.MoveTo(ARect.Left - 1, ARect.Top - 1);
      Canvas.LineTo(ARect.Right - 1, ARect.Top - 1);
    end;

    MinutesWidth := Canvas.TextWidth(Line1);
    ARect.Left := ARect.Right - MinutesWidth;

    //ARect.Left := ARect.Left + (ARect.Right - ARect.Left) div 2;

    Line2 := Line1;
    Line1 := '';

    if (FPlanner.Sidebar.TimeIndicator) then
    begin
      FPlanner.CellToAbsTime(ORow, t1, t2);

      if (Now >= t1) and (Now <= t2) then
      begin
        p := FPlanner.Display.DisplayScale * ((Now - t1) / (t2 - t1));
        DrawTimeIndicator(PRect, p);
      end;
    end;
  end;

  if (ARect.Bottom - ARect.Top < MinutesHeight * 2) and
    (FPlanner.Mode.PlannerType <> plDay) then
    Line1 := '';

  // Special painting in case there is a Line1 in day mode
  if (FPlanner.FMode.FPlannerType in [plDay]) or (Line1 <> '') then
  begin
    OnTheHour := False;
    IsDay := FPlanner.FMode.FPlannerType = plDay;

    if (FPlanner.Sidebar.TimeIndicator) then
    begin
      FPlanner.CellToAbsTime(ORow, t1, t2);

      if (Frac(Now) >= Frac(t1)) and (Frac(Now) <= Frac(t2)) then
      begin
        p := FPlanner.Display.DisplayScale *
          ((Frac(Now) - Frac(t1)) / (Frac(t2) - Frac(t1)));

        DrawTimeIndicator(PRect, p);
      end;
    end;

    HS := HS or not IsDay;

    // Line1=HoursString, Line2=MinutesString, Line3=AmPmString
    //    if ARow >= 0 then
    begin
      if FPlanner.FMode.FPlannerType = plDay then
      begin
        OnTheHour := Pos('00', Line2) > 0; // Don't display hours if we are not 'on the hour'

        if FPlanner.Sidebar.AMPMPos = apNone then
          Line3 := '';

        if Line3 <> '' then // There is an AM/PM, so concatenate it to the minutes
        begin
          if FPlanner.Sidebar.AMPMPos = apUnderTime then
            Line2 := Line2 + RegularCRLF + Line3
          else
          begin
            Line2 := Line2 + ' ' + Line3;
            MinutesWidth := Canvas.TextWidth(Line2);
          end;
        end;
      end;

      if FPlanner.FMode.FPlannerType = plHalfDayPeriod then
      begin
        if FPlanner.Sidebar.AMPMPos = apNone then
          Line3 := '';

        if FPlanner.Sidebar.AMPMPos = apUnderTime then
          Line2 := Line2 + RegularCRLF + Line3
        else
          Line2 := Line2 + ' ' + Line3
      end;

      if FPlanner.FSidebar.Flat and (FPlanner.FMode.FPlannerType = plDay) and
        (ARow <> FPlanner.FGrid.TopRow) then
      begin
        Canvas.Pen.Color := FPlanner.Sidebar.LineColor;

        if OnTheHour then
          Canvas.MoveTo(ARect.Left, ARect.Top - 1) // paint Hours
        else
          Canvas.MoveTo(ARect.Right - MinutesWidth, ARect.Top - 1);
        // do not paint hours

        Canvas.LineTo(ARect.Right - 1, ARect.Top - 1);
      end;
    end;

    OldSize := Canvas.Font.Size;
    try

      if IsDay then
      begin
        Canvas.Font.Size := Round(Canvas.Font.Size * FPlanner.Sidebar.HourFontRatio);
      end
      else
      begin
        MinutesWidth := 0;
      end;

      HoursWidth := Canvas.TextWidth(Line1);
      SetBkMode(Canvas.Handle, Transparent);

      case FPlanner.Sidebar.Alignment of
      taLeftJustify:
        begin
          if HS then
            Canvas.TextOut(ARect.Left, ARect.Top, Line1);
  
          if IsDay then
            ARect.Left := ARect.Left + HoursWidth + 4
        end;
      taRightJustify:
        begin
          if HS then
            Canvas.TextOut(ARect.Right - MinutesWidth - 4 - HoursWidth, ARect.Top, Line1);
        end;
      taCenter:
        begin
          if HS then
            Canvas.TextOut(ARect.Left + (ARect.Right - ARect.Left - HoursWidth - MinutesWidth) div 2, ARect.Top, Line1);
          if IsDay then
            ARect.Left := ARect.Left + HoursWidth + 4 + (ARect.Right - ARect.Left - HoursWidth - MinutesWidth) div 2;
        end;
      end;

      if not IsDay then
        ARect.Top := ARect.Top + MinutesHeight + 2;

    finally
      if IsDay then
        Canvas.Font.Size := OldSize;
    end;
  end;

  if (FPlanner.Display.DisplayText > 0) then
  begin
    if ((FPlanner.Display.DisplayStart + ARow) mod FPlanner.Display.DisplayText <> 0) then
    begin
      Line2 := '';
    end;
  end;

  { Painting }
  if (Line2 <> '') then
  begin
    SetBkMode(Canvas.Handle, Transparent);
    DrawText(Canvas.Handle, PChar(Line2), Length(Line2), ARect,
      DT_NOPREFIX or DT_WORDBREAK or HorizontalAlign);
  end;

end;

procedure TPlannerGrid.PaintSideRow(Canvas: TCanvas; ARect: TRect;
  AColumn, APos: Integer; Occupied, Print: Boolean; DefColWidth: Integer);
var
  Line1, Line2, Line3, DT: string;
  HorizontalAlign: Integer;
  OldSize: Integer;
  OnTheOur: Boolean;
  LFont: TLogFont;
  HOldFont, HNewFont: HFont;
  MinorLineWidth: Integer;
  MajorLineWidth: Integer;
  HS: Boolean;
  DNum, delta: Integer;
  DRect, HRect, PRect: TRect;
  dday: Integer;
  p: double;
  t1, t2: TDateTime;
  Mins: Integer;
  OCol, colw: Integer;

  procedure DrawTimeIndicator(ARect: TRect; po: double);
  var
    offset: integer;
  begin
    offset := Max(0,round(po) - 2);

    if (FPlanner.Sidebar.TimeIndicatorType in [tiLine, tiLineGlyph]) then
    begin
      Canvas.Pen.Color := FPlanner.Sidebar.TimeIndicatorColor;
      Canvas.Pen.Width := 3;
      Canvas.MoveTo(ARect.Left + offset, ARect.Top);
      Canvas.LineTo(ARect.Left + offset, ARect.Bottom);
      Canvas.Pen.Width := 1;
    end;

    if (FPlanner.Sidebar.TimeIndicatorType in [tiLineGlyph, tiGlyph]) and not FPlanner.Sidebar.TimeIndicatorGlyph.Empty then
    begin
      FPlanner.Sidebar.TimeIndicatorGlyph.Transparent := true;
      Canvas.Draw(ARect.Left + offset - (FPlanner.Sidebar.TimeIndicatorGlyph.Width div 2), ARect.Top,FPlanner.Sidebar.TimeIndicatorGlyph);
    end;
  end;


begin
  // Initialize
  GetSideBarLines(AColumn, APos, Line1, Line2, Line3, HS);
  MinorLineWidth := Canvas.TextHeight(Line2);

  PRect := ARect;
  OCol := AColumn;

  HorizontalAlign := AlignToFlag(FPlanner.Sidebar.Alignment);
  HOldFont := 0;
  SetBkMode(Canvas.Handle, Transparent);

  if (FPlanner.Display.DisplayText > 0) then
  begin
    delta := (FPlanner.Display.DisplayStart + AColumn) mod FPlanner.Display.DisplayText;

    if (delta <> 0) then
    begin
      AColumn := AColumn - delta;
      if Print then
        ARect.Left := ARect.Left - delta * (ARect.Right - ARect.Left + 2)
      else
        ARect.Left := ARect.Left - delta * FPlanner.Display.DisplayScale;

      GetSideBarLines(AColumn, APos, Line1, Line2, Line3, HS);
    end
    else
      Line2 := '';

    ARect.Right := ARect.Left + (DefaultColWidth);
  end
  else if (FPlanner.Mode.FPlannerType = plTimeLine) then
  begin
    if Line2 <> '' then
      Line1 := Line1 + TimeSeparator + Line2;
  end;

  if FPlanner.Sidebar.AMPMPos = apNone then
    Line3 := '';

  if Occupied then
    Canvas.Font.Color := FPlanner.Sidebar.OccupiedFontColor;

  if (FPlanner.Mode.FPlannerType = plHalfDayPeriod) then
  begin
    DRect := ARect;

    if not Odd(AColumn) then
      ARect.Right := ARect.Right + DefColWidth
    else
      ARect.Left := ARect.Left - DefColWidth;

    Canvas.Pen.Color := FPlanner.Sidebar.SeparatorLineColor;

    Canvas.MoveTo(ARect.Right + 3, ARect.Top);
    Canvas.LineTo(ARect.Right + 3, ARect.Bottom);

    if (Line3 <> '') and (not FPlanner.Sidebar.RotateOnTop) then
      ARect.Bottom := ARect.Bottom - Canvas.TextHeight('gh');
    SetBkMode(Canvas.Handle, Transparent);
    DrawText(Canvas.Handle, PChar(Line3), Length(Line3), DRect, DT_CENTER or DT_SINGLELINE or DT_BOTTOM);
    Line3 := '';
  end;

  if (FPlanner.FMode.FPlannerType = plTimeLine) then
  begin
    dday := (MININDAY div FPlanner.Display.DisplayUnit) - (FPlanner.Mode.TimeLineNVUBegin + FPlanner.Mode.TimeLineNVUEnd);
    if dday = 0 then
    begin
      delta := 0;
      DNum := 1;
    end
    else
    begin
      delta := AColumn mod dday;
      DNum := AColumn div dday;
    end;

    {
    delta := AColumn mod (MININDAY div (FPlanner.Display.DisplayUnit));
    DNum := ((AColumn * FPlanner.Display.DisplayUnit) div MININDAY);
    }

    if FPlanner.Sidebar.DateTimeFormat <> '' then
      DT := FormatDateTime(FPlanner.Sidebar.DateTimeFormat, FPlanner.Mode.TimeLineStart + DNum)
    else
      DT := DateToStr(FPlanner.Mode.TimeLineStart + DNum);

    if not Print or (delta = dday - 1) then
    begin
      DRect := ARect;

      colw := (ARect.Right - ARect.Left);

      if not Print then
      begin
        DRect.Left := Max(0, ARect.Left - delta * DefaultColWidth);
        DRect.Right := DRect.Left + (dday * DefaultColWidth);
      end
      else
      begin
        DRect.Left := Max(0, ARect.Left - delta * colw);
        DRect.Right := DRect.Left + (dday * colw);
      end;

      DrawText(Canvas.Handle, PChar(DT), Length(DT), DRect, DT_NOPREFIX or HorizontalAlign);
      if (FPlanner.Sidebar.TimeIndicator) then
      begin
        FPlanner.CellToAbsTime(OCol, t1, t2);
        if (Now >= t1) and (Now <= t2) then
        begin
          p := ColWidths[OCol] * ((Now - t1) / (t2 - t1));

          DrawTimeIndicator(PRect, p);
        end;
      end;
    end;

    if not Print or (delta = 0) then
    begin
      DRect := ARect;
      if not Print then
        DRect.Left := (AColumn - delta - LeftCol) * DefaultColWidth;

      Canvas.Pen.Color := FPlanner.GridLineColor;
      Canvas.MoveTo(DRect.Left - 1, ARect.Top);
      Canvas.LineTo(DRect.Left - 1, ARect.Bottom);
    end;

    ARect.Top := ARect.Top + (ARect.Bottom - ARect.Top) div 2;

    if FPlanner.Display.DisplayText >= 0 then
    begin
      Line2 := Line1;
      ARect.Right := ARect.Right + FPlanner.Display.DisplayText * DefaultColWidth;
    end;

    Line1 := '';
  end;

  // Special painting in case there is a Line1
  if (FPlanner.FMode.FPlannerType = plDay) or ((Line1 <> '') and not FPlanner.Sidebar.RotateOnTop) then
  begin
    OnTheOur := False;
    OldSize := Canvas.Font.Size;
    if (FPlanner.FMode.FPlannerType = plDay) then
      Canvas.Font.Size := Round(Canvas.Font.Size * FPlanner.Sidebar.HourFontRatio) - 1;
    try
      MajorLineWidth := Canvas.TextHeight(Line1);
      if FPlanner.FMode.FPlannerType = plDay then
      begin
        OnTheOur := Line2 = '00'; // Don't display hours if we are not 'on the hour'
        if Line3 <> '' then // There is an AM/PM, so concatenate it to the minutes
          Line2 := Line2 + RegularCRLF + Line3;
      end;

      HRect := ARect;

      if (FPlanner.FMode.FPlannerType = plDay) then
      begin
        Mins := (AColumn + FPlanner.Display.DisplayStart) * FPlanner.Display.DisplayUnit + FPlanner.Display.DisplayOffset;
        delta := Round(((Mins mod 60) / FPlanner.Display.DisplayUnit));
        if (delta > 0) then
          HRect.Left := HRect.Left - delta * DefColWidth;

        HRect.Right := HRect.Right + delta * DefColWidth;

        if DefColWidth * Abs(delta) < Canvas.TextWidth(Line1) then
          HS := true;
      end;

      if OnTheOur or HS then
      begin
        if FPlanner.Sidebar.Alignment = taLeftJustify then
          hrect.Right := hrect.Right + 100;

        DrawText(Canvas.Handle, PChar(Line1), Length(Line1), HRect, DT_NOPREFIX or DT_WORDBREAK or HorizontalAlign);
      end;

      if (AColumn > 0) and (AColumn <= ColCount - 1) and (FPlanner.FMode.FPlannerType = plDay) then
      begin
        Canvas.Pen.Color := FPlanner.Sidebar.LineColor;

        if OnTheOur then
          Canvas.MoveTo(ARect.Left - 1, ARect.Bottom - 24)
        else
          Canvas.MoveTo(ARect.Left - 1, ARect.Bottom - 12);

        Canvas.LineTo(ARect.Left - 1, ARect.Bottom);
        {
        if OnTheOur then
          Canvas.MoveTo(Arect.Right + 3,ARect.Bottom - 24)
        else
          Canvas.MoveTo(Arect.Right+ 3,ARect.Bottom - 12);

        Canvas.LineTo(Arect.Right + 3,ARect.Bottom);
        }
      end;

      if (FPlanner.Sidebar.TimeIndicator) then
      begin
        FPlanner.CellToAbsTime(OCol, t1, t2);

        if (Frac(Now) >= Frac(t1)) and (Frac(Now) <= Frac(t2)) then
        begin
          p := FPlanner.Display.DisplayScale *
            ((Frac(Now) - Frac(t1)) / (Frac(t2) - Frac(t1)));

          DrawTimeIndicator(PRect, p);
        end;
      end;

      ARect.Top := ARect.Top + MajorLineWidth;
    finally
      Canvas.Font.Size := OldSize;
    end;
  end
  else
  begin
    if (Line2 = '') then
    begin
      Line2 := Line1;
      Line1 := '';
    end;
  end;

  // Painting

  if (Line2 <> '') then
    case FPlanner.FMode.FPlannerType of
      plDay, plWeek, plTimeLine:
       begin
         DrawText(Canvas.Handle, PChar(Line2), Length(Line2), ARect, DT_NOPREFIX or DT_WORDBREAK or HorizontalAlign);
       end;

      plMonth, plDayPeriod, plHalfDayPeriod, plActiveDayPeriod, plMultiMonth, plCustomList, plCustom:
        begin
          if FPlanner.Sidebar.RotateOnTop then
          begin
            GetObject(Canvas.Font.Handle, SizeOf(LFont), Addr(LFont));
            LFont.lfEscapement := 90 * 10;
            LFont.lfOrientation := 90 * 10;
            if Print and FPlanner.FPrinterDriverFix then
            begin
              LFont.lfEscapement := -LFont.lfEscapement;
              LFont.lfOrientation := -LFont.lfEscapement;
            end;
            HNewFont := CreateFontIndirect(LFont);
            HOldFont := SelectObject(Canvas.Handle, HNewFont);

            SetTextAlign(Canvas.Handle, TA_TOP);
          end;

          if MinorLineWidth >= ARect.Right - ARect.Left then
            MinorLineWidth := 0 // does not fit in the box, so left align
          else
            case HorizontalAlign of
              DT_LEFT: MinorLineWidth := 0;
              DT_RIGHT: MinorLineWidth := ARect.Right - ARect.Left - MinorLineWidth;
              DT_CENTER: MinorLineWidth := (ARect.Right - ARect.Left - MinorLineWidth) shr 1;
            end;
          try
            if FPlanner.Sidebar.RotateOnTop then
            begin
              Canvas.Brush.Style := bsClear;
              if (Line1 <> '') then
              begin
                Canvas.TextRect(ARect, ARect.Left + MinorLineWidth, ARect.Bottom - 4, Line1);
                ARect.Left := ARect.Left + Canvas.TextHeight('gh');
              end;

              Canvas.TextRect(ARect, ARect.Left + MinorLineWidth, ARect.Bottom - 4, Line2);
              ARect.Left := ARect.Left + Canvas.TextHeight('gh');
              if Line3 <> '' then
                Canvas.TextRect(ARect, ARect.Left + MinorLineWidth, ARect.Bottom - 4, Line3);
            end
            else
            begin
              SetBkMode(Canvas.Handle, Transparent);

              DrawText(Canvas.Handle, PChar(Line2), Length(Line2), ARect,
                DT_NOPREFIX or DT_WORDBREAK or HorizontalAlign);
            end;

          finally
            { Cleanup }
            if FPlanner.FMode.FPlannerType in [plMonth, plDayPeriod,
              plHalfDayPeriod, plMultiMonth, plCustomList, plCustom] then
            begin
              if FPlanner.Sidebar.RotateOnTop then
              begin
                HNewFont := SelectObject(Canvas.Handle, HOldFont);
                DeleteObject(HNewFont);
              end;
            end;
          end;
        end;
    end;
end;

procedure TPlannerGrid.DrawCell(AColumn, ARow: LongInt; ARect: TRect;
  AState: TGridDrawState);
begin
  if FPlanner.Sidebar.Orientation = soVertical then
    DrawCellCol(AColumn, ARow, ARect, AState)
  else
    DrawCellRow(AColumn, ARow, ARect, AState);
end;

procedure TPlannerGrid.DrawWallPaperFixed(CRect: TRect; xcorr, ycorr: Integer;
  BKColor: TColor);
var
  SrcRect, DsTRect, Irect: TRect;
  X, Y, ox, oy: Integer;
  dst: TPoint;
begin
  dst.X := FPlanner.FBackGround.Left;
  dst.Y := FPlanner.FBackGround.Top;

  X := FPlanner.FBackGround.Bitmap.Width;
  Y := FPlanner.FBackGround.Bitmap.Height;

  DsTRect.Top := dst.Y;
  DsTRect.Left := dst.X;
  DsTRect.Right := DsTRect.Left + X;
  DsTRect.Bottom := DsTRect.Top + Y;

  if not IntersectRect(Irect, CRect, DsTRect) then
    Exit;
  SetBkMode(Canvas.Handle, Transparent);
  ox := CRect.Left - dst.X;
  oy := CRect.Top - dst.Y;

  SrcRect.Left := ox;
  SrcRect.Top := oy;
  SrcRect.Right := ox + CRect.Right - CRect.Left;
  SrcRect.Bottom := oy + CRect.Bottom - CRect.Top;

  dst.X := dst.X - xcorr;
  dst.Y := dst.Y - ycorr;

  if dst.X < 0 then
    Exit;

  DsTRect := CRect;

  if ox <= 0 then
  begin
    DsTRect.Left := dst.X;
    SrcRect.Left := 0;
    SrcRect.Right := DsTRect.Right - DsTRect.Left;
  end;

  if oy <= 0 then
  begin
    DsTRect.Top := dst.Y;
    SrcRect.Top := 0;
    SrcRect.Bottom := DsTRect.Bottom - DsTRect.Top;
  end;

  if (SrcRect.Left + (DsTRect.Right - DsTRect.Left) > X) then
  begin
    DsTRect.Right := DsTRect.Left + X - SrcRect.Left;
    SrcRect.Right := X;
  end;

  if (SrcRect.Top + DsTRect.Bottom - DsTRect.Top > Y) then
  begin
    DsTRect.Bottom := DsTRect.Top + Y - SrcRect.Top;
    SrcRect.Bottom := Y;
  end;

  Canvas.CopyRect(DsTRect, FPlanner.FBackGround.Bitmap.Canvas, SrcRect);
end;

procedure TPlannerGrid.DrawWallPaperTile(ACol, ARow: Integer; CRect: TRect;
  xcorr, ycorr: Integer; BKColor: TColor);
var
  SrcRect, DsTRect: TRect;
  X, Y, xo, yo, ox, oy, i: Integer;
  BMP: TBitmap;
begin
  BMP := FPlanner.FBackGround.Bitmap;

  if FPlanner.Sidebar.Position <> spTop then
  begin
    if (FPlanner.PositionProps.Count >= ACol) and (ACol > 0) then
    begin
      if (not FPlanner.PositionProps[ACol - 1].Background.Empty)
        and FPlanner.PositionProps[ACol - 1].Use then
        BMP := FPlanner.PositionProps[ACol - 1].Background;
    end;
  end
  else
  begin
    if (FPlanner.PositionProps.Count >= ARow) and (ARow > 0) then
    begin
      if (not FPlanner.PositionProps[ARow - 1].Background.Empty)
        and FPlanner.PositionProps[ARow - 1].Use then
        BMP := FPlanner.PositionProps[ARow - 1].Background;
    end;
  end;

  X := BMP.Width;
  Y := BMP.Height;
  SetBkMode(Canvas.Handle, Transparent);
  if (FPlanner.FSidebar.Position = spLeft) and FPlanner.FSidebar.Visible then
    xo := 1
  else
    xo := 0;

  ox := 0;
  for i := xo + 1 to ACol do
    ox := ox + ColWidths[i - 1];

  yo := 0;
  oy := 0;
  for i := yo + 1 to ARow do
    oy := oy + RowHeights[i - 1];

  ox := ox + xcorr;
  oy := oy + ycorr;

  ox := ox mod X;
  oy := oy mod Y;

  SrcRect.Left := ox;
  SrcRect.Top := oy;
  SrcRect.Right := X;
  SrcRect.Bottom := Y;

  yo := CRect.Top;

  while yo < CRect.Bottom do
  begin
    xo := CRect.Left;
    SrcRect.Left := ox;
    SrcRect.Right := X;
    while xo < CRect.Right do
    begin
      DsTRect := Rect(xo, yo, xo + SrcRect.Right - SrcRect.Left,
        yo + SrcRect.Bottom - SrcRect.Top);

      if DsTRect.Right > CRect.Right then
      begin
        DsTRect.Right := CRect.Right;
        SrcRect.Right := SrcRect.Left + (DsTRect.Right - DsTRect.Left);
      end;
      if DsTRect.Bottom > CRect.Bottom then
      begin
        DsTRect.Bottom := CRect.Bottom;
        SrcRect.Bottom := SrcRect.Top + (DsTRect.Bottom - DsTRect.Top);
      end;

      Canvas.CopyRect(DsTRect, BMP.Canvas, SrcRect);

      xo := xo + SrcRect.Right - SrcRect.Left;
      SrcRect.Left := 0;
      SrcRect.Right := X;
    end;
    yo := yo + SrcRect.Bottom - SrcRect.Top;
    SrcRect.Top := 0;
    SrcRect.Bottom := Y;
  end;
end;

procedure TPlannerGrid.DrawCellCol(AColumn, ARow: LongInt; ARect: TRect;
  AState: TGridDrawState);
var
  OldBrush: TBrush;
  OldFont: TFont;
  SubIndex, M: Integer;
  APlannerItem: TPlannerItem;
  NRect, R: TRect;
  NumberOfConflicts: TPoint;
  CellColor: TColor;
  CellBrush: TBrushStyle;
  Fixcol: Integer;
  ColOffset, NumI: Integer;
  PlannerColorArrayPointer: PPlannerColorArray;
  BottomPen, RightPen: TPen;
  Occupied: Boolean;
  ABrush: TBrush;
  BkgFlag: Boolean;
  RGN: THandle;
  delta: Integer;
  dts, dte: TDateTime;
  BMP: TBitmap;
  selbkg: Boolean;
  AColorTo: TColor;
  UseColor: Boolean;
  sw, tzd: Integer;
  cb: TCellBrush;
  {$IFDEF DELPHIXE2_LVL}
  LStyle: TCustomStyleServices;
  LDetails: TThemedElementDetails;
  SaveIndex: integer;
  cellinstyle: boolean;
  {$ENDIF}

begin
  ColOffset := FPlanner.FSidebar.FColOffset;

  if ColOffset = 0 then
    Fixcol := ColCount - 1
  else
    Fixcol := 0;

  {$IFDEF DELPHIXE2_LVL}
  cellinstyle := false;
  LStyle := StyleServices;
  if LStyle.Enabled and (LStyle.Name <> 'Windows') and (gdSelected in AState) and FPlanner.FUseVCLStyles then
  begin
    cellinstyle := true;
  end;
  {$ENDIF}

  OldFont := TFont.Create;
  OldFont.Assign(Canvas.Font);
  OldBrush := TBrush.Create;
  OldBrush.Assign(Canvas.Brush);

  UseColor := False;

  if (AColumn = Fixcol) or ((FPlanner.PositionGap > 0) and
      (FPlanner.Sidebar.ShowInPositionGap) and FPlanner.GapAtColumn(AColumn))
    or ((AColumn = ColCount - 1) and (FPlanner.Sidebar.Position = spLeftRight)
      and FPlanner.Sidebar.Visible) then
  begin
    // Draw the SideBar
    R := ARect;

    if (AColumn <> Fixcol) and not((AColumn = ColCount - 1) and
        (FPlanner.Sidebar.Position = spLeftRight)
        and FPlanner.Sidebar.Visible) then
    begin
      R.Right := R.Left + FPlanner.FPositionGap;
      ARect.Left := ARect.Left + FPlanner.FPositionGap;
    end;

    Canvas.Brush.Color := FPlanner.Sidebar.Background;
    AColorTo := FPlanner.Sidebar.BackgroundTo;

    Canvas.Font.Assign(FPlanner.Sidebar.Font);

    if (Assigned(FPlanner.OnPlannerSideProp)) then
      FPlanner.OnPlannerSideProp(FPlanner, ARow, Canvas.Brush, Canvas.Font, AColorTo);

    if AColumn = Fixcol then
      APlannerItem := FPlanner.Items.FindItemIdx(ARow)
    else
      APlannerItem := FPlanner.Items.FindItem(ARow, AColumn - ColOffset);

    Occupied := (APlannerItem <> nil) and FPlanner.Sidebar.ShowOccupied;

    if ((ARow >= Selection.Top) and (ARow <= Selection.Bottom) and
        (FPlanner.Sidebar.ActiveColor <> clNone)) and not
      (FPlanner.Sidebar.ShowInPositionGap and (AColumn > Fixcol + 1)) then
    begin
      // if not FPlanner.SideBar.ShowInPositionGap or (AColumn = Selection.Left) then
      begin
        Canvas.Brush.Color := FPlanner.Sidebar.ActiveColor;
        DrawGradient(Canvas, FPlanner.Sidebar.ActiveColor,
            FPlanner.Sidebar.ActiveColorTo, FPlanner.GradientSteps, R, True);
      end;
    end
    else
    begin
      if Occupied then
      begin
        Canvas.Brush.Color := FPlanner.Sidebar.Occupied;
        DrawGradient(Canvas, FPlanner.Sidebar.Occupied,
            FPlanner.Sidebar.OccupiedTo, FPlanner.GradientSteps, R, True);
      end
      else
      begin
        DrawGradient(Canvas, Canvas.Brush.Color, AColorTo, FPlanner.GradientSteps, R, True);
      end;
    end;

    if not FPlanner.Sidebar.Flat then
      Frame3D(Canvas, R, clWhite, clGray, 1);

    if FPlanner.Sidebar.Border then
    begin
      if not FPlanner.FUseVCLStyles then
      begin
        Canvas.Pen.Color := clWhite;
        Canvas.MoveTo(R.Left, R.Top);
        Canvas.LineTo(R.Left, R.Bottom);

        if ARow = FPlanner.FGrid.TopRow then
        begin
          Canvas.MoveTo(R.Left, R.Top);
          Canvas.LineTo(R.Right, R.Top);
        end;
      end;

      Canvas.Pen.Color := FPlanner.SideBar.BorderColor;
      Canvas.MoveTo(R.Right - 1, R.Top);
      Canvas.LineTo(R.Right - 1, R.Bottom);

      if ARow = FPlanner.FGrid.RowCount - 1 then
      begin
        Canvas.MoveTo(R.Left, R.Bottom - 1);
        Canvas.LineTo(R.Right, R.Bottom - 1);
      end;
    end;

    Canvas.Pen.Color := FPlanner.Sidebar.SeparatorLineColor;

    if not(FPlanner.FMode.FPlannerType in [plDay, plTimeLine, plHalfDayPeriod]) then
    begin
      Canvas.MoveTo(R.Left, R.Bottom - 1);
      Canvas.LineTo(R.Right - 1, R.Bottom - 1);
      Canvas.Pen.Color := clGray;
      Canvas.LineTo(R.Right - 1, R.Top);
    end;

    R.Left := R.Left + 4;
    R.Right := R.Right - 4;
    R.Top := R.Top + 1;
    R.Bottom := R.Bottom - 1;

    if Assigned(FPlanner.OnPlannerSideDraw) then
      FPlanner.OnPlannerSideDraw(FPlanner, Self.Canvas, ARect, ARow)
    else
    begin
      if (FPlanner.Sidebar.ShowOtherTimeZone) and
        (FPlanner.Mode.PlannerType = plDay) then
      begin
        sw := (R.Right - R.Left) div 2;
        R.Right := R.Right - sw - 4;
        PaintSideCol(Canvas, R, ARow, AColumn, 0, Occupied, False);

        R.Right := R.Right + sw + 4;
        R.Left := R.Left + sw + 4;

        tzd := FPlanner.Sidebar.TimeZoneMinDelta div FPlanner.Display.DisplayUnit;

        PaintSideCol(Canvas, R, ARow, AColumn, tzd, Occupied, False);

        Canvas.MoveTo(R.Left - 4, R.Top - 1);
        Canvas.LineTo(R.Left - 4, R.Bottom + 1);
        if Assigned(FPlanner.FOnPlannerSideDrawAfter) then
          FPlanner.FOnPlannerSideDrawAfter(Self, Canvas, ARect, ARow);
      end
      else
      begin
        PaintSideCol(Canvas, R, ARow, AColumn, 0, Occupied, False);

        if Assigned(FPlanner.FOnPlannerSideDrawAfter) then
          FPlanner.FOnPlannerSideDrawAfter(Self, Canvas, ARect, ARow);
      end;
    end;

    if (AColumn = 0) and (ARow = TopRow) and FPlanner.FTopIndicator then
    begin
      R := CellRect(0, 0);
      Canvas.Brush.Color := clInfoBk;
      Canvas.Pen.Color := clBlack;
      Canvas.Pen.Width := 1;
      Canvas.Rectangle(R.Left, R.Top, R.Left + 22, R.Top + 10);
      Canvas.Brush.Color := clBlack;
      Canvas.Polygon([Point(R.Left + 4, R.Top + 2),
        Point(R.Left + 6, R.Top + 6), Point(R.Left + 2, R.Top + 6)]);
      Canvas.Rectangle(R.Left + 8, R.Top + 5, R.Left + 10, R.Top + 7);
      Canvas.Rectangle(R.Left + 12, R.Top + 5, R.Left + 14, R.Top + 7);
      Canvas.Rectangle(R.Left + 16, R.Top + 5, R.Left + 18, R.Top + 7);
    end;

    if (AColumn = 0) and (ARow = TopRow + VisibleRowCount - 1)
      and FPlanner.FBottomIndicator then
    begin
      Canvas.Brush.Color := clInfoBk;
      Canvas.Pen.Color := clBlack;
      Canvas.Pen.Width := 1;
      R := CellRect(0, ARow);
      Canvas.Rectangle(R.Left, R.Bottom - 10, R.Left + 22, R.Bottom);
      Canvas.Brush.Color := clBlack;
      Canvas.Polygon([Point(R.Left + 4, R.Bottom - 4),
        Point(R.Left + 6, R.Bottom - 8), Point(R.Left + 2, R.Bottom - 8)]);
      Canvas.Rectangle(R.Left + 8, R.Bottom - 5, R.Left + 10, R.Bottom - 3);
      Canvas.Rectangle(R.Left + 12, R.Bottom - 5, R.Left + 14, R.Bottom - 3);
      Canvas.Rectangle(R.Left + 16, R.Bottom - 5, R.Left + 18, R.Bottom - 3);
    end;
  end;

  if (AColumn <> Fixcol) and not ((AColumn = ColCount - 1) and
     (FPlanner.Sidebar.Position = spLeftRight) and FPlanner.Sidebar.Visible) then
  begin
    if (FPlanner.FPositionGap > 0) and FPlanner.GapAtColumn(AColumn)
      and not FPlanner.Sidebar.ShowInPositionGap then
    begin
      Canvas.Pen.Color := FPlanner.GridLineColor;
      Canvas.Pen.Width := 1;

      APlannerItem := FPlanner.Items.FindItem(ARow, AColumn - ColOffset);

      if (APlannerItem <> nil) and FPlanner.ShowOccupiedInPositionGap then
        Canvas.Brush.Color := FPlanner.FTrackColor
      else
        Canvas.Brush.Color := FPlanner.PositionGapColor;

      Canvas.FillRect(Rect(ARect.Left, ARect.Top,
          ARect.Left + FPlanner.FPositionGap, ARect.Bottom));

      ARect.Left := ARect.Left + FPlanner.FPositionGap;

      Canvas.MoveTo(ARect.Left - 1, ARect.Top);
      Canvas.LineTo(ARect.Left - 1, ARect.Bottom);
    end;

    { Draw the normal cells - set BackGround Color }

    ABrush := TBrush.Create;
    FPlanner.GetCellBrush(AColumn - ColOffset, ARow, ABrush);
    CellColor := ABrush.Color;
    CellBrush := ABrush.Style;
    ABrush.Free;

    if FPlanner.CellInCurrTime(ARow, AColumn) then
    begin
      CellColor := FPlanner.FDisplay.ColorCurrent;
      UseColor := True;
    end;

    { Custom cell color }
    if (AColumn - ColOffset < FColorList.Count) and (AColumn - ColOffset >= 0)
    {and FPlanner.ShowSelection} and (ARow < NumColors) and not UseColor then
    begin
      PlannerColorArrayPointer := FColorList.Items[AColumn - ColOffset];
      if PlannerColorArrayPointer^[ARow].Color <> clNone then
        CellColor := PlannerColorArrayPointer^[ARow].Color;

      if PlannerColorArrayPointer^[ARow].Selected > 0 then
      begin
        CellColor := BlendColor(FPlanner.DisjunctSelectColor, CellColor,
          FPlanner.FSelectBlend);
        UseColor := True;
      end;
    end;

    if (gdSelected in AState) and FPlanner.ShowSelection then
    begin
      CellBrush := bsSolid;
      // do color blend
      CellColor := BlendColor(FPlanner.FSelectColor, CellColor,
        FPlanner.FSelectBlend);
    end;

    Canvas.Brush.Color := CellColor;

    if Assigned(FPlanner.OnPlannerBkgProp) then
    begin
      FPlanner.OnPlannerBkgProp(FPlanner, ARow, AColumn, Canvas.Brush, nil);
      CellColor := Canvas.Brush.Color;
    end;


    { Nr of Items at cell }
    NumberOfConflicts := FPlanner.Items.NumItem(ARow, ARow + 1,
      AColumn - ColOffset);

    R := ARect;

    BottomPen := TPen.Create;
    BottomPen.Assign(Canvas.Pen);

    BottomPen.Width := 1;
    BottomPen.Color := FPlanner.GridLineColor;

    if (FPlanner.Mode.PlannerType = plHalfDayPeriod) and
      (FPlanner.Mode.FullHalfDay) and not Odd(ARow) then
    begin
      BottomPen.Color := CellColor;
    end;

    if (FPlanner.Mode.PlannerType = plDay) then
    begin
      if ((ARow + 1 + FPlanner.Display.DisplayStart)
          * FPlanner.Display.DisplayUnit mod 60 = 0) then
        BottomPen.Color := FPlanner.Display.HourLineColor;
    end;

    if Assigned(FPlanner.FOnPlannerBottomLine) then
      FPlanner.FOnPlannerBottomLine(Self, ARow, AColumn, BottomPen);

    { Draw Items / cell background }

    // if background item, draw first here
    APlannerItem := FPlanner.Items.FindBackground(ARow, AColumn - ColOffset);

    if Assigned(APlannerItem) then
    begin
      NRect.Top := ARect.Top - ((ARow - APlannerItem.ItemBegin) *
          (ARect.Bottom - ARect.Top));
      NRect.Bottom := ARect.Bottom + ((APlannerItem.ItemEnd - ARow - 1) *
          (ARect.Bottom - ARect.Top));
      NRect.Left := ARect.Left;
      NRect.Right := ARect.Right;

      RGN := CreateRectRgn(ARect.Left, ARect.Top, ARect.Right, ARect.Bottom);
      SelectClipRgn(Canvas.Handle, RGN);

      if AColumn > 0 then
        selbkg := FPlanner.Selected[AColumn - 1, ARow]
      else
        selbkg := False;

      PaintItemCol(Canvas, NRect, APlannerItem, False,
        (gdSelected in AState) or selbkg);

      // draw bottom line for background item if required
      if ARow = APlannerItem.ItemEnd - 1 then
      begin
        Canvas.Pen.Assign(BottomPen);
        Canvas.MoveTo(ARect.Left, ARect.Bottom - 1);
        Canvas.LineTo(ARect.Right, ARect.Bottom - 1);
      end;

      APlannerItem.Repainted := False;

      SelectClipRgn(Canvas.Handle, 0);
      DeleteObject(RGN);

      // make sure overlapping items are repainted  afterwards
      FPlanner.Items.ClearSelectedRepaints(ARow, AColumn - ColOffset);
    end;

    BkgFlag := Assigned(APlannerItem);
    for SubIndex := 1 to NumberOfConflicts.Y do
    begin
      ARect := R;
      M := (ARect.Right - ARect.Left) div NumberOfConflicts.Y;
      ARect.Left := ARect.Left + (SubIndex - 1) * M;

      //      if SubIndex = NumberOfConflicts.Y then
      //        ARect.Right := r.Right
      //      else
      ARect.Right := ARect.Left + M;

      APlannerItem := FPlanner.Items.FindItemIndex(ARow, AColumn - ColOffset,
        SubIndex - 1);

      // found item
      if (APlannerItem <> nil) then
      begin
        NRect.Top := ARect.Top - ((ARow - APlannerItem.ItemBegin) *
            (ARect.Bottom - ARect.Top));
        NRect.Bottom := ARect.Bottom + ((APlannerItem.ItemEnd - ARow - 1) *
            (ARect.Bottom - ARect.Top));

        NRect.Left := ARect.Left;
        NRect.Right := ARect.Right;

        if (APlannerItem.Shape = psHexagon) then
        begin
          RectHorzEx(Canvas, ARect, CellColor, FPlanner.Color,
            FPlanner.FGridLineColor, BottomPen.Color, BottomPen.Width,
            CellBrush);
          APlannerItem.Repainted := False;
        end;

        if ((APlannerItem.Shape in [
{$IFDEF TMSSKINS}
            psSkin,
{$ENDIF}
            psRounded, psHexagon]) and ((APlannerItem.ItemBegin = ARow) or
              (APlannerItem.ItemEnd = ARow))) or (APlannerItem.Shape = psTool)
          then
        begin
          RectHorzEx(Canvas, ARect, CellColor, FPlanner.Color,
            FPlanner.FGridLineColor, BottomPen.Color, BottomPen.Width,
            CellBrush);
          APlannerItem.Repainted := False;
        end;

        // do precise time based adaption here
        if FPlanner.DrawPrecise then
        begin
          if FPlanner.Mode.PlannerType = plTimeLine then
          begin
            FPlanner.CellToAbsTime(APlannerItem.ItemBegin, dts, dte);
            delta := 0;
          end
          else
          begin
            delta := APlannerItem.ItemBeginPrecis - ((APlannerItem.ItemBegin + FPlanner.Display.DisplayStart)
                * FPlanner.Display.DisplayUnit);
            delta := Round(delta / FPlanner.Display.DisplayUnit * FPlanner.Display.DisplayScale);
          end;

          if (delta > 0) then
          begin
            NumI := FPlanner.Items.ItemsAtCell(APlannerItem.ItemBegin, APlannerItem.ItemBegin, APlannerItem.ItemPos);
            if NumI = 1 then
            begin
              if (APlannerItem.ItemBegin >= Selection.Top) and
                (APlannerItem.ItemBegin <= Selection.Bottom) and
                (APlannerItem.ItemPos + ColOffset >= Selection.Left) and
                (APlannerItem.ItemPos + ColOffset <= Selection.Right) then
                Canvas.Brush.Color := FPlanner.SelectColor
              else
              begin
                cb := FPlanner.GetCellColorCol(AColumn - ColOffset, APlannerItem.ItemBegin, UseColor);
                Canvas.Brush.Color := cb.Color;
                Canvas.Brush.Style := cb.BrushStyle;
              end;

              Canvas.Pen.Color := Canvas.Brush.Color;
              Canvas.Rectangle(NRect.Left - 1, NRect.Top, NRect.Right - 1, NRect.Top + delta);
            end;
          end;

          NRect.Top := NRect.Top + delta;

          if FPlanner.Mode.PlannerType = plTimeLine then
          begin
            FPlanner.CellToAbsTime(APlannerItem.ItemBegin, dts, dte);
            delta := 0;
          end
          else
          begin
            delta := ((APlannerItem.ItemEnd + FPlanner.Display.DisplayStart)
                * FPlanner.Display.DisplayUnit) - APlannerItem.ItemEndPrecis;
            delta := Round(delta / FPlanner.Display.DisplayUnit * FPlanner.Display.DisplayScale);
          end;

          if delta > 0 then
          begin
            Inc(delta);

            if (APlannerItem.ItemEnd >= Selection.Top) and
              (APlannerItem.ItemEnd <= Selection.Bottom) then
              Canvas.Brush.Color := FPlanner.SelectColor
            else
              Canvas.Brush.Color := FPlanner.GetCellColorCol(AColumn - ColOffset, APlannerItem.ItemEnd, UseColor).Color;

            Canvas.Brush.Color := CellColor;
            Canvas.Pen.Color := Canvas.Brush.Color;
            Canvas.Rectangle(NRect.Left - 1, NRect.Bottom - delta, NRect.Right - 1, NRect.Bottom - 1);
            Canvas.Pen.Color := FPlanner.GridLineColor;
            Canvas.MoveTo(NRect.Left, NRect.Bottom - 1);
            Canvas.LineTo(NRect.Right, NRect.Bottom - 1);
          end;

          NRect.Bottom := NRect.Bottom - delta;
        end;

        RGN := 0;
        if APlannerItem.Shape = psTool then
        begin
          RGN := CreateRectRgn(R.Left, R.Top, R.Right, R.Bottom);
          SelectClipRgn(Canvas.Handle, RGN);
        end;

        PaintItemCol(Canvas, NRect, APlannerItem, False, True);

        if APlannerItem.Shape = psTool then
        begin
          SelectClipRgn(Canvas.Handle, 0);
          DeleteObject(RGN);
        end;
        // blend background items with selection here
        if (gdSelected in AState)
          and APlannerItem.Background and FPlanner.SelectBackground then
        begin
          BMP := TBitmap.Create;
          try
            BMP.Width := NRect.Right - NRect.Left;
            BMP.Height := NRect.Bottom - NRect.Top;

            BMP.Canvas.Brush.Color := FPlanner.SelectColor;
            BMP.Canvas.Rectangle(0, 0, BMP.Width, BMP.Height);

            Canvas.CopyMode := cmSrcAnd;
            Canvas.Draw(NRect.Left, NRect.Top, BMP);
          finally
            BMP.Free;
          end;
        end;

        if FPlanner.TrackOnly then
        begin
          ARect.Right := ARect.Left + FPlanner.TrackWidth + FPlanner.ItemGap;
        end;

        if not(APlannerItem.Background and not APlannerItem.AllowOverlap) then
          ARect.Left := ARect.Right - FPlanner.FItemGap
        else
          ARect.Left := ARect.Right;

        // Item found, paint only extra rect at Right
        if (not APlannerItem.Background or (SubIndex > 1)) and not BkgFlag then
        begin
          NRect := ARect;
          NRect.Left := ARect.Right - FPlanner.FItemGap;

          if SubIndex = NumberOfConflicts.Y then
            ARect.Right := R.Right + 1;

          if FPlanner.TrackOnly then
          begin
            NRect.Right := NRect.Left + M - FPlanner.TrackWidth;
          end;

          if (SubIndex = NumberOfConflicts.Y) and (SubIndex > 1) then
            NRect.Right := R.Right;

          if (not FPlanner.Background.Bitmap.Empty) and not
            (gdSelected in AState) and not UseColor and FPlanner.IsActive(ARow, AColumn - 1) then
          begin
            if FPlanner.Background.Display = bdTile then
            begin
              DrawWallPaperTile(AColumn, ARow, NRect, NRect.Left - R.Left, 0,
                CellColor);
              RectHorzEx(Canvas, NRect, clNone, FPlanner.Color,
                FPlanner.FGridLineColor, BottomPen.Color, BottomPen.Width,
                CellBrush);
            end
            else
            begin
              RectHorzEx(Canvas, NRect, CellColor, FPlanner.Color,
                FPlanner.FGridLineColor, BottomPen.Color, BottomPen.Width,
                CellBrush);
              DrawWallPaperFixed(NRect, NRect.Left - R.Left, 0, CellColor);
              RectHorzEx(Canvas, NRect, clNone, FPlanner.Color,
                FPlanner.FGridLineColor, BottomPen.Color, BottomPen.Width,
                CellBrush);
            end;
          end
          else
          begin
            {$IFDEF DELPHIXE2_LVL}
            if (gdSelected in AState) and cellinstyle then
            begin
              LDetails := LStyle.GetElementDetails(tgCellSelected);

              SaveIndex := SaveDC(Canvas.Handle);
              try
                LStyle.DrawElement(Canvas.Handle, LDetails, NRect, NRect);
              finally
                RestoreDC(Canvas.Handle, SaveIndex);
              end;
            end
            else
            {$ENDIF}
            begin
              Canvas.Pen.Style := BottomPen.Style;
              RectHorzEx(Canvas, NRect, CellColor, FPlanner.Color, CellColor,
                BottomPen.Color, BottomPen.Width, CellBrush);
              Canvas.Pen.Style := psSolid;
            end;
          end;

          if (AColumn > 0) and (Assigned(FPlanner.OnPlannerBkgDraw)) then
          begin
            FPlanner.OnPlannerBkgDraw(FPlanner, Canvas, NRect, ARow,
              AColumn - 1);
          end;
        end;
      end
      else
      begin
        if not BkgFlag then
        begin
          NRect := ARect;
          if SubIndex > 1 then
            NRect.Left := ARect.Left - 1
          else
            NRect.Left := ARect.Left;

          if SubIndex = NumberOfConflicts.Y then
            NRect.Right := R.Right + 1;

          if (not FPlanner.Background.Bitmap.Empty) and not
            (gdSelected in AState) and not UseColor and FPlanner.IsActive
            (ARow, AColumn - 1) then
          begin
            if FPlanner.Background.Display = bdTile then
            begin
              DrawWallPaperTile(AColumn, ARow, NRect, NRect.Left - R.Left, 0,
                CellColor);
              RectHorzEx(Canvas, NRect, clNone, FPlanner.Color,
                FPlanner.FGridLineColor, BottomPen.Color, BottomPen.Width,
                CellBrush);
            end
            else
            begin
              RectHorzEx(Canvas, NRect, CellColor, FPlanner.Color,
                FPlanner.FGridLineColor, BottomPen.Color, BottomPen.Width,
                CellBrush);
              DrawWallPaperFixed(NRect, NRect.Left - R.Left, 0, CellColor);
              RectHorzEx(Canvas, NRect, clNone, FPlanner.Color,
                FPlanner.FGridLineColor, BottomPen.Color, BottomPen.Width,
                CellBrush);
            end;
          end
          else
          begin
            {$IFDEF DELPHIXE2_LVL}
            if (gdSelected in AState) and cellinstyle then
            begin
              LDetails := LStyle.GetElementDetails(tgCellSelected);

              SaveIndex := SaveDC(Canvas.Handle);
              try
                LStyle.DrawElement(Canvas.Handle, LDetails, NRect, NRect);
              finally
                RestoreDC(Canvas.Handle, SaveIndex);
              end;
            end
            else
            {$ENDIF}
            begin
              Canvas.Pen.Style := BottomPen.Style;
              RectHorzEx(Canvas, NRect, CellColor, FPlanner.Color, CellColor,
                BottomPen.Color, BottomPen.Width, CellBrush);
              Canvas.Pen.Style := psSolid;
            end;
          end;

          if (AColumn > 0) and (Assigned(FPlanner.OnPlannerBkgDraw)) then
          begin
            FPlanner.OnPlannerBkgDraw(FPlanner, Canvas, NRect, ARow,
              AColumn - 1);
          end;
        end;
      end;
    end;

    { Draws line on Top & Bottom of cell if no Items are present }
    if (NumberOfConflicts.X = 0) then
    begin
      if (not FPlanner.Background.Bitmap.Empty) and not(gdSelected in AState)
        and not UseColor and FPlanner.IsActive(ARow, AColumn - 1) then
      begin
        if FPlanner.Background.Display = bdTile then
        begin
          DrawWallPaperTile(AColumn, ARow, ARect, 0, 0, CellColor);
          RectHorzEx(Canvas, ARect, clNone, FPlanner.Color,
            FPlanner.FGridLineColor, BottomPen.Color, BottomPen.Width,
            CellBrush);
        end
        else
        begin
          RectHorzEx(Canvas, ARect, CellColor, FPlanner.Color,
            FPlanner.FGridLineColor, BottomPen.Color, BottomPen.Width,
            CellBrush);
          DrawWallPaperFixed(ARect, 0, 0, CellColor);
          RectHorzEx(Canvas, ARect, clNone, FPlanner.Color,
            FPlanner.FGridLineColor, BottomPen.Color, BottomPen.Width,
            CellBrush);
        end;
      end
      else
      begin
        {$IFDEF DELPHIXE2_LVL}
        if (gdSelected in AState) and cellinstyle then
        begin
          LDetails := LStyle.GetElementDetails(tgCellSelected);

          SaveIndex := SaveDC(Canvas.Handle);
          try
            LStyle.DrawElement(Canvas.Handle, LDetails, ARect, ARect);
          finally
            RestoreDC(Canvas.Handle, SaveIndex);
          end;
        end
        else
        {$ENDIF}
        begin
          Canvas.Pen.Style := BottomPen.Style;
          RectHorzEx(Canvas, ARect, CellColor, FPlanner.Color,
            FPlanner.FGridLineColor, BottomPen.Color, BottomPen.Width,
            CellBrush);
          Canvas.Pen.Style := psSolid;
        end;
      end;
    end;

    BottomPen.Free;

    if (AColumn > 0) and (Assigned(FPlanner.OnPlannerBkgDraw)) then
    begin
      FPlanner.OnPlannerBkgDraw(FPlanner, Canvas, ARect, ARow, AColumn - 1);
    end;

    Canvas.Pen.Color := FPlanner.FGridLineColor;

    RightPen := TPen.Create;
    RightPen.Assign(Canvas.Pen);
    RightPen.Width := 1;

    if Assigned(FPlanner.OnPlannerRightLine) then
      FPlanner.FOnPlannerRightLine(FPlanner, AColumn, ARow, RightPen);

    { Draw cell line at end of cell }
    if RightPen.Color <> clNone then
    begin
      Canvas.Pen.Color := RightPen.Color;
      Canvas.Pen.Width := RightPen.Width;
      Canvas.MoveTo(R.Right - 1, ARect.Top - 1);
      Canvas.LineTo(R.Right - 1, ARect.Bottom - 1);
    end;

    RightPen.Free;
  end;

  Canvas.Font.Assign(OldFont);
  Canvas.Brush.Assign(OldBrush);
  OldFont.Free;
  OldBrush.Free;
end;

procedure TPlannerGrid.DrawCellRow(AColumn, ARow: LongInt; ARect: TRect;
  AState: TGridDrawState);
var
  OldBrush: TBrush;
  OldFont: TFont;
  APlannerItem: TPlannerItem;
  NRect, R: TRect;
  NumberOfConflicts: TPoint;
  CellColor: TColor;
  CellBrush: TBrushStyle;
  FixRow, SubIndex, M: Integer;
  RowOffset, NumI: Integer;
  PlannerColorArrayPointer: PPlannerColorArray;
  BottomPen, RightPen: TPen;
  Occupied: Boolean;
  ABrush: TBrush;
  BkgFlag: Boolean;
  RGN: THandle;
  delta: Integer;
  dts, dte: TDateTime;
  BMP: TBitmap;
  selbkg,hasbkg: Boolean;
  AColorTo: TColor;
  UseColor: Boolean;
  cb: TCellBrush;
  {$IFDEF DELPHIXE2_LVL}
  LStyle: TCustomStyleServices;
  LDetails: TThemedElementDetails;
  SaveIndex: integer;
  cellinstyle: boolean;
  {$ENDIF}

begin
  RowOffset := FPlanner.FSidebar.FRowOffset;

  if RowOffset = 0 then
    FixRow := RowCount - 1
  else
    FixRow := 0;

  UseColor := false;

  OldFont := TFont.Create;
  OldFont.Assign(Canvas.Font);
  OldBrush := TBrush.Create;
  OldBrush.Assign(Canvas.Brush);

  {$IFDEF DELPHIXE2_LVL}
  cellinstyle := false;
  LStyle := StyleServices;
  if LStyle.Enabled and (LStyle.Name <> 'Windows') and (gdSelected in AState) and FPlanner.FUseVCLStyles then
  begin
    cellinstyle := true;
  end;
  {$ENDIF}

  if (ARow = FixRow) and (FPlanner.Sidebar.Visible) then
  begin
    Canvas.Brush.Color := FPlanner.Sidebar.Background;
    AColorTo := FPlanner.Sidebar.BackgroundTo;

    Canvas.Font.Assign(FPlanner.Sidebar.Font);

    if Assigned(FPlanner.OnPlannerSideProp) then
      FPlanner.OnPlannerSideProp(FPlanner, AColumn, Canvas.Brush, Canvas.Font,
        AColorTo);

    APlannerItem := FPlanner.Items.FindItemIdx(AColumn);

    Occupied := False;

    if (APlannerItem <> nil) and FPlanner.Sidebar.ShowOccupied then
    begin
      Occupied := True;
      Canvas.Brush.Color := FPlanner.Sidebar.Occupied;
      AColorTo := FPlanner.Sidebar.OccupiedTo;
    end;

    if ((AColumn >= Selection.Left) and (AColumn <= Selection.Right) and
        (FPlanner.Sidebar.ActiveColor <> clNone)) then
    begin
      Canvas.Brush.Color := FPlanner.Sidebar.ActiveColor;
      if (AColorTo <> clNone) then
        DrawGradient(Canvas, FPlanner.Sidebar.ActiveColor,
          FPlanner.Sidebar.ActiveColorTo, FPlanner.GradientSteps, ARect, False)
      else
        Canvas.FillRect(ARect);
    end
    else
    begin
      if AColorTo <> clNone then
        DrawGradient(Canvas, Canvas.Brush.Color, AColorTo,
          FPlanner.GradientSteps, ARect, False)
      else
        Canvas.FillRect(ARect);
    end;

    if not FPlanner.Sidebar.Flat then
      Frame3D(Canvas, ARect, clWhite, clGray, 1);

    if FPlanner.Sidebar.Border then
    begin
      if not FPlanner.FUseVCLStyles then
      begin
        Canvas.Pen.Color := clWhite;
        Canvas.MoveTo(ARect.Left, ARect.Top);
        Canvas.LineTo(ARect.Right, ARect.Top);

        if AColumn = FPlanner.FGrid.LeftCol then
        begin
          Canvas.MoveTo(ARect.Left, ARect.Top);
          Canvas.LineTo(ARect.Left, ARect.Bottom);
        end;
      end;

      Canvas.Pen.Color := FPlanner.Sidebar.BorderColor;

      if not FPlanner.FUseVCLStyles then
      begin
        Canvas.MoveTo(ARect.Left, ARect.Bottom - 1);
        Canvas.LineTo(ARect.Right, ARect.Bottom - 1);
      end;

      if AColumn = FPlanner.FGrid.ColCount - 1 then
      begin
        Canvas.MoveTo(ARect.Right - 1, ARect.Top);
        Canvas.LineTo(ARect.Right - 1, ARect.Bottom);
      end;
    end;

    if not(FPlanner.FMode.FPlannerType in [plDay, plTimeLine, plHalfDayPeriod]) then
    begin
      Canvas.Pen.Color := FPlanner.Sidebar.BorderColor;
      Canvas.MoveTo(ARect.Left, ARect.Bottom - 1);
      Canvas.LineTo(ARect.Right - 1, ARect.Bottom - 1);
      Canvas.Pen.Color := FPlanner.Sidebar.SeparatorLineColor;
      Canvas.LineTo(ARect.Right - 1, ARect.Top);
    end;

    R := ARect;

    if (not FPlanner.Sidebar.RotateOnTop) and (FPlanner.FMode.FPlannerType <> plTimeLine) then
      ARect.Left := ARect.Left + 4;

    ARect.Right := ARect.Right - 4;

    ARect.Top := ARect.Top + 1;
    ARect.Bottom := ARect.Bottom - 1;

    Canvas.Pen.Color := FPlanner.Sidebar.SeparatorLineColor;

    if Assigned(FPlanner.OnPlannerSideDraw) then
      FPlanner.OnPlannerSideDraw(FPlanner, Canvas, ARect, AColumn)
    else
    begin
      PaintSideRow(Canvas, ARect, AColumn, ARow, Occupied, False, DefaultColWidth);
      if Assigned(FPlanner.FOnPlannerSideDrawAfter) then
        FPlanner.FOnPlannerSideDrawAfter(Self, Canvas, ARect, AColumn);
    end;

    if (ARow = 0) and (AColumn = LeftCol) and FPlanner.FTopIndicator then
    begin
      Canvas.Brush.Color := clInfoBk;
      Canvas.Pen.Color := clBlack;
      Canvas.Pen.Width := 1;
      Canvas.Rectangle(R.Left, R.Top, R.Left + 22, R.Top + 10);
      Canvas.Brush.Color := clBlack;
      Canvas.Polygon([Point(R.Left + 2, R.Top + 4),
        Point(R.Left + 4, R.Top + 2), Point(R.Left + 4, R.Top + 6)]);
      Canvas.Rectangle(R.Left + 8, R.Top + 5, R.Left + 10, R.Top + 7);
      Canvas.Rectangle(R.Left + 12, R.Top + 5, R.Left + 14, R.Top + 7);
      Canvas.Rectangle(R.Left + 16, R.Top + 5, R.Left + 18, R.Top + 7);
    end;

    if (ARow = 0) and (AColumn = LeftCol + VisibleColCount - 1)
      and FPlanner.FBottomIndicator then
    begin
      Canvas.Brush.Color := clInfoBk;
      Canvas.Pen.Color := clBlack;
      Canvas.Pen.Width := 1;
      R := CellRect(AColumn, 0);
      R.Bottom := R.Top + 10;
      // Canvas.Rectangle(r.Left,r.Top,r.Left + 22, r.Top + 10);

      Canvas.Rectangle(R.Right - 24, R.Top, R.Right - 2, R.Top + 10);
      Canvas.Brush.Color := clBlack;
      Canvas.Polygon([Point(R.Right - 6, R.Top + 4),
        Point(R.Right - 8, R.Top + 2), Point(R.Right - 8, R.Top + 6)]);
      Canvas.Rectangle(R.Right - 10, R.Bottom - 5, R.Right - 12, R.Bottom - 3);
      Canvas.Rectangle(R.Right - 14, R.Bottom - 5, R.Right - 16, R.Bottom - 3);
      Canvas.Rectangle(R.Right - 18, R.Bottom - 5, R.Right - 20, R.Bottom - 3);
    end;

  end
  else
  begin
    { Determine the cell background Color first }

    ABrush := TBrush.Create;
    FPlanner.GetCellBrush(ARow - RowOffset, AColumn, ABrush);
    CellColor := ABrush.Color;
    CellBrush := ABrush.Style;
    ABrush.Free;

    if FPlanner.CellInCurrTime(AColumn, ARow) then
      CellColor := FPlanner.FDisplay.ColorCurrent;

    if (ARow - RowOffset < FColorList.Count) and (ARow - RowOffset >= 0)
    {and FPlanner.ShowSelection} and (AColumn < NumColors) then
    begin
      PlannerColorArrayPointer := FColorList.Items[ARow - RowOffset];
      if PlannerColorArrayPointer^[AColumn].Color <> clNone then
        CellColor := PlannerColorArrayPointer^[AColumn].Color;

      if PlannerColorArrayPointer^[AColumn].Selected > 0 then
      begin
        CellColor := BlendColor(FPlanner.DisjunctSelectColor, CellColor,
          FPlanner.FSelectBlend);
        UseColor := true;
      end;
    end;

    if (gdSelected in AState) and FPlanner.ShowSelection then
    begin
      CellColor := BlendColor(FPlanner.FSelectColor, CellColor,
        FPlanner.FSelectBlend);
    end;

    { End of setting cell background Color }
    NumberOfConflicts := FPlanner.Items.NumItem(AColumn, AColumn + 1, ARow - RowOffset);

    R := ARect;

    BottomPen := TPen.Create;
    BottomPen.Assign(Canvas.Pen);

    BottomPen.Width := 1;
    BottomPen.Color := FPlanner.GridLineColor;

    if (FPlanner.Mode.PlannerType = plHalfDayPeriod) and
      (FPlanner.Mode.FullHalfDay) and not Odd(AColumn) then
    begin
      BottomPen.Color := CellColor;
    end;

    if (FPlanner.Mode.PlannerType = plDay) then
    begin
      if ((AColumn + 1 + FPlanner.Display.DisplayStart) * FPlanner.Display.DisplayUnit mod 60 = 0) then
        BottomPen.Color := FPlanner.Display.HourLineColor;
    end;

    if Assigned(FPlanner.FOnPlannerBottomLine) then
      FPlanner.FOnPlannerBottomLine(Self, AColumn, ARow, BottomPen);

    Canvas.Brush.Color := CellColor;

    if Assigned(FPlanner.OnPlannerBkgProp) then
    begin
      FPlanner.OnPlannerBkgProp(FPlanner, AColumn, ARow - 1, Canvas.Brush, nil);
      CellColor := Canvas.Brush.Color;
    end;

    // if background item, draw first here
    APlannerItem := FPlanner.Items.FindBackground(AColumn, ARow - RowOffset);
    hasbkg := Assigned(APlannerItem);

    if hasbkg then
    begin
      NRect.Left := ARect.Left - ((AColumn - APlannerItem.ItemBegin) * (ARect.Right - ARect.Left));
      NRect.Right := ARect.Right + ((APlannerItem.ItemEnd - AColumn - 1) * (ARect.Right - ARect.Left));
      NRect.Top := ARect.Top;
      NRect.Bottom := ARect.Bottom;

      RGN := CreateRectRgn(ARect.Left, ARect.Top, ARect.Right, ARect.Bottom);
      SelectClipRgn(Canvas.Handle, RGN);

      if ARow > 0 then
        selbkg := FPlanner.Selected[AColumn, ARow - 1]
      else
        selbkg := False;

      PaintItemRow(Canvas, NRect, APlannerItem, False, (gdSelected in AState) or selbkg);

      // draw bottom line for background item if required
      if ARow = APlannerItem.ItemEnd - 1 then
      begin
        Canvas.Pen.Assign(BottomPen);
        Canvas.MoveTo(ARect.Right - 1, ARect.Top);
        Canvas.LineTo(ARect.Right - 1, ARect.Bottom - 1);
      end;

      APlannerItem.Repainted := False;

      SelectClipRgn(Canvas.Handle, 0);
      DeleteObject(RGN);

      // make sure overlapping items are repainted  afterwards
      FPlanner.Items.ClearSelectedRepaints(AColumn, ARow - RowOffset);
    end;

    BkgFlag := Assigned(APlannerItem);

    for SubIndex := 1 to NumberOfConflicts.Y do
    begin
      ARect := R;
      M := (ARect.Bottom - ARect.Top) div (NumberOfConflicts.Y);
      ARect.Top := ARect.Top + (SubIndex - 1) * M;

      if SubIndex = NumberOfConflicts.Y then
        ARect.Bottom := R.Bottom
      else
        ARect.Bottom := ARect.Top + M;

      APlannerItem := FPlanner.Items.FindItemIndex(AColumn, ARow - RowOffset, SubIndex - 1);

      if (APlannerItem <> nil) then
      begin
        NRect.Left := ARect.Left - ((AColumn - APlannerItem.ItemBegin) * (ARect.Right - ARect.Left));
        NRect.Right := ARect.Right + ((APlannerItem.ItemEnd - AColumn - 1) * (ARect.Right - ARect.Left));
        NRect.Top := ARect.Top + 1;
        NRect.Bottom := ARect.Bottom;

        if ((APlannerItem.Shape in [psRounded, psHexagon
{$IFDEF TMSSKINS}
            , psSkin
{$ENDIF}
            ]) and ((APlannerItem.ItemBegin = AColumn) or
              (APlannerItem.ItemEnd = AColumn + 1))) or ((APlannerItem.VMargin > 0) and not hasbkg) or
          (APlannerItem.Shape = psTool) then
        begin
          if BottomPen.Style = psClear then
            RectVertEx(Canvas, ARect, CellColor, FPlanner.Color, clNone,
              BottomPen.Width, CellBrush)
          else
            RectVertEx(Canvas, ARect, CellColor, FPlanner.Color, BottomPen.Color,
              BottomPen.Width, CellBrush);

          APlannerItem.Repainted := False;
        end;

        if FPlanner.DrawPrecise then
        begin

          if FPlanner.Mode.PlannerType = plTimeLine then
          begin
            FPlanner.CellToAbsTime(APlannerItem.ItemBegin, dts, dte);
            delta := 0;
          end
          else
          begin
            delta := APlannerItem.ItemBeginPrecis - ((APlannerItem.ItemBegin + FPlanner.Display.DisplayStart)
                * FPlanner.Display.DisplayUnit);
            delta := Round(delta / FPlanner.Display.DisplayUnit * FPlanner.Display.DisplayScale);
          end;

          if delta > 0 then
          begin
            NumI := FPlanner.Items.ItemsAtCell(APlannerItem.ItemBegin, APlannerItem.ItemBegin, APlannerItem.ItemPos);

            if NumI = 1 then
            begin
              if (APlannerItem.ItemBegin >= Selection.Left) and
                (APlannerItem.ItemBegin <= Selection.Right) and
                (APlannerItem.ItemPos + RowOffset >= Selection.Top) and
                (APlannerItem.ItemPos + RowOffset <= Selection.Bottom) then
              begin
                Canvas.Brush.Color := FPlanner.SelectColor;
              end
              else
              begin
                cb := FPlanner.GetCellColorCol(ARow - RowOffset, APlannerItem.ItemBegin, UseColor);
                Canvas.Brush.Color := cb.Color;
                Canvas.Brush.Style := cb.BrushStyle;
              end;

              Canvas.Pen.Color := Canvas.Brush.Color;
              Canvas.Rectangle(NRect.Left, NRect.Top, NRect.Left + delta, NRect.Bottom);
            end;
          end;

          NRect.Left := NRect.Left + delta;

          delta := ((APlannerItem.ItemEnd + FPlanner.Display.DisplayStart)
              * FPlanner.Display.DisplayUnit) - APlannerItem.ItemEndPrecis;
          delta := Round(delta / FPlanner.Display.DisplayUnit * FPlanner.Display.DisplayScale);

          if delta > 0 then
          begin
            Inc(delta);

            Canvas.Brush.Color := CellColor;
            Canvas.Pen.Color := Canvas.Brush.Color;
            Canvas.Rectangle(NRect.Right - delta, NRect.Top, NRect.Right - 1, NRect.Bottom);

            Canvas.Pen.Color := FPlanner.GridLineColor;
            Canvas.MoveTo(NRect.Right - 1, NRect.Top);
            Canvas.LineTo(NRect.Right - 1, NRect.Bottom);
          end;

          NRect.Right := NRect.Right - delta;
        end;

        NRect.Top := NRect.Top - 1;
        PaintItemRow(Canvas, NRect, APlannerItem, False, True);
        NRect.Top := NRect.Top + 1;

        // blend background items with selection here
        if (gdSelected in AState) and APlannerItem.Background and FPlanner.SelectBackground then
        begin
          BMP := TBitmap.Create;
          try
            BMP.Width := NRect.Right - NRect.Left;
            BMP.Height := NRect.Bottom - NRect.Top;

            BMP.Canvas.Brush.Color := FPlanner.SelectColor;
            BMP.Canvas.Rectangle(0, 0, BMP.Width, BMP.Height);

            Canvas.CopyMode := cmSrcAnd;
            Canvas.Draw(NRect.Left, NRect.Top, BMP);
          finally
            BMP.Free;
          end;
        end;

        NRect.Left := ARect.Left;
        NRect.Right := ARect.Right;

        if FPlanner.TrackOnly then
        begin
          if SubIndex = NumberOfConflicts.Y then
          // last item of conflicting items
            ARect.Bottom := ARect.Top + FPlanner.TrackWidth +
              FPlanner.ItemGap + 1
          else
            ARect.Bottom := ARect.Top + FPlanner.TrackWidth + FPlanner.ItemGap
        end;

        if APlannerItem.Background then
          NRect.Top := ARect.Bottom
        else
        if not (APlannerItem.Background and not APlannerItem.AllowOverlap) then
          NRect.Top := ARect.Bottom - FPlanner.FItemGap - 1
        else
          NRect.Top := ARect.Bottom - 1;

        if FPlanner.TrackOnly then
        begin
          if SubIndex = NumberOfConflicts.Y then
          // last item of conflicting items
            NRect.Bottom := NRect.Top + M - FPlanner.TrackWidth + 2
          else
            NRect.Bottom := NRect.Top + M - FPlanner.TrackWidth + 1;
        end
        else
        begin
          if SubIndex = NumberOfConflicts.Y then
            NRect.Bottom := ARect.Bottom + 1
          else
            NRect.Bottom := ARect.Bottom;
        end;

        if not BkgFlag then
        begin
          if (not FPlanner.Background.Bitmap.Empty) and not UseColor and not (gdSelected in AState) and FPlanner.IsActive(AColumn, ARow) then
          begin
            if FPlanner.Background.Display = bdTile then
            begin
              DrawWallPaperTile(AColumn, ARow, NRect, 0, NRect.Top - R.Top,
                CellColor);
              RectVertEx(Canvas, NRect, clNone, FPlanner.Color,
                BottomPen.Color, BottomPen.Width, CellBrush);
            end
            else
            begin
              RectVertEx(Canvas, NRect, CellColor, FPlanner.Color,
                BottomPen.Color, BottomPen.Width, CellBrush);
              DrawWallPaperFixed(NRect, 0, 0, CellColor);
              RectVertEx(Canvas, NRect, clNone, FPlanner.Color,
                BottomPen.Color, BottomPen.Width, CellBrush);
            end;
          end
          else
          begin
            {$IFDEF DELPHIXE2_LVL}
            if (gdSelected in AState) and cellinstyle then
            begin
              LDetails := LStyle.GetElementDetails(tgCellSelected);

              SaveIndex := SaveDC(Canvas.Handle);
              try
                LStyle.DrawElement(Canvas.Handle, LDetails, NRect, NRect);
              finally
                RestoreDC(Canvas.Handle, SaveIndex);
              end;
            end
            else
            {$ENDIF}
            begin
              Canvas.Pen.Style := BottomPen.Style;
              RectVertEx(Canvas, NRect, CellColor, FPlanner.Color,
                BottomPen.Color, BottomPen.Width, CellBrush);
              Canvas.Pen.Style := psSolid;
            end;
          end;

          if (ARow > 0) and (Assigned(FPlanner.OnPlannerBkgDraw)) then
          begin
            FPlanner.OnPlannerBkgDraw(FPlanner, Canvas, NRect, AColumn,
              ARow - 1);
          end;
        end;
      end
      else
      begin
        if not BkgFlag then
        begin
          if (not FPlanner.Background.Bitmap.Empty) and not UseColor and not
            (gdSelected in AState) and FPlanner.IsActive(AColumn, ARow) then
          begin
            if FPlanner.Background.Display = bdTile then
            begin
              DrawWallPaperTile(AColumn, ARow, ARect, 0, ARect.Top - R.Top,
                CellColor);
              RectVertEx(Canvas, ARect, clNone, FPlanner.Color,
                BottomPen.Color, BottomPen.Width, CellBrush);
            end
            else
            begin
              RectVertEx(Canvas, ARect, CellColor, FPlanner.Color,
                BottomPen.Color, BottomPen.Width, CellBrush);
              DrawWallPaperFixed(ARect, 0, 0, CellColor);
              RectVertEx(Canvas, ARect, clNone, FPlanner.Color,
                BottomPen.Color, BottomPen.Width, CellBrush);
            end;
          end
          else
          begin
            {$IFDEF DELPHIXE2_LVL}
            if (gdSelected in AState) and cellinstyle then
            begin
              LDetails := LStyle.GetElementDetails(tgCellSelected);

              SaveIndex := SaveDC(Canvas.Handle);
              try
                LStyle.DrawElement(Canvas.Handle, LDetails, ARect, ARect);
              finally
                RestoreDC(Canvas.Handle, SaveIndex);
              end;
            end
            else
            {$ENDIF}
            begin
              Canvas.Pen.Style := BottomPen.Style;
              RectVertEx(Canvas, ARect, CellColor, FPlanner.Color,
                BottomPen.Color, BottomPen.Width, CellBrush);
              Canvas.Pen.Style := psSolid;
            end;
          end;

          if (ARow > 0) and (Assigned(FPlanner.OnPlannerBkgDraw)) then
          begin
            FPlanner.OnPlannerBkgDraw(FPlanner, Canvas, ARect, AColumn,
              ARow - 1);
          end;
        end;
      end;
    end;

    if (NumberOfConflicts.Y = 0) and not BkgFlag then
    begin
      if (not FPlanner.Background.Bitmap.Empty) and not UseColor and not(gdSelected in AState)
        and FPlanner.IsActive(AColumn, ARow) then
      begin
        if FPlanner.Background.Display = bdTile then
        begin
          DrawWallPaperTile(AColumn, ARow, ARect, 0, 0, CellColor);
          RectVertEx(Canvas, ARect, clNone, FPlanner.Color, BottomPen.Color,
            BottomPen.Width, CellBrush);
        end
        else
        begin
          RectVertEx(Canvas, ARect, CellColor, FPlanner.Color, BottomPen.Color,
            BottomPen.Width, CellBrush);
          DrawWallPaperFixed(ARect, 0, 0, CellColor);
          RectVertEx(Canvas, ARect, clNone, FPlanner.Color, BottomPen.Color,
            BottomPen.Width, CellBrush);
        end;
      end
      else
      begin
        {$IFDEF DELPHIXE2_LVL}
        if (gdSelected in AState) and cellinstyle then
        begin
          LDetails := LStyle.GetElementDetails(tgCellSelected);

          SaveIndex := SaveDC(Canvas.Handle);
          try
            LStyle.DrawElement(Canvas.Handle, LDetails, ARect, ARect);
          finally
            RestoreDC(Canvas.Handle, SaveIndex);
          end;
        end
        else
        {$ENDIF}
        begin
          Canvas.Pen.Style := BottomPen.Style;
          RectVertEx(Canvas, ARect, CellColor, FPlanner.Color, BottomPen.Color,
            BottomPen.Width, CellBrush);
          Canvas.Pen.Style := psSolid;
        end;
      end;

      if (ARow > 0) and (Assigned(FPlanner.OnPlannerBkgDraw)) then
      begin
        FPlanner.OnPlannerBkgDraw(FPlanner, Canvas, ARect, AColumn, ARow - 1);
      end;
    end;

    BottomPen.Free;

    ARect := R;

    Canvas.Pen.Color := FPlanner.FGridLineColor;

    RightPen := TPen.Create;
    RightPen.Assign(Canvas.Pen);
    RightPen.Width := 1;

    if Assigned(FPlanner.OnPlannerRightLine) then
      FPlanner.FOnPlannerRightLine(FPlanner, ARow, AColumn, RightPen);

    if (RightPen.Color <> clNone) then
    begin
      Canvas.Pen.Width := RightPen.Width;
      Canvas.Pen.Color := RightPen.Color;
      Canvas.MoveTo(ARect.Left, ARect.Top);
      Canvas.LineTo(ARect.Right, ARect.Top);
      if (ARow = RowCount - 1) then
      begin
        Canvas.MoveTo(ARect.Left, ARect.Bottom - 1);
        Canvas.LineTo(ARect.Right, ARect.Bottom - 1);
      end;
    end;

    RightPen.Free;
  end;

  Canvas.Font.Assign(OldFont);
  Canvas.Brush.Assign(OldBrush);
  OldFont.Free;
  OldBrush.Free;
end;

procedure TPlannerGrid.DragDrop(Source: TObject; X, Y: Integer);
var
  Point: TPoint;
  ColOffset, RowOffset: Integer;
  GridRect: TRect;
  GridCoord: TGridCoord;
  APlannerItem: TPlannerItem;
begin

  ColOffset := FPlanner.FSidebar.FColOffset;
  RowOffset := FPlanner.FSidebar.FRowOffset;

  GridCoord := MouseCoord(X, Y);
  GridRect := CellRectEx(GridCoord.X, GridCoord.Y);

  if FPlanner.Sidebar.Orientation = soVertical then
  begin
    APlannerItem := FPlanner.Items.FindItemPos(GridCoord.Y - RowOffset,
      GridCoord.X - ColOffset, X - GridRect.Left);
  end
  else
  begin
    APlannerItem := FPlanner.Items.FindItemPos(GridCoord.X - ColOffset,
      GridCoord.Y - RowOffset, Y - GridRect.Top);
  end;

  if Assigned(FPlanner.FOnDragDrop) then
    FPlanner.FOnDragDrop(FPlanner, Source, X, Y);

  Point := FPlanner.XYToCell(X, Y);

  if Assigned(FPlanner.FOnDragDropCell) then
  begin
    FPlanner.FOnDragDropCell(FPlanner, Source, Point.X, Point.Y);
  end;

  if Assigned(APlannerItem) then
  begin
    if Assigned(FPlanner.FOnDragDropItem) then
      FPlanner.FOnDragDropItem(FPlanner, Source, GridCoord.X,
        GridCoord.Y - RowOffset, APlannerItem);
  end;

  if Source = FPlanner.FHeader then
  begin
    FPlanner.FHeader.FDragItem.InHeader := False;
    if FPlanner.Sidebar.Position = spLeft then
    begin
      FPlanner.FHeader.FDragItem.ItemBegin := Point.Y;
      FPlanner.FHeader.FDragItem.ItemEnd := Point.Y + 1;
      FPlanner.FHeader.FDragItem.ItemPos := Point.X;
    end
    else
    begin
      FPlanner.FHeader.FDragItem.ItemBegin := Point.X;
      FPlanner.FHeader.FDragItem.ItemEnd := Point.X + 1;
      FPlanner.FHeader.FDragItem.ItemPos := Point.Y;
    end;

    FPlanner.FHeader.FDragItem.Update;

    Exit;
  end;
  FPlanner.HeaderControl.Invalidate;
end;

procedure TPlannerGrid.DragOver(Source: TObject; X, Y: Integer;
  State: TDragState; var Accept: Boolean);
var
  GridCoord: TGridCoord;
  APlannerItem: TPlannerItem;
  //ColOffset, RowOffset: Integer;
  GridRect: TRect;
begin
  Accept := False;
  inherited;

  GridCoord := MouseCoord(X, Y);

  if (Source = FPlanner.FHeader) then
    Accept := True;

  if Assigned(FPlanner.FOnDragOver) then
  begin
    Accept := True;
    FPlanner.FOnDragOver(FPlanner, Source, X, Y, State, Accept);
  end;

  if Assigned(FPlanner.FOnDragOverCell) then
  begin
    Accept := True;
    if (FPlanner.FSidebar.Visible) and (FPlanner.FSidebar.Position in [spLeft,
      spLeftRight]) then
      GridCoord.X := GridCoord.X - 1;
    if (FPlanner.FSidebar.Visible) and (FPlanner.Sidebar.Position = spTop) then
      GridCoord.Y := GridCoord.Y - 1;
    FPlanner.FOnDragOverCell(FPlanner, Source, GridCoord.X, GridCoord.Y, State,
      Accept);
  end;

  //ColOffset := FPlanner.FSidebar.FColOffset;
  //RowOffset := FPlanner.FSidebar.FRowOffset;

  GridCoord := MouseCoord(X, Y);
  GridRect := CellRectEx(GridCoord.X, GridCoord.Y);

  APlannerItem := FPlanner.XYToItem(X,Y);

  if Assigned(APlannerItem) then
  begin
    if Assigned(FPlanner.FOnDragOverItem) then
      FPlanner.FOnDragOverItem(Self, Source, GridCoord.X, GridCoord.Y,
        APlannerItem, State, Accept);
  end;
end;

function TPlannerGrid.GetColEx: Integer;
begin
  Result := inherited Col;
end;

function TPlannerGrid.GetHScrollSize: Integer;
begin
  Result := 0;

  if (VisibleRowCount < RowCount)
  {and not (Scrollbars in [ssNone, ssHorizontal])} then
  begin
    Result := GetSystemMetrics(SM_CXVSCROLL);
  end;
end;

function TPlannerGrid.GetRowEx: Integer;
begin
  Result := inherited Row;
end;

function TPlannerGrid.GetVScrollSize: Integer;
begin
  Result := 0;
  if (VisibleColCount < ColCount)
  {and not (Scrollbars in [ssNone, ssVertical])} then
  begin
    Result := GetSystemMetrics(SM_CYHSCROLL);
  end;
end;

procedure TPlannerGrid.UpdatePositions;
var
  ColumnIndex: Integer;
  ItemIndex: Integer;
  SectionIndex, delta: Integer;
  ColumnWidth, j: Integer;
  ColOffset, RowOffset: Integer;
  poswi: SmallInt;

begin
  if csLoading in FPlanner.ComponentState then
    Exit;

  if FPlanner.Positions = 0 then
    Exit;

  ColOffset := FPlanner.FSidebar.FColOffset;
  RowOffset := FPlanner.FSidebar.FRowOffset;

  //  if FPlanner.Flat then
  //    bw := 1
  //  else
  //    bw := 5;
  //
  //  delta := 0;

  if FPlanner.Sidebar.Orientation = soVertical then
  begin
    if ColCount < FPlanner.Positions + ColOffset then
      ColCount := FPlanner.Positions + ColOffset;

    if FPlanner.Sidebar.Visible then
      ColumnWidth := FPlanner.FSidebar.Width
    else
      ColumnWidth := 1;

    case FPlanner.Sidebar.Position of
      spRight:
        begin
          ColumnWidth := ClientWidth - ColumnWidth;
          delta := ColumnWidth mod FPlanner.Positions;
          ColumnWidth := ColumnWidth div FPlanner.Positions;
          if FPlanner.Sidebar.Visible then
            ColWidths[ColCount - 1] := FPlanner.FSidebar.Width
          else
            ColWidths[ColCount - 1] := 0;
        end;
      spLeftRight:
        begin
          ColumnWidth := ClientWidth - 2 * ColumnWidth;
          delta := ColumnWidth mod FPlanner.Positions;
          ColumnWidth := ColumnWidth div FPlanner.Positions;

          if FPlanner.Sidebar.Visible then
            ColWidths[ColCount - 1] := FPlanner.FSidebar.Width
          else
            ColWidths[ColCount - 1] := 0;
        end
      else
      begin
        ColumnWidth := ClientWidth - ColumnWidth;
        delta := ColumnWidth mod FPlanner.Positions;
        ColumnWidth := ColumnWidth div FPlanner.Positions;
      end;
    end;

    FPosResizing := True;
    DefaultRowHeight := FPlanner.FDisplay.FDisplayScale;
    FPosResizing := False;

    if FPlanner.FPositionWidth <> 0 then
      ColumnWidth := FPlanner.FPositionWidth;

    if not FPlanner.FNoPositionSize then
      for ColumnIndex := ColOffset to FPlanner.Positions + ColOffset - 1 do
        if (ColumnIndex < ColCount) then
        begin
          if delta > 0 then
          begin
            ColWidths[ColumnIndex] := ColumnWidth + 1;
            Dec(delta);
          end
          else
            ColWidths[ColumnIndex] := ColumnWidth;
        end;
  end
  else
  begin
    if RowOffset = 1 then
    begin
      if FPlanner.FSidebar.Visible then
        RowHeights[0] := FPlanner.FSidebar.Width
      else
        RowHeights[0] := 0;

      ColumnWidth := Self.ClientHeight - RowHeights[0] {- GetVScrollSize - bw};
      delta := ColumnWidth mod FPlanner.Positions;
      ColumnWidth := ColumnWidth div FPlanner.Positions;
    end
    else
    begin
      ColumnWidth := Self.ClientHeight - FPlanner.FSidebar.Width
      {- GetVScrollSize - 10};
      delta := ColumnWidth mod FPlanner.Positions;
      ColumnWidth := ColumnWidth div FPlanner.Positions;
      RowHeights[RowCount - 1] := FPlanner.FSidebar.Width;
    end;

    FPosResizing := True;
    DefaultColWidth := FPlanner.FDisplay.FDisplayScale;
    FPosResizing := False;

    if FPlanner.FPositionWidth <> 0 then
      ColumnWidth := FPlanner.FPositionWidth;

    if not FPlanner.FNoPositionSize then
      for ItemIndex := RowOffset to FPlanner.Positions + RowOffset - 1 do
      begin
        if delta > 0 then
        begin
          RowHeights[ItemIndex] := ColumnWidth + 1;
          Dec(delta);
        end
        else
          RowHeights[ItemIndex] := ColumnWidth;
      end;
  end;

  for ItemIndex := 0 to FPlanner.Items.Count - 1 do
    (FPlanner.Items.Items[ItemIndex] as TPlannerItem).UpdateWnd;

  poswi := 0;

  if FPlanner.Sidebar.Visible then
    Inc(poswi);

  while (FPlanner.FHeader.Sections.Count < FPlanner.Positions + poswi + 1) do
    FPlanner.FHeader.Sections.Add('');

  while (FPlanner.FHeader.Sections.Count > FPlanner.Positions + poswi + 1) do
    FPlanner.FHeader.Sections.Delete(FPlanner.FHeader.Sections.Count - 1);

  while (FPlanner.FFooter.Sections.Count < FPlanner.Positions + poswi + 1) do
    FPlanner.FFooter.Sections.Add('');

  while (FPlanner.FFooter.Sections.Count > FPlanner.Positions + poswi + 1) do
    FPlanner.FFooter.Sections.Delete(FPlanner.FFooter.Sections.Count - 1);

  for SectionIndex := 0 to FPlanner.FHeader.Sections.Count - 1 do
  begin

    if SectionIndex < FPlanner.FPlannerHeader.Captions.Count then
      FPlanner.FHeader.Sections[SectionIndex] :=
        FPlanner.FPlannerHeader.Captions.Strings[SectionIndex]
    else
      FPlanner.FHeader.Sections[SectionIndex] := '';

    if SectionIndex < FPlanner.FPlannerFooter.Captions.Count then
      FPlanner.FFooter.Sections[SectionIndex] :=
        FPlanner.FPlannerFooter.Captions.Strings[SectionIndex]
    else
      FPlanner.FFooter.Sections[SectionIndex] := '';

    if FPlanner.Sidebar.Orientation = soVertical then
      FPlanner.FHeader.SectionWidth[SectionIndex] := ColWidths[SectionIndex]
    else
      FPlanner.FHeader.SectionWidth[SectionIndex] := RowHeights[SectionIndex];

    if FPlanner.Sidebar.Orientation = soVertical then
      FPlanner.FFooter.SectionWidth[SectionIndex] := ColWidths[SectionIndex]
    else
      FPlanner.FFooter.SectionWidth[SectionIndex] := RowHeights[SectionIndex];

    if FPlanner.FSidebar.Visible then
      j := 0
    else
      j := 1;

    if (SectionIndex = j) and FPlanner.NavigatorButtons.Visible and
      (FPlanner.Sidebar.Position <> spTop) then
    begin
      FPlanner.FHeader.SectionWidth[SectionIndex] := ColWidths[SectionIndex]
        - BtnWidth;
    end;

    if FPlanner.Sidebar.Orientation = soVertical then
    begin
      if not FPlanner.NavigatorButtons.Visible then
        FPlanner.FHeader.SectionWidth[0] := ColWidths[0] + 1;
      FPlanner.FFooter.SectionWidth[0] := ColWidths[0] + 1;
    end
    else
    begin
      if not FPlanner.NavigatorButtons.Visible then
        FPlanner.FHeader.SectionWidth[0] := RowHeights[0];
      FPlanner.FFooter.SectionWidth[0] := RowHeights[0];
    end;

    if (SectionIndex = FPlanner.FHeader.Sections.Count - 1) and
      (FPlanner.Sidebar.Position <> spTop)
      and FPlanner.NavigatorButtons.Visible then
      FPlanner.FHeader.SectionWidth[SectionIndex] := ColWidths[SectionIndex]
        - BtnWidth;

    if (SectionIndex = FPlanner.FFooter.Sections.Count - 1) and
      (FPlanner.Sidebar.Position <> spTop)
      and FPlanner.NavigatorButtons.Visible then
      FPlanner.FFooter.SectionWidth[SectionIndex] := ColWidths[SectionIndex]
        - BtnWidth;
  end;

  if FPlanner.Flat then
  begin
    if FPlanner.FHeader.Flat then
      FPlanner.FHeader.SectionWidth[0] := FPlanner.FHeader.SectionWidth[0] - 2
    else
      FPlanner.FHeader.SectionWidth[0] := FPlanner.FHeader.SectionWidth[0];
  end
  else
  begin
    if not FPlanner.FHeader.Flat then
      FPlanner.FHeader.SectionWidth[0] := FPlanner.FHeader.SectionWidth[0] + 2
  end;
end;

procedure TPlannerGrid.UpdateScrollBars;
var
  i: integer;
  th,tw: integer;
begin
  th := 0;
  for i := 0 to RowCount - 1 do
    th := th + RowHeights[i];

  tw := 0;
  for i := 0 to ColCount - 1 do
    tw := tw + ColWidths[i];

  if (th < Height) and (tw < Width) then
    ScrollBars := ssNone;

  if (th < Height) and (tw > Width) then
    ScrollBars := ssHorizontal;

  if (th > Height) and (tw < Width) then
    ScrollBars := ssVertical;

  if (th > Height) and (tw > Width) then
    ScrollBars := ssBoth;
end;

procedure TPlannerGrid.SelChanged;
var
  FromSel, ToSel, FromSelPrecis, ToSelPrecis, Position: Integer;

  function EqualSel(a, b: TGridRect): Boolean;
  begin
    Result := (a.Left = b.Left) and (a.Top = b.Top) and (a.Right = b.Right) and
      (a.Bottom = b.Bottom);
  end;

begin
  if not EqualSel(FOldSelection, Selection) then
  begin
    if FPlanner.Sidebar.Orientation = soHorizontal then
    begin
      Position := Selection.Top - 1;
      FromSel := Selection.Left;
      ToSel := 1 + Selection.Right;
    end
    else
    begin
      Position := Selection.Left - 1;
      FromSel := Selection.Top;
      ToSel := 1 + Selection.Bottom;
    end;

    FromSelPrecis := FromSel * FPlanner.Display.DisplayUnit + FPlanner.Display.DisplayOffset;
    ToSelPrecis := ToSel * FPlanner.Display.DisplayUnit + FPlanner.Display.DisplayOffset;

    if Assigned(FPlanner.FOnPlannerSelChange) then
      FPlanner.FOnPlannerSelChange(FPlanner, Position, FromSel, FromSelPrecis,
        ToSel, ToSelPrecis);

    RepaintSelection(FOldSelection);
    RepaintSelection(Selection);

    if FPlanner.Header.ActiveColor <> clNone then
    begin
      FPlanner.FHeader.Invalidate;
    end;

    (*
    if FPlanner.SideBar.ActiveColor <> clNone then
    begin
      if (FPlanner.SideBar.Position in [spLeft, spLeftRight]) then
        FPlanner.GridControl.RepaintRect(Rect(0,0,0,FPlanner.GridControl.RowCount - 1));

      if (FPlanner.SideBar.Position in [spRight, spLeftRight]) then
        FPlanner.GridControl.RepaintRect(Rect(FPlanner.GridControl.ColCount - 1,0,FPlanner.GridControl.ColCount - 1,FPlanner.GridControl.RowCount - 1));

      if FPlanner.SideBar.Position = spTop then
        FPlanner.GridControl.RepaintRect(Rect(0,0,FPlanner.GridControl.ColCount - 1,0));
    end;
    *)

  end;

  FOldSelection := Selection;
end;

procedure TPlannerGrid.UpdateNVI;
var
  i, j: Integer;
  TVS, BVS: Boolean;
  ir: TRect;
begin
  if not FPlanner.IndicateNonVisibleItems then
    Exit;

  if (csDestroying in ComponentState) then
    Exit;

  if FPlanner.Items.FUpdateCount > 0 then
    Exit;

  TVS := False;
  BVS := False;

  if FPlanner.Sidebar.Position <> spTop then
  begin
    if FPlanner.FTopIndicator then
    begin
      ir := CellRect(0, FOldTopRow);
      RepaintRect(ir);
    end;
    if FPlanner.FBottomIndicator then
    begin
      ir := CellRect(0, FOldTopRow + VisibleRowCount);
      RepaintRect(ir);
    end;

    if TopRow > 0 then
    begin
      for j := 0 to TopRow - 1 do
        for i := 1 to FPlanner.Positions do
        begin
          if Assigned(FPlanner.Items.FindItem(j, i - 1)) then
          begin
            TVS := True;
            Break;
          end;
        end;
    end;

    if TopRow + VisibleRowCount < RowCount then
    begin
      for j := TopRow + VisibleRowCount to RowCount - 1 do
        for i := 1 to FPlanner.Positions do
        begin
          if Assigned(FPlanner.Items.FindItem(j, i - 1)) then
          begin
            BVS := True;
            Break;
          end;
        end;
    end;

    if FPlanner.FTopIndicator <> TVS then
    begin
      FPlanner.FTopIndicator := TVS;
      FPlanner.FGrid.RepaintRect(Rect(0, 0, 22, 20));
    end;

    FPlanner.FBottomIndicator := BVS;
    ir := Rect(0, FPlanner.FGrid.Height - 30, 22, FPlanner.FGrid.Height);
    InvalidateRect(FPlanner.FGrid.Handle, @ir, True);
    // FPlanner.FGrid.RepaintRect(Rect(0,FPlanner.FGrid.Height - 30,22,FPlanner.FGrid.Height));
  end
  else
  begin
    if FPlanner.FTopIndicator then
    begin
      ir := CellRect(FOldLeftCol, 0);
      RepaintRect(ir);
    end;
    if FPlanner.FBottomIndicator then
    begin
      ir := CellRect(0, FOldLeftCol + VisibleColCount);
      RepaintRect(ir);
    end;

    if LeftCol > 0 then
    begin
      for j := 0 to LeftCol - 1 do
        for i := 1 to FPlanner.Positions do
        begin
          if Assigned(FPlanner.Items.FindItem(j, i - 1)) then
          begin
            TVS := True;
            Break;
          end;
        end;
    end;

    if LeftCol + VisibleColCount < ColCount then
    begin
      for j := LeftCol + VisibleColCount to ColCount - 1 do
        for i := 1 to FPlanner.Positions do
        begin
          if Assigned(FPlanner.Items.FindItem(j, i - 1)) then
          begin
            BVS := True;
            Break;
          end;
        end;
    end;

    if FPlanner.FTopIndicator <> TVS then
    begin
      FPlanner.FTopIndicator := TVS;
      FPlanner.FGrid.RepaintRect(Rect(0, 0, 22, 20));
    end;

    FPlanner.FBottomIndicator := BVS;

    ir := Rect(0, 0, FPlanner.FGrid.Width, 22);
    InvalidateRect(FPlanner.FGrid.Handle, @ir, True);

    //FPlanner.FGrid.RepaintRect(Rect(FPlanner.FGrid.Width - 22,0,FPlanner.FGrid.Width,22));
  end;
end;

procedure TPlannerGrid.TopLeftChanged;
var
  ItemIndex, i: Integer;
  R,R1,R2: TRect;
begin
  if (csDesigning in ComponentState) and FPlanner.ShowDesignHelper then
    Invalidate;

  if (FOldLeftCol <> LeftCol) and (FPlanner.Sidebar.Position in [spLeft,
    spRight, spLeftRight]) then
  begin
    if FGridState = gsSelecting then
      FGridState := gsNormal;
  end;

  if (FOldTopRow <> TopRow) and (FPlanner.Sidebar.Position in [spTop]) then
  begin
    if FGridState = gsSelecting then
      FGridState := gsNormal;
  end;

  for ItemIndex := 0 to FPlanner.Items.Count - 1 do
  begin
    if ((FPlanner.Items.Items[ItemIndex] as TPlannerItem).ItemBegin >= TopRow - 1) and
      ((FPlanner.Items.Items[ItemIndex] as TPlannerItem).ItemEnd <= TopRow + VisibleRowCount + 1) and
      Assigned((FPlanner.Items.Items[ItemIndex] as TPlannerItem).DrawTool) then
       (FPlanner.Items.Items[ItemIndex] as TPlannerItem).UpdateWnd;
  end;

  if FPlanner.Header.Visible then
  begin
    if FPlanner.Sidebar.Orientation = soVertical then
      FPlanner.FHeader.FLeftPos := Max(0, LeftCol - 1)
    else
      FPlanner.FHeader.FLeftPos := Max(0, TopRow - 1);

    FPlanner.FHeader.Repaint;
  end;

  if FPlanner.Footer.Visible then
  begin
    if FPlanner.Sidebar.Orientation = soVertical then
      FPlanner.FFooter.FLeftPos := Max(0, LeftCol - 1)
    else
      FPlanner.FFooter.FLeftPos := Max(0, TopRow - 1);

    FPlanner.FFooter.Repaint;
  end;

  if Assigned(FPlanner.FOnTopLeftChanged) then
    FPlanner.FOnTopLeftChanged(FPlanner);

  if FPlanner.ScrollBarStyle.Flat then
  begin
    UpdateVScrollBar;
    UpdateHScrollBar;
  end;

  // repainting for links
  if (FOldLeftCol = LeftCol - 1) and (FPlanner.ShowLinks) then
  begin
    R1 := CellRect(LeftCol + VisibleColCount - 3, 0);
    R2 := CellRect(LeftCol + VisibleColCount, 0);

    R.Top := 0;
    R.Left := R1.Left;
    R.Right := R2.Right;
    R.Bottom := Height;

    InvalidateRect(Handle,@R, True);
  end;

  if (FOldTopRow <>  TopRow) and (FPlanner.ShowLinks) then
  begin
    Invalidate;
    {
    R1 := CellRectEx(0,TopRow + VisibleRowCount - 3);
    R2 := CellRectEx(0,TopRow + VisibleRowCount);

    R.Top := R1.Top;
    R.Left := 0;
    R.Right := Width;
    R.Bottom := R2.Top;

    InvalidateRect(Handle,@R, True);
   }
  end;

  if (FPlanner.FSidebar.Position in [spLeft, spLeftRight, spRight]) and
    (FPlanner.FSidebar.ActiveColor <> clNone) then
  begin
    if FPlanner.FSidebar.ShowInPositionGap then
    begin
      for i := 1 to ColCount do
        for ItemIndex := 0 to RowCount - 1 do
        begin
          InvalidateCell(i - 1, ItemIndex);
        end;
    end
    else
    begin
      for ItemIndex := 0 to RowCount - 1 do
      begin
        if (FPlanner.Sidebar.Position in [spRight, spLeftRight]) then
        begin
          InvalidateCell(ColCount - 1, ItemIndex);
        end;
        InvalidateCell(0, ItemIndex);
      end;
    end;
  end;

  if FPlanner.FSidebar.Visible and FPlanner.FSidebar.Border and
    (FPlanner.FSidebar.Position in [spLeft, spLeftRight, spRight]) then
  begin
    if FPlanner.FSidebar.Position in [spLeft, spLeftRight] then
    begin
      InvalidateCell(0, TopRow);
      InvalidateCell(0, FOldTopRow);
      FOldTopRow := TopRow;
    end;

    if FPlanner.FSidebar.Position in [spRight, spLeftRight] then
    begin
      InvalidateCell(ColCount - 1, TopRow);
      InvalidateCell(ColCount - 1, FOldTopRow);
      FOldTopRow := TopRow;
    end;
  end;

  if (FPlanner.FSidebar.ShowInPositionGap and
      (FPlanner.FSidebar.Position in [spLeft, spLeftRight, spRight])) then
  begin
    for ItemIndex := 0 to ColCount - 1 do
    begin
      InvalidateCell(ItemIndex, TopRow);
      InvalidateCell(ItemIndex, FOldTopRow);
    end;
    FOldTopRow := TopRow;
  end;

  if FPlanner.FDisplay.FDisplayText > 0 then
  begin
    if (FPlanner.FSidebar.Position in [spLeft, spLeftRight, spRight]) then
      R := Rect(0, 0, ColWidths[0], Height)
    else
      R := Rect(0, 0, Width, RowHeights[0]);
    InvalidateRect(Handle, @R, False);
  end;

  if (FPlanner.Mode.PlannerType = plTimeLine) and
    (FPlanner.FSidebar.Position = spTop) and (FPlanner.Sidebar.Visible) then
  begin
    for i := FixedCols to ColCount do
      InvalidateCell(i, 0);
  end;

  if (FPlanner.FSidebar.Visible and FPlanner.FSidebar.Border) and
    (FPlanner.FSidebar.Position = spTop) then
  begin
    InvalidateCell(LeftCol, 0);
    InvalidateCell(FOldLeftCol, 0);
    FOldLeftCol := LeftCol;
  end;

  UpdateNVI;

  FOldLeftCol := LeftCol;
  FOldTopRow := TopRow;

  if Assigned(FPlanner.SyncPlanner.Planner) then
  begin
    if FPlanner.SyncPlanner.ScrollVertical then
      FPlanner.SyncPlanner.Planner.GridControl.TopRow := TopRow;

    if FPlanner.SyncPlanner.ScrollHorizontal then
      FPlanner.SyncPlanner.Planner.GridControl.LeftCol := LeftCol;
  end;

  //if FPlanner.ShowLinks then
  //  Invalidate;
end;

procedure TPlannerGrid.StartEditCol(ARect: TRect; APlannerItem: TPlannerItem;
  X, Y: Integer);
var
  ColumnHeight, ih, iw, ew, tw, eh, TopOffset: Integer;
  s: string;
  ER: TRect;

begin
  if APlannerItem = nil then
    Exit;

  if APlannerItem.FPopupEdit then
    Exit;

  if Assigned(APlannerItem.Editor) then
  begin
    if APlannerItem.Editor.EditorUse = euAlways then
    begin
      if Assigned(FPlanner.OnItemStartEdit) then
      begin
        FPlanner.OnItemStartEdit(Self, APlannerItem);
      end;

      FPlanner.FEditMode := True;

      APlannerItem.Editor.Edit(FPlanner, APlannerItem);

      if Assigned(FPlanner.OnItemEndEdit) then
        FPlanner.OnItemEndEdit(Self, APlannerItem);

      FPlanner.FEditMode := False;

      Exit;
    end;
  end;

  if FPlanner.InplaceEdit = ieNever then
    Exit;

  FPlanner.FEditMode := True;

  if Assigned(FPlanner.OnItemStartEdit) then
  begin
    FPlanner.OnItemStartEdit(Self, APlannerItem);
  end;

  if (APlannerItem.FConflicts > 1) then
  begin
    iw := ColWidthEx(APlannerItem.ItemPos) div APlannerItem.FConflicts;
    ARect.Left := ARect.Left + APlannerItem.FConflictPos * iw;
    ARect.Right := ARect.Left + iw;
  end;

  ColumnHeight := EDITOFFSET;
  ih := 0;
  iw := 0;
  ew := 0;
  eh := 0;

  if (APlannerItem.Shape = psRect) and (APlannerItem.TrackVisible) then
    tw := FPlanner.TrackWidth
  else
    tw := 0;

  case APlannerItem.Shape of
    psRounded:
      begin
        ew := ew + (CORNER_EFFECT shr 2) + 1;
        ARect.Top := ARect.Top + (CORNER_EFFECT shr 2);
        eh := eh + 6;
      end;
    psHexagon:
      begin
        ew := ew + CORNER_EFFECT;
        ARect.Top := ARect.Top + 4;
        eh := eh + 6;
      end;
{$IFDEF TMSSKINS}
    psSkin:
      begin
        InflateRect(ARect, -FPlanner.Skin.SkinX, -FPlanner.Skin.SkinY);
        eh := FPlanner.Skin.SkinY;
      end;
{$ENDIF}
  end;

  if APlannerItem.Shadow then
  begin
    ew := ew + 1;
    eh := eh + 3;
  end;

  if APlannerItem.CompletionDisplay = cdVertical then
    ew := ew + 12;

  if ((APlannerItem.ImageID >= 0) or (APlannerItem.FImageIndexList.Count > 0))
    and Assigned(FPlanner.PlannerImages) then
  begin
    if not (APlannerItem.CaptionType = ctNone) then
      ih := FPlanner.PlannerImages.Height + 6 + FPlanner.ImageOffsetY;

    iw := FPlanner.PlannerImages.Width + EDITOFFSET;
  end;

  if (APlannerItem.CaptionType <> ctNone) or
    ((APlannerItem.FImageIndexList.Count > 1) and
      (APlannerItem.ImagePosition = ipHorizontal)) then
  begin
    Canvas.Font.Assign(APlannerItem.CaptionFont);
    ColumnHeight := Canvas.TextHeight('gh') + 4;
    if (APlannerItem.ImagePosition = ipHorizontal) then
      iw := 0;
  end;
  //  else
  //    ih := 0;

  if (ih > ColumnHeight) then
    ColumnHeight := ih;

  s := APlannerItem.Text.Text;

  if APlannerItem.ItemBegin < TopRow then
    TopOffset := 0
  else
    TopOffset := 2 {+ EDITOFFSET} + ColumnHeight;

  if (APlannerItem.CompletionDisplay = cdHorizontal) then
    TopOffset := TopOffset + 12;

  if IsRtf(s) or (APlannerItem.InplaceEdit = peRichText) then
  begin
    FPlanner.FRichEdit.Parent := Self;
    FPlanner.FRichEdit.ScrollBars := FPlanner.EditScroll;
    FPlanner.FRichEdit.PlannerItem := APlannerItem;
    FPlanner.TextToRich(s);
    FPlanner.FRichEdit.Top := ARect.Top + 6 + ColumnHeight;
    FPlanner.FRichEdit.Left := ARect.Left + tw + 1 + iw + ew;
    FPlanner.FRichEdit.Width := ARect.Right - ARect.Left - tw - 3 -
      FPlanner.FItemGap - iw - 2 * ew;
    FPlanner.FRichEdit.Height :=
      (APlannerItem.ItemEnd - APlannerItem.ItemBegin) * RowHeights[0]
      - 10 - ColumnHeight;
    FPlanner.FRichEdit.Visible := True;
    BringWindowToTop(FPlanner.FRichEdit.Handle);
    FPlanner.FRichEdit.SetFocus;
    FPlanner.FRichEdit.SelectAll;
  end
  else
    case APlannerItem.InplaceEdit of
      peMaskEdit, peEdit:
        begin
          if APlannerItem.InplaceEdit = peMaskEdit then
            FMaskEdit.EditMask := APlannerItem.EditMask
          else
            FMaskEdit.EditMask := '';
          FMaskEdit.Font.Assign(FPlanner.Font);
          if APlannerItem.ShowSelection then
          begin
            FMaskEdit.Color := FPlanner.GetEditColor(APlannerItem, True);
            FMaskEdit.Font.Color := APlannerItem.SelectFontColor
          end
          else
            FMaskEdit.Color := FPlanner.GetEditColor(APlannerItem, False);

          FMaskEdit.PlannerItem := APlannerItem;
          FMaskEdit.Top := ARect.Top + TopOffset;
          FMaskEdit.Left := ARect.Left + tw + 1 + iw + ew;
          FMaskEdit.Width := ARect.Right - ARect.Left - tw - 3 -
            FPlanner.FItemGap - iw - 2 * ew;
          FMaskEdit.Height := APlannerItem.GetVisibleSpan * RowHeights[0]
            - 2 - TopOffset;
          FMaskEdit.BorderStyle := bsNone;
          FMaskEdit.Visible := True;
          if (APlannerItem.Text.Count > 0) then
            FMaskEdit.Text := APlannerItem.Text[0];
          BringWindowToTop(FMaskEdit.Handle);
          FMaskEdit.SetFocus;
        end;
      peMemo:
        begin
          FMemo.Parent := Self;
          FMemo.ScrollBars := FPlanner.EditScroll;
          FMemo.Font.Assign(APlannerItem.Font);
          if APlannerItem.ShowSelection then
          begin
            FMemo.Color := FPlanner.GetEditColor(APlannerItem, True);
            FMemo.Font.Color := APlannerItem.SelectFontColor;
          end
          else
            FMemo.Color := FPlanner.GetEditColor(APlannerItem, False);

          FMemo.PlannerItem := APlannerItem;

          FMemo.Top := ARect.Top + TopOffset;
          FMemo.Left := ARect.Left + tw + iw + ew;
          FMemo.Width := ARect.Right - ARect.Left - tw - 4 -
            FPlanner.FItemGap - iw - ew;

          FMemo.Height := APlannerItem.GetVisibleSpan * RowHeights[0]
            - 4 - eh - TopOffset;

          FMemo.BorderStyle := bsNone;
          FMemo.Visible := True;
          BringWindowToTop(FMemo.Handle);
          FMemo.Lines.Text := HTMLStrip(APlannerItem.Text.Text);
          if FPlanner.NotesMaxLength > 0 then
            FMemo.MaxLength := FPlanner.NotesMaxLength;

          FMemo.SetFocus;

          SetEditDirectSelection(ARect, X, Y);
        end;
{$IFNDEF DELPHI_UNICODE}
      peUniMemo:
        begin
          FUniMemo.Parent := Self;
          FUniMemo.ScrollBars := FPlanner.EditScroll;
          FUniMemo.Font.Assign(APlannerItem.Font);
          if APlannerItem.ShowSelection then
          begin
            FUniMemo.Color := FPlanner.GetEditColor(APlannerItem, True);
            FUniMemo.Font.Color := APlannerItem.SelectFontColor;
          end
          else
            FUniMemo.Color := FPlanner.GetEditColor(APlannerItem, False);

          FUniMemo.PlannerItem := APlannerItem;

          FUniMemo.Top := ARect.Top + TopOffset;
          FUniMemo.Left := ARect.Left + tw + iw + ew;
          FUniMemo.Width := ARect.Right - ARect.Left - tw - 4 -
            FPlanner.FItemGap - iw - ew;

          FUniMemo.Height := APlannerItem.GetVisibleSpan * RowHeights[0]
            - 4 - eh - TopOffset;

          FUniMemo.BorderStyle := bsNone;
          FUniMemo.Visible := True;
          BringWindowToTop(FUniMemo.Handle);
          FUniMemo.Text := APlannerItem.WideText;

          if FPlanner.NotesMaxLength > 0 then
            FUniMemo.MaxLength := FPlanner.NotesMaxLength;

          FUniMemo.SetFocus;
          SetEditDirectSelection(ARect, X, Y);
        end;
{$ENDIF}
      peCustom:
        begin
          ER.Left := ARect.Left + tw + 1 + iw + ew;
          ER.Top := ARect.Top + TopOffset;
          ER.Right := ARect.Right - tw - 3 - FPlanner.FItemGap - iw - 2 * ew;
          ER.Bottom := ARect.Top + APlannerItem.GetVisibleSpan * RowHeights[0]
            - 10 - ColumnHeight;
          if Assigned(FPlanner.FOnCustomEdit) then
            FPlanner.FOnCustomEdit(Self, ER, APlannerItem);
        end;
    end;
end;

procedure TPlannerGrid.SetEditDirectSelection(ARect: TRect; X, Y: Integer);
var
  CharacterCoordinate: Integer;
begin
  if (FPlanner.EditDirect) and (X > -1) then
  begin
    CharacterCoordinate := SendMessage(FMemo.Handle, EM_CHARFROMPOS, 0,
      MakeLong(X - ARect.Left, Y - ARect.Top));
    if (CharacterCoordinate = -1) then
      Exit;
    FMemo.SelStart := Loword(CharacterCoordinate);
    FMemo.SelLength := 0;
  end
  else
    FMemo.SelectAll;
end;

procedure TPlannerGrid.SetRowEx(const Value: Integer);
var
  dosync: boolean;
begin
  dosync := inherited Row <> Value;

  inherited Row := Value;

  if Assigned(FPlanner.SyncPlanner.Planner) and dosync then
  begin
    if FPlanner.SyncPlanner.SelectionRow then
      FPlanner.SyncPlanner.Planner.GridControl.Row := inherited Row;
  end;
end;

procedure TPlannerGrid.StartEditRow(ARect: TRect; APlannerItem: TPlannerItem;
  X, Y: Integer);
var
  ColumnHeight, ih, iw, ew, eh: Integer;
  s: string;
  ER: TRect;

begin
  if APlannerItem = nil then
    Exit;

  if APlannerItem.FPopupEdit then
    Exit;

  if Assigned(APlannerItem.Editor) then
  begin
    if APlannerItem.Editor.EditorUse = euAlways then
    begin
      FPlanner.FEditMode := True;

      if Assigned(FPlanner.OnItemStartEdit) then
      begin
        FPlanner.OnItemStartEdit(Self, APlannerItem);
      end;

      APlannerItem.Editor.Edit(FPlanner, APlannerItem);

      if Assigned(FPlanner.OnItemEndEdit) then
        FPlanner.OnItemEndEdit(Self, APlannerItem);

      FPlanner.FEditMode := False;
      Exit;
    end;
  end;

  if FPlanner.InplaceEdit = ieNever then
    Exit;

  FPlanner.FEditMode := True;

  if Assigned(FPlanner.OnItemStartEdit) then
  begin
    FPlanner.OnItemStartEdit(Self, APlannerItem);
  end;

  if (APlannerItem.FConflicts > 1) then
  begin
    iw := RowHeightEx(APlannerItem.ItemPos) div APlannerItem.FConflicts;
    ARect.Top := ARect.Top + APlannerItem.FConflictPos * iw;
    ARect.Bottom := ARect.Top + iw;
  end;

  ARect.Top := ARect.Top + APlannerItem.VMargin;
  ARect.Bottom := ARect.Bottom - APlannerItem.VMargin;

  ColumnHeight := 0;
  ih := 0;
  iw := 0;
  ew := 0;
  eh := 0;

  case APlannerItem.Shape of
    psRounded:
      begin
        ew := ew + (CORNER_EFFECT shr 1) - 1;
        if APlannerItem.CaptionType = ctNone then
          ARect.Top := ARect.Top + (CORNER_EFFECT shr 2);
        //ARect.Top := ARect.Top + 4;
      end;
    psHexagon:
      ew := ew + CORNER_EFFECT;
{$IFDEF TMSSKINS}
    psSkin:
      begin
        InflateRect(ARect, 0, -(FPlanner.Skin.SkinY div 2));
        ew := FPlanner.Skin.SkinX div 2;
      end;
{$ENDIF}
  end;

  if APlannerItem.Shadow then
  begin
    ew := ew + 1;
    eh := eh + 2;
  end;

  if APlannerItem.CompletionDisplay = cdVertical then
    ew := ew + 10;

  if APlannerItem.CompletionDisplay = cdHorizontal then
    ARect.Top := ARect.Top + 12;

  if ((APlannerItem.ImageID >= 0) or (APlannerItem.FImageIndexList.Count > 0))
    and Assigned(FPlanner.PlannerImages) then
  begin
    if not((APlannerItem.CaptionType = ctNone) or
        (APlannerItem.ImagePosition = ipVertical)) then
      ih := FPlanner.PlannerImages.Height + 4 + FPlanner.ImageOffsetY;

    iw := FPlanner.PlannerImages.Width + EDITOFFSET;
  end;

  if (APlannerItem.CaptionType <> ctNone) or
    ((APlannerItem.FImageIndexList.Count > 1) and
      (APlannerItem.ImagePosition = ipHorizontal)) then
  begin
    ColumnHeight := Canvas.TextHeight('gh') + 6;
    if (APlannerItem.ImagePosition = ipHorizontal) then
      iw := 0;
  end;
  //  else
  //    ih := 0;

  if (ih > ColumnHeight) then
    ColumnHeight := ih;

  s := APlannerItem.Text.Text;
  if IsRtf(s) or (APlannerItem.InplaceEdit = peRichText) then
  begin
    FPlanner.FRichEdit.Parent := Self;
    FPlanner.FRichEdit.ScrollBars := FPlanner.EditScroll;
    FPlanner.FRichEdit.PlannerItem := APlannerItem;
    FPlanner.TextToRich(s);
    FPlanner.FRichEdit.Top := ARect.Top + FPlanner.TrackWidth + 2 + ColumnHeight;
    FPlanner.FRichEdit.Left := ARect.Left + 3 + iw + ew;
    FPlanner.FRichEdit.Width := (APlannerItem.ItemEnd - APlannerItem.ItemBegin)
      * ColWidthEx(APlannerItem.ItemPos) - 6 - ColumnHeight - 2 * ew;
    FPlanner.FRichEdit.Height := ARect.Bottom - ARect.Top - 18 - iw;
    FPlanner.FRichEdit.Visible := True;
    BringWindowToTop(FPlanner.FRichEdit.Handle);
    FPlanner.FRichEdit.SetFocus;
    FPlanner.FRichEdit.SelectAll;
  end
  else
    case APlannerItem.InplaceEdit of
      peMaskEdit, peEdit:
        begin
          if APlannerItem.InplaceEdit = peMaskEdit then
            FMaskEdit.EditMask := APlannerItem.EditMask
          else
            FMaskEdit.EditMask := '';
          FMaskEdit.Font.Assign(FPlanner.Font);

          FMaskEdit.Color := FPlanner.GetEditColor(APlannerItem,
            APlannerItem.ShowSelection);
          FMaskEdit.Font.Color := APlannerItem.SelectFontColor;

          FMaskEdit.PlannerItem := APlannerItem;
          FMaskEdit.Top := ARect.Top + FPlanner.TrackWidth + 2 + ColumnHeight;
          FMaskEdit.Left := ARect.Left + 3 + iw + ew;
          FMaskEdit.Width := APlannerItem.GetVisibleSpan * ColWidthEx
            (APlannerItem.ItemPos) - 6 - iw - 2 * ew;
          FMaskEdit.Height := ARect.Bottom - ARect.Top - FPlanner.FItemGap -
            ColumnHeight - FPlanner.TrackWidth;
          FMaskEdit.BorderStyle := bsNone;
          FMaskEdit.Visible := True;
          if (APlannerItem.Text.Count > 0) then
            FMaskEdit.Text := APlannerItem.Text[0];
          BringWindowToTop(FMaskEdit.Handle);
          FMaskEdit.SetFocus;
        end;
      peMemo:
        begin
          FMemo.Parent := Self;
          FMemo.ScrollBars := FPlanner.EditScroll;
          FMemo.Font.Assign(APlannerItem.Font);

          if APlannerItem.ShowSelection then
          begin
            FMemo.Color := FPlanner.GetEditColor(APlannerItem, True);
            FMemo.Font.Color := APlannerItem.SelectFontColor;
          end
          else
            FMemo.Color := FPlanner.GetEditColor(APlannerItem, False);

          FMemo.PlannerItem := APlannerItem;
          FMemo.Top := ARect.Top + FPlanner.TrackWidth + 2 + ColumnHeight;
          FMemo.Left := ARect.Left + 3 + iw + ew;
          FMemo.Width := APlannerItem.GetVisibleSpan * ColWidthEx
            (APlannerItem.ItemPos) - 8 - iw - 2 * ew;
          FMemo.Height := ARect.Bottom - ARect.Top - FPlanner.FItemGap -
            ColumnHeight - FPlanner.TrackWidth - 6 - eh;
          FMemo.BorderStyle := bsNone;
          FMemo.Visible := True;
          FMemo.Lines.Text := HTMLStrip(APlannerItem.Text.Text);
          BringWindowToTop(FMemo.Handle);
          if FPlanner.NotesMaxLength > 0 then
            FMemo.MaxLength := FPlanner.NotesMaxLength;

          FMemo.SetFocus;
          SetEditDirectSelection(ARect, X, Y);
        end;
{$IFNDEF DELPHI_UNICODE}
      peUniMemo:
        begin
          FUniMemo.Parent := Self;
          FUniMemo.ScrollBars := FPlanner.EditScroll;
          FUniMemo.Font.Assign(APlannerItem.Font);
          if APlannerItem.ShowSelection then
          begin
            FUniMemo.Color := FPlanner.GetEditColor(APlannerItem, True);
            FUniMemo.Font.Color := APlannerItem.SelectFontColor;
          end
          else
            FUniMemo.Color := FPlanner.GetEditColor(APlannerItem, False);

          FUniMemo.PlannerItem := APlannerItem;

          FUniMemo.Top := ARect.Top + FPlanner.TrackWidth + 2 + ColumnHeight;
          FUniMemo.Left := ARect.Left + 3 + iw + ew;
          FUniMemo.Width := APlannerItem.GetVisibleSpan * ColWidthEx
            (APlannerItem.ItemPos) - 8 - iw - 2 * ew;
          FUniMemo.Height := ARect.Bottom - ARect.Top - FPlanner.FItemGap -
            ColumnHeight - FPlanner.TrackWidth - 6 - eh;

          FUniMemo.BorderStyle := bsNone;
          FUniMemo.Visible := True;
          BringWindowToTop(FUniMemo.Handle);
          FUniMemo.Text := APlannerItem.WideText;

          if FPlanner.NotesMaxLength > 0 then
            FUniMemo.MaxLength := FPlanner.NotesMaxLength;

          FUniMemo.SetFocus;
          SetEditDirectSelection(ARect, X, Y);
        end;
{$ENDIF}
      peCustom:
        begin
          ER.Left := ARect.Left + 3 + iw + ew;
          ER.Top := ARect.Top + FPlanner.TrackWidth + 2 + ColumnHeight;
          ER.Right := ARect.Left + APlannerItem.GetVisibleSpan * ColWidthEx
            (APlannerItem.ItemPos) - 6 - iw - 2 * ew;
          ER.Bottom := ARect.Bottom - FPlanner.FItemGap - ColumnHeight -
            FPlanner.TrackWidth - 6;
          if Assigned(FPlanner.FOnCustomEdit) then
            FPlanner.FOnCustomEdit(Self, ER, APlannerItem);
        end;
    end;
end;

procedure TPlannerGrid.WMMouseMove(var Message: TWMMouseMove);
begin
  inherited;
end;


procedure TPlannerGrid.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var
  FromSel, FromSelPrecis: Integer;
  ToSel, ToSelPrecis: Integer;
  APlannerItem, nplIt: TPlannerItem;
  GridCoord: TGridCoord;
  GridRect, GridRectE, R, tr, hr, CR: TRect;
  iw: Integer;
  grr: TGridRect;
  s, Anchor, StrippedHTMLString, FocusAnchor: string;
  XSize, YSize, ImgSize, ImgVSize, ml, hl: Integer;
  ColOffset, RowOffset: Integer;
  OutBounds, AutoHandle: Boolean;
  //ShiftState: TShiftState;
  ScreenPoint: TPoint;
  CID, CV, CT: string;
  OrigButton: TMouseButton;
  SelP: TPoint;
  isSizing: boolean;

begin
  if (csDesigning in ComponentState) and FPlanner.ShowDesignHelper then
  begin
    case MouseOverDesignChoice(X, Y) of
      1:
        if FPlanner.Sidebar.Position in [spLeft, spRight, spLeftRight] then
          FPlanner.Sidebar.Position := spTop
        else
          FPlanner.Sidebar.Position := spLeft;
      2:
        begin
          if FPlanner.Items.Count = 0 then
          begin
            with FPlanner.Items.Add do
            begin
              ItemBegin := 4;
              ItemEnd := 8;
              ItemPos := 0;
            end;
            // scroll back to ensure visibility of design item
            TopRow := FixedRows;
            LeftCol := FixedCols;
          end
          else
            FPlanner.Items.Clear;
        end;
      3:
        begin
          case FPlanner.Mode.PlannerType of
            plDay:
              FPlanner.Mode.PlannerType := plMonth;
            plMonth:
              FPlanner.Mode.PlannerType := plDayPeriod;
            plDayPeriod:
              FPlanner.Mode.PlannerType := plHalfDayPeriod;
            plHalfDayPeriod:
              FPlanner.Mode.PlannerType := plMultiMonth;
            plMultiMonth:
              FPlanner.Mode.PlannerType := plTimeLine;
            plTimeLine:
              FPlanner.Mode.PlannerType := plDay;
          else
            FPlanner.Mode.PlannerType := plDay;
          end;
        end;
    end;
    Exit;
  end;

  ImgVSize := 0;
  FPlanner.FDownOnItem := False;
  ColOffset := FPlanner.FSidebar.FColOffset;
  RowOffset := FPlanner.FSidebar.FRowOffset;

  FPlanner.DoMouseDown(FPlanner, Button, Shift, X, Y);

  OrigButton := Button;

  if (Button = mbRight) and (FPlanner.ItemSelection.Button in [sbRight, sbBoth]) then
    Button := mbLeft
  else if (Button = mbLeft) and (FPlanner.ItemSelection.Button in [sbRight]) then
  begin
    Button := mbRight;
  end;

  if (Button = mbLeft) then
  begin
    //SetCapture(Self.Handle);
    FMouseUnSelect := False;
    FMouseDown := True;
    FMouseXY := Point(X, Y);
    GridCoord := MouseCoord(X, Y);
    FMouseRCD := MouseCoord(X, Y);

    if not (ssCtrl in Shift) and (FPlanner.Selections.Count > 0)
      and FPlanner.DisjunctSelect then
    begin
      FPlanner.Selections.Clear;
    end;

    if (ssCtrl in Shift) and FPlanner.DisjunctSelect and
      (FPlanner.Selections.Count > 0) then
    begin
      SelP := FPlanner.XYToSelection(GridCoord.X, GridCoord.Y);

      iw := 1;
      while iw <= FPlanner.Selections.Count do
      begin
        with FPlanner.Selections[iw - 1] do
        begin
          if (SelPos = SelP.Y) and (SelBegin <= SelP.X) and (SelEnd >= SelP.X) then
          begin
            FPlanner.UpdateSelection(SelBegin, SelEnd, SelPos, False);
            FPlanner.Selections[iw - 1].Free;
            FMouseUnSelect := True;
          end
          else
            Inc(iw);
        end;
      end;
    end
    else if (ssCtrl in Shift) and FPlanner.DisjunctSelect and
      (FPlanner.Selections.Count = 0) then
    begin
      with FPlanner.FSelections.Add do
      begin
        if FPlanner.SelItemBegin < FPlanner.SelItemEnd then
        begin
          SelBegin := FPlanner.SelItemBegin;
          SelEnd := FPlanner.SelItemEnd;
          SelPos := FPlanner.SelPosition;
        end
        else
        begin
          SelBegin := FPlanner.SelItemEnd;
          SelEnd := FPlanner.SelItemBegin;
          SelPos := FPlanner.SelPosition;
        end;
      end;

      FPlanner.UpdateSelection(FPlanner.SelItemBegin, FPlanner.SelItemEnd,
        FPlanner.SelPosition, True);
    end;

    GridRect := CellRectEx(GridCoord.X, GridCoord.Y);
    if GetFocus <> Self.Handle then
    begin
      if Self.CanFocus then
        Self.SetFocus;
      //++v1.6b++
      if (Selection.Left < 0) or (Selection.Top < 0) or
        (Selection.Left >= ColCount) or (Selection.Top >= RowCount) then
      //--v1.6b--
      begin
        grr.Top := GridCoord.Y;
        grr.Left := GridCoord.X;
        grr.Bottom := GridCoord.Y;
        grr.Right := GridCoord.X;
        Selection := grr;
        SelChanged;
      end;
    end;

    if FPlanner.Sidebar.Orientation = soVertical then
    begin
      APlannerItem := FPlanner.Items.FindItemPos(GridCoord.Y - RowOffset,
        GridCoord.X - ColOffset, X - GridRect.Left);
      OutBounds := (X > GridRect.Right - FPlanner.ItemGap);
    end
    else
    begin
      APlannerItem := FPlanner.Items.FindItemPos(GridCoord.X - ColOffset,
        GridCoord.Y - RowOffset, Y - GridRect.Top);
      OutBounds := (Y > GridRect.Bottom - FPlanner.ItemGap);
    end;

    if FPlanner.AllowBackgroundItemSelection and (APlannerItem = nil) then
    begin
      if FPlanner.Sidebar.Orientation = soVertical then
      begin
        APlannerItem := FPlanner.Items.FindBkgPos(GridCoord.Y - RowOffset,
          GridCoord.X - ColOffset, X - GridRect.Left);
        OutBounds := (X > GridRect.Right);
      end
      else
      begin
        APlannerItem := FPlanner.Items.FindBkgPos(GridCoord.X - ColOffset,
          GridCoord.Y - RowOffset, Y - GridRect.Top);
        OutBounds := (Y > GridRect.Bottom);
      end;
    end;


    if (APlannerItem = nil) or OutBounds then
    begin
      inherited;

      if FPlanner.Mode.FullHalfDay then
      begin
        CorrectSelection;
        InvalidateRow(0);
        InvalidateCol(0);
      end;

      if FPlanner.ItemSelection.AutoUnSelect then
      begin
        FPlanner.Items.UnSelectAll;
        SelChanged;
      end;

      if Assigned(FPlanner.FOnPlannerLeftClick) then
      begin
        if FPlanner.Sidebar.Orientation = soVertical then
        begin
          FromSel := Selection.Top + FPlanner.Display.DisplayStart;
          ToSel := 1 + Selection.Bottom + FPlanner.Display.DisplayStart;
          FromSelPrecis := FromSel * FPlanner.Display.DisplayUnit +
            FPlanner.Display.DisplayOffset;
          ToSelPrecis := ToSel * FPlanner.Display.DisplayUnit +
            FPlanner.Display.DisplayOffset;
          FPlanner.FOnPlannerLeftClick(FPlanner, Col - ColOffset, FromSel,
            FromSelPrecis, ToSel, ToSelPrecis);
        end
        else
        begin
          FromSel := Selection.Left + FPlanner.Display.DisplayStart;
          ToSel := 1 + Selection.Right + FPlanner.Display.DisplayStart;
          FromSelPrecis := FromSel * FPlanner.Display.DisplayUnit +
            FPlanner.Display.DisplayOffset;
          ToSelPrecis := ToSel * FPlanner.Display.DisplayUnit +
            FPlanner.Display.DisplayOffset;
          FPlanner.FOnPlannerLeftClick(FPlanner, Row - RowOffset, FromSel,
            FromSelPrecis, ToSel, ToSelPrecis);
        end;
      end;

      SyncPlanner;

      if not (OrigButton = mbRight) then
        Exit;
    end
    else
    begin
      FPlanner.FDownOnItem := True;

      if not FPlanner.SelectionAlways then
        HideSelection;

      if FPlanner.Sidebar.Orientation = soVertical then
      begin
        if (APlannerItem.ItemBegin < TopRow) and FPlanner.AutoItemScroll then
          TopRow := APlannerItem.ItemBegin;
      end
      else
      begin
        if (APlannerItem.ItemBegin < LeftCol) and FPlanner.AutoItemScroll then
          LeftCol := APlannerItem.ItemBegin;
      end;

      if Assigned(FPlanner.FOnItemLeftClick) then
      begin
        FMouseDown := False;
        FMouseDownMove := False;
        FMouseDownMoveFirst := False;
        FPlanner.FOnItemLeftClick(FPlanner, APlannerItem);
      end;
    end;

    APlannerItem := FPlanner.Items.Selected;

    if FPlanner.Sidebar.Orientation = soVertical then
    begin
      nplIt := FPlanner.Items.FocusItem(GridCoord.Y - RowOffset, GridCoord.X - ColOffset, X - GridRect.Left,
        (ssCtrl in Shift) or FPlanner.StickySelect);

      if FPlanner.AllowBackgroundItemSelection and not Assigned(nplIt) then
        nplIt := FPlanner.Items.FocusBkg(GridCoord.Y - RowOffset, GridCoord.X - ColOffset, X - GridRect.Left,
          (ssCtrl in Shift) or FPlanner.StickySelect);

      if (Assigned(nplIt)) and (APlannerItem <> nplIt) and not Assigned(APlannerItem) then
      begin
        FPlanner.ItemSelected(nplIt);
        if Self.CanFocus and (GetFocus <> Self.Handle) then
          Self.SetFocus;
      end;

      if (Assigned(nplIt)) and ((APlannerItem <> nplIt) or not FPlanner.EditOnSelectedClick) then
      begin
        FPlanner.ItemSelected(nplIt);
        if Self.CanFocus and (GetFocus <> Self.Handle) then
          Self.SetFocus;

        { direct move fix }
        if (FPlanner.DirectMove or nplIt.NotEditable)
          and not nplIt.FixedPos and (FPlanner.UserMode in [puNormal,
          puReadOnly]) then
        begin
          FItemXY := Point(nplIt.ItemPos, nplIt.ItemBegin);
          FItemXYS := Rect(nplIt.ItemPos, nplIt.ItemBegin, nplIt.ItemEnd, 0);

          //FMouseDownMove := not APlannerItem.FixedPos;
          FMouseDownMove := not nplIt.FixedPos;
          FMouseDownMoveFirst := FMouseDownMove;
          FMouseStart := FMouseDownMove;
          if FMemo.Visible then
            FMemo.DoExit;

          HintShowXY(X, Y, nplIt, nplIt.ItemSpanTimeStr);
          Exit;
        end;

        if FPlanner.EditDirect then
        begin
          APlannerItem := nplIt;
          APlannerItem.EnsureFullVisibility;
        end;
      end;

      if (APlannerItem = nplIt) and Assigned(APlannerItem) then
      begin
        GridRect := CellRectEx(APlannerItem.ItemPos + ColOffset,
          APlannerItem.ItemBegin);

        GridRectE := CellRectEx(APlannerItem.ItemPos + ColOffset,
          APlannerItem.ItemEnd - 1);

        if FPlanner.DragItemAlways and (APlannerItem.ReadOnly) then
        begin
          isSizing := (Cursor = crSize) or (Cursor = crSizeNS) or (Cursor = crSizeWE);
          if not isSizing then
            FMouseDownMove := true;
        end;

        ImgSize := 0;

        if Assigned(FPlanner.PlannerImages) and
          ((APlannerItem.ImageID >= 0) or
            (APlannerItem.FImageIndexList.Count > 0)) then
        begin
          iw := FPlanner.PlannerImages.Width;
          if APlannerItem.ImagePosition = ipHorizontal then
            ImgSize := (iw * APlannerItem.FImageIndexList.Count) + iw
          else
            ImgSize := iw;

          if APlannerItem.ImagePosition = ipVertical then
            ImgVSize := (iw * APlannerItem.FImageIndexList.Count) + iw
          else
            ImgVSize := iw;
        end;

        APlannerItem.CalcConflictRect(GridRect, ColWidthEx(nplIt.ItemPos),
          RowHeightEx(RowOffset), FPlanner.Sidebar.Orientation = soVertical);

        if APlannerItem.Focus then
        begin
          s := ConcatenateTextStrings(APlannerItem.Text);

          R := CellRectEx(GridCoord.X, GridCoord.Y);

          APlannerItem.CalcConflictRect(R, ColWidthEx(nplIt.ItemPos),
            RowHeightEx(1), FPlanner.Sidebar.Orientation = soVertical);

          R.Left := R.Left + FPlanner.TrackWidth;
          R.Top := R.Top - ((GridCoord.Y - APlannerItem.ItemBegin)
              * DefaultRowHeight) + 4;
          R.Bottom := R.Bottom + ((APlannerItem.ItemEnd - GridCoord.Y - 1)
              * DefaultRowHeight) + 4;

          if (APlannerItem.CaptionType <> ctNone) then
          begin
            tr := R;
            tr.Right := tr.Right - FPlanner.ItemGap;

            tr.Bottom := tr.Top + 16;

            if APlannerItem.ShowDeleteButton and
              (R.Right - R.Left - ImgSize > 32) then
            begin
              tr.Left := tr.Right - FPlanner.DeleteGlyph.Width;
              if PtInRect(tr, Point(X, Y)) then
              begin
                if Assigned(FPlanner.OnItemDelete) then
                  FPlanner.OnItemDelete(Self, APlannerItem);

                if FPlanner.AutoInsDel then
                begin
                  if Assigned(FPlanner.OnItemDeleted) then
                    FPlanner.OnItemDeleted(Self, APlannerItem);
                  FPlanner.FreeItem(APlannerItem);
                end;

                Exit;
              end;
              tr.Right := tr.Right - FPlanner.DeleteGlyph.Width;
            end;

            if APlannerItem.Attachement <> '' then
            begin
              tr.Left := tr.Right - FPlanner.AttachementGlyph.Width;

              if PtInRect(tr, Point(X, Y)) then
              begin
                AutoHandle := True;

                if Assigned(FPlanner.FOnItemAttachementClick) then
                  FPlanner.FOnItemAttachementClick(FPlanner, APlannerItem,
                    APlannerItem.Attachement, AutoHandle);
                if AutoHandle then
                  ShellExecute(0, 'open', PChar(APlannerItem.Attachement), nil,
                    nil, SW_NORMAL);
                Exit;
              end;

              tr.Right := tr.Right - FPlanner.AttachementGlyph.Width;
            end;

            if APlannerItem.URL <> '' then
            begin
              tr.Left := tr.Right - FPlanner.URLGlyph.Width;

              if PtInRect(tr, Point(X, Y)) then
              begin
                AutoHandle := True;

                if Assigned(FPlanner.FOnItemURLClick) then
                  FPlanner.FOnItemURLClick(FPlanner, APlannerItem,
                    APlannerItem.URL, AutoHandle);
                if AutoHandle then
                  ShellExecute(0, 'open', PChar(APlannerItem.URL), nil, nil,
                    SW_NORMAL);
                Exit;
              end;
            end;

            if (APlannerItem.CaptionType in [ctText, ctTimeText]) then
            begin
              if IsHtml(APlannerItem, APlannerItem.CaptionText, True) then

                if HTMLDrawEx(Canvas, APlannerItem.CaptionText, R,
                  FPlanner.PlannerImages, X, Y, -1, -1, 1, True, False, False,
                  True, True, False, APlannerItem.WordWrap
                  , False
                  , 1.0, FPlanner.URLColor, clNone, clNone, clGray, Anchor,
                  StrippedHTMLString, FocusAnchor, XSize, YSize, ml, hl, hr
                  , CR, CID, CV, CT, FPlanner.FImageCache, FPlanner.FContainer,
                  Handle
                ) then

                begin
                  if Assigned(FPlanner.FOnItemAnchorClick) then
                    FPlanner.FOnItemAnchorClick(FPlanner, APlannerItem, Anchor);
                  Exit;
                end;
            end;

            R.Top := R.Top + APlannerItem.FCaptionHeight;
          end;

          if IsHtml(APlannerItem, s, False) then
          begin
            Canvas.Font := APlannerItem.Font;

            if (APlannerItem.ImageID >= 0) and Assigned(FPlanner.PlannerImages) then
              R.Left := R.Left + ImgSize;

            if APlannerItem.Shadow and not APlannerItem.Background and
              (APlannerItem.Shape = psRect) and not FPlanner.TrackOnly then
            begin
              R.Right := R.Right - 5;
              R.Bottom := R.Bottom - 3;
            end
            else
            begin
              R.Right := R.Right - 2;
            end;

            R.Left := R.Left + 2;

            APlannerItem.CompletionAdapt(R);
            APlannerItem.ImageListAdapt(R);

            if HTMLDrawEx(Canvas, s, R, FPlanner.PlannerImages, X, Y, -1, -1,
              1, True, False, False, True, True, False, APlannerItem.WordWrap
              , False
              , 1.0, FPlanner.URLColor, clNone, clNone, clGray, Anchor,
              StrippedHTMLString, FocusAnchor, XSize, YSize, ml, hl, hr
              , CR, CID, CV, CT, FPlanner.FImageCache, FPlanner.FContainer,
              Handle
            ) then

            begin
              if CR.Right <> 0 then
              begin
                FormHandle(APlannerItem, CR, CID, CT, CV);

                If Assigned(FPlanner.FOnItemControlClick) then
                  FPlanner.FOnItemControlClick(Self, X, Y, APlannerItem, CID,
                    CT, CV);
                InvalidateRect(Handle, @CR, False);
              end;
              if Assigned(FPlanner.FOnItemAnchorClick) then
                FPlanner.FOnItemAnchorClick(FPlanner, APlannerItem, Anchor);
              Exit;
            end;
          end;
        end;

        if (Y < GridRect.Top + 3)
          and not APlannerItem.Background and not APlannerItem.FixedSize and
          (FPlanner.UserMode in [puNormal, puReadOnly]) then
        begin
          if FMemo.Visible then
            FMemo.DoExit;
          FItemXY := Point(APlannerItem.ItemPos, APlannerItem.ItemBegin);
          FItemXYS := Rect(APlannerItem.ItemPos, APlannerItem.ItemBegin,
            APlannerItem.ItemEnd, 0);
          FMouseDownSizeUp := not APlannerItem.FixedSize;
          FMouseStart := FMouseDownSizeUp;
          HintShowXY(X, Y, APlannerItem, APlannerItem.ItemStartTimeStr);
          Exit;
        end;

        {
         if (Message.YPos + 5 > GridRect.Bottom + (APlannerItem.ItemEnd - APlannerItem.ItemBegin - 1) *
         DefaultRowHeight) and
         not APlannerItem.Background and not APlannerItem.FixedSize then
         }
        if (Y + 5 > GridRectE.Bottom) and not APlannerItem.Background and not APlannerItem.FixedSize and
          (FPlanner.UserMode in [puNormal, puReadOnly]) then
        begin
          if FMemo.Visible then
            FMemo.DoExit;

          FItemXY := Point(APlannerItem.ItemPos, APlannerItem.ItemEnd);
          FItemXYS := Rect(APlannerItem.ItemPos, APlannerItem.ItemBegin, APlannerItem.ItemEnd, 0);
          FMouseDownSizeDown := not APlannerItem.FixedSize;
          FMouseStart := FMouseDownSizeDown;

          HintShowXY(X, Y, APlannerItem, APlannerItem.ItemEndTimeStr);
          Exit;
        end;

        if Assigned(FPlanner.PlannerImages) and Assigned(FPlanner.FOnItemImageClick) then
        begin
          if APlannerItem.ImagePosition = ipHorizontal then
          begin
            if (Y > GridRect.Top) and (Y < GridRect.Top + FPlanner.PlannerImages.Height + 3) and
              (X >= GridRect.Left) and (X < GridRect.Left + ImgSize) and
              ((APlannerItem.ImageID >= 0) or (APlannerItem.FImageIndexList.Count > 0)) then
            begin
              iw := FPlanner.PlannerImages.Width + 1;

              if (X < GridRect.Left + ImgSize) and (iw > 0) then
              begin
                if (((X - GridRect.Left + 8) div iw) <= APlannerItem.FImageIndexList.Count) or (APlannerItem.ImageID >= 0) then
                  FPlanner.FOnItemImageClick(FPlanner, APlannerItem, ((X - GridRect.Left + 8) div iw) - 1);
              end;
              Exit;
            end;
          end
          else
          begin
            if (X > GridRect.Left) and (X < GridRect.Left + FPlanner.PlannerImages.Height + 3) and
              (Y >= GridRect.Top) and (Y < GridRect.Top + ImgVSize) and
              ((APlannerItem.ImageID >= 0) or (APlannerItem.FImageIndexList.Count > 0)) then
            begin
              iw := FPlanner.PlannerImages.Width + 1;

              if (X < GridRect.Left + ImgSize) and (iw > 0) then
              begin
                if (((X - GridRect.Left + 8) div iw) <= APlannerItem.FImageIndexList.Count) or (APlannerItem.ImageID >= 0) then
                  FPlanner.FOnItemImageClick(FPlanner, APlannerItem, ((Y - GridRect.Top) div iw));
              end;
              Exit;
            end;
          end;
        end;

        if ((X < GridRect.Left + FPlanner.TrackWidth + 2) or ((Y > GridRect.Top + 3) and
           (Y < GridRect.Top + APlannerItem.GetCaptionHeight) and
           (APlannerItem.ItemBegin = GridCoord.Y) and (X > GridRect.Left)))
            and not APlannerItem.Background and not APlannerItem.FixedPos and
           (FPlanner.UserMode in [puNormal, puReadOnly]) then
        begin
          FItemXY := Point(APlannerItem.ItemPos, APlannerItem.ItemBegin);
          FItemXYS := Rect(APlannerItem.ItemPos, APlannerItem.ItemBegin, APlannerItem.ItemEnd, 0);
          FMouseDownMove := not APlannerItem.FixedPos;
          FMouseDownMoveFirst := FMouseDownMove;
          FMouseStart := FMouseDownMove;

          if FMemo.Visible then
            FMemo.DoExit;

          HintShowXY(X, Y, APlannerItem, APlannerItem.ItemSpanTimeStr);
          Exit;
        end;

        if APlannerItem.NotEditable and FPlanner.DirectMove and not APlannerItem.FixedPos
           and (FPlanner.UserMode in [puNormal, puReadOnly]) then
        begin
          FItemXY := Point(APlannerItem.ItemPos, APlannerItem.ItemBegin);
          FItemXYS := Rect(APlannerItem.ItemPos, APlannerItem.ItemBegin, APlannerItem.ItemEnd, 0);
          FMouseDownMove := not APlannerItem.FixedPos;
          FMouseDownMoveFirst := FMouseDownMove;
          FMouseStart := FMouseDownMove;

          HintShowXY(X, Y, APlannerItem, APlannerItem.ItemSpanTimeStr);
          Exit;
        end;

        if APlannerItem.NotEditable then
          Exit;

        if FPlanner.EditOnSelectedClick then
        begin
          GridRect := CellRectEx(APlannerItem.ItemPos + ColOffset, APlannerItem.ItemBegin);
          StartEditCol(GridRect, APlannerItem, X, Y);
        end;
      end
      else
        if not Assigned(nplIt) then
          inherited;
    end
    else
    begin
      nplIt := FPlanner.Items.FocusItem(GridCoord.X - ColOffset, GridCoord.Y - RowOffset, Y - GridRect.Top, ssCtrl in Shift);

      if FPlanner.AllowBackgroundItemSelection and not Assigned(nplIt) then
        nplIt := FPlanner.Items.FocusBkg(GridCoord.X - ColOffset, GridCoord.Y - RowOffset, Y - GridRect.Top, ssCtrl in Shift);

      if Assigned(nplIt) and ((APlannerItem <> nplIt) or not FPlanner.EditOnSelectedClick) then
      begin
        FPlanner.ItemSelected(nplIt);
        if Self.CanFocus and (GetFocus <> Self.Handle) then
          Self.SetFocus;

        // Direct move handling or always move of readonly items
        if (FPlanner.DirectMove or nplIt.NotEditable) {and (Cursor = crSizeAll)}
          and not nplIt.FixedPos and (FPlanner.UserMode in [puNormal, puReadOnly]) then
        begin
          FItemXY := Point(nplIt.ItemBegin, nplIt.ItemPos);
          FItemXYS := Rect(nplIt.ItemPos, nplIt.ItemBegin, nplIt.ItemEnd, 0);
          FMouseDownMove := not nplIt.FixedPos;
          FMouseDownMoveFirst := FMouseDownMove;
          FMouseStart := FMouseDownMove;
          if FMemo.Visible then
            FMemo.DoExit;

          HintShowXY(X, Y, nplIt, nplIt.ItemSpanTimeStr);
        end;

        if FPlanner.EditDirect then
        begin
          APlannerItem := nplIt;
          APlannerItem.EnsureFullVisibility;
        end;
      end;

      if (Assigned(nplIt)) and (APlannerItem <> nplIt) and not Assigned(APlannerItem) then
      begin
        FPlanner.ItemSelected(nplIt);
        if Self.CanFocus and (GetFocus <> Self.Handle) then
          Self.SetFocus;
      end;

      if (APlannerItem = nplIt) and Assigned(APlannerItem) then
      begin
        GridRect := CellRectEx(APlannerItem.ItemBegin,
          APlannerItem.ItemPos + RowOffset);

        ImgSize := 0;

        if Assigned(FPlanner.PlannerImages) and
          ((APlannerItem.ImageID >= 0) or
          (APlannerItem.FImageIndexList.Count > 0)) then
        begin
          iw := FPlanner.PlannerImages.Width;

          if APlannerItem.ImagePosition = ipHorizontal then
          begin
            ImgSize := (iw * APlannerItem.FImageIndexList.Count) + iw;
          end;

          if APlannerItem.ImagePosition = ipVertical then
          begin
            ImgVSize := (iw * APlannerItem.FImageIndexList.Count) + iw
          end
          else
            ImgVSize := iw;
        end;

        APlannerItem.CalcConflictRect(GridRect, ColWidthEx(nplIt.ItemPos),
          RowHeightEx(RowOffset), FPlanner.Sidebar.Orientation = soVertical);

        if APlannerItem.Focus then
        begin
          s := ConcatenateTextStrings(APlannerItem.Text);

          R := CellRectEx(GridCoord.X, GridCoord.Y);

          APlannerItem.CalcConflictRect(R, ColWidthEx(nplIt.ItemPos),
            RowHeightEx(nplIt.ItemPos),
            FPlanner.Sidebar.Orientation = soVertical);

          R.Top := R.Top + FPlanner.TrackWidth;
          R.Left := R.Left - ((GridCoord.X - APlannerItem.ItemBegin) * DefaultColWidth) + 4;
          R.Right := R.Right + ((APlannerItem.ItemEnd - GridCoord.X - 1) * DefaultColWidth) + 4;

          if APlannerItem.CaptionType <> ctNone then
          begin
            tr := R;
            tr.Right := tr.Right - 4 - FPlanner.TrackWidth;

            tr.Bottom := tr.Top + 16;

            if APlannerItem.ShowDeleteButton then
            begin
              tr.Left := tr.Right - FPlanner.DeleteGlyph.Width;
              if PtInRect(tr, Point(X, Y)) then
              begin
                if Assigned(FPlanner.OnItemDelete) then
                  FPlanner.OnItemDelete(Self, APlannerItem);

                if FPlanner.AutoInsDel then
                begin
                  if Assigned(FPlanner.OnItemDeleted) then
                    FPlanner.OnItemDeleted(Self, APlannerItem);
                  FPlanner.FreeItem(APlannerItem);
                end;
                Exit;
              end;
              tr.Right := tr.Right - FPlanner.DeleteGlyph.Width;
            end;

            if APlannerItem.Attachement <> '' then
            begin
              tr.Left := tr.Right - FPlanner.AttachementGlyph.Width;

              if PtInRect(tr, Point(X, Y)) then
              begin
                AutoHandle := True;

                if Assigned(FPlanner.FOnItemAttachementClick) then
                  FPlanner.FOnItemAttachementClick(FPlanner, APlannerItem,
                    APlannerItem.Attachement, AutoHandle);
                if AutoHandle then
                  ShellExecute(0, 'open', PChar(APlannerItem.Attachement), nil,
                    nil, SW_NORMAL);
                Exit;
              end;

              tr.Right := tr.Right - FPlanner.AttachementGlyph.Width;
            end;

            if APlannerItem.URL <> '' then
            begin
              tr.Left := tr.Right - FPlanner.URLGlyph.Width;

              if PtInRect(tr, Point(X, Y)) then
              begin
                AutoHandle := True;

                if Assigned(FPlanner.FOnItemURLClick) then
                  FPlanner.FOnItemURLClick(FPlanner, APlannerItem,
                    APlannerItem.URL, AutoHandle);
                if AutoHandle then
                  ShellExecute(0, 'open', PChar(APlannerItem.URL), nil, nil,
                    SW_NORMAL);
                Exit;
              end;
            end;

            if (APlannerItem.CaptionType in [ctText, ctTimeText]) then
            begin
              if IsHtml(APlannerItem, APlannerItem.CaptionText, True) then

                if HTMLDrawEx(Canvas, APlannerItem.CaptionText, R,
                  FPlanner.PlannerImages, X, Y, -1, -1, 1, True, False, False,
                  True, True, False, APlannerItem.WordWrap
                  , False
                  , 1.0, FPlanner.URLColor, clNone, clNone, clGray, Anchor,
                  StrippedHTMLString, FocusAnchor, XSize, YSize, ml, hl, hr
                  , CR, CID, CV, CT, FPlanner.FImageCache, FPlanner.FContainer,
                  Handle
                ) then

                begin
                  if Assigned(FPlanner.FOnItemAnchorClick) then
                    FPlanner.FOnItemAnchorClick(FPlanner, APlannerItem, Anchor);
                  Exit;
                end;

              R.Top := R.Top + APlannerItem.FCaptionHeight;
            end;
          end;

          if IsHtml(APlannerItem, s, False) then
          begin
            Canvas.Font := APlannerItem.Font;

            if (APlannerItem.ImageID >= 0) and Assigned(FPlanner.PlannerImages) then
              R.Left := R.Left + ImgSize;

            if APlannerItem.Shadow and not APlannerItem.Background and
              (APlannerItem.Shape = psRect) and not FPlanner.TrackOnly then
            begin
              R.Right := R.Right - 5;
              R.Bottom := R.Bottom - 3;
            end
            else
            begin
              R.Right := R.Right - 2;
            end;
            R.Left := R.Left + 2;

            APlannerItem.CompletionAdapt(R);
            APlannerItem.ImageListAdapt(R);

            if HTMLDrawEx(Canvas, s, R, FPlanner.PlannerImages, X, Y, -1, -1,
              1, True, False, False, True, True, False, APlannerItem.WordWrap
              , False
              , 1.0, FPlanner.URLColor, clNone, clNone, clGray, Anchor,
              StrippedHTMLString, FocusAnchor, XSize, YSize, ml, hl, hr
              , CR, CID, CV, CT, FPlanner.FImageCache, FPlanner.FContainer,
              Handle
            ) then

            begin
              if CR.Right <> 0 then
              begin
                OffsetRect(CR, -2, 2);
                FormHandle(APlannerItem, CR, CID, CT, CV);

                If Assigned(FPlanner.FOnItemControlClick) then
                  FPlanner.FOnItemControlClick(Self, X, Y, APlannerItem, CID,
                    CT, CV);
                InvalidateRect(Handle, @CR, False);
              end;
              if Assigned(FPlanner.FOnItemAnchorClick) then
                FPlanner.FOnItemAnchorClick(FPlanner, APlannerItem, Anchor);
              Exit;
            end;
          end;
        end;

        if (X < GridRect.Left + 3)
          and not APlannerItem.Background and not APlannerItem.FixedSize and
          (FPlanner.UserMode in [puNormal, puReadOnly]) then
        begin
          FItemXY := Point(APlannerItem.ItemBegin, APlannerItem.ItemPos);
          FItemXYS := Rect(APlannerItem.ItemPos, APlannerItem.ItemBegin,
            APlannerItem.ItemEnd, 0);
          FMouseDownSizeUp := not APlannerItem.FixedSize;
          FMouseStart := FMouseDownSizeUp;
          if FMemo.Visible then
            FMemo.DoExit;

          HintShowXY(X, Y, APlannerItem, APlannerItem.ItemStartTimeStr);
          Exit;
        end;

        GridRect := CellRectEx(APlannerItem.ItemEnd - 1,
          APlannerItem.ItemPos + RowOffset);

        if (X + 5 > GridRect.Right)
          and not APlannerItem.Background and not APlannerItem.FixedSize and
          (FPlanner.UserMode in [puNormal, puReadOnly]) then
        begin
          FItemXY := Point(APlannerItem.ItemEnd, APlannerItem.ItemPos);
          FItemXYS := Rect(APlannerItem.ItemPos, APlannerItem.ItemBegin,
            APlannerItem.ItemEnd, 0);
          FMouseDownSizeDown := not APlannerItem.FixedSize;
          FMouseStart := FMouseDownSizeDown;

          HintShowXY(X, Y, APlannerItem, APlannerItem.ItemEndTimeStr);
          if FMemo.Visible then
            FMemo.DoExit;
          Exit;
        end;

        APlannerItem.CalcConflictRect(GridRect, ColWidthEx(nplIt.ItemPos),
          RowHeightEx(nplIt.ItemPos),
          FPlanner.Sidebar.Orientation = soVertical);

        if (((Y < GridRect.Top + FPlanner.TrackWidth + 2) and (Y > GridRect.Top)) or
            ((Y > GridRect.Top + FPlanner.TrackWidth + 2) and
              (Y < GridRect.Top + FPlanner.TrackWidth + 2 +
                APlannerItem.GetCaptionHeight) and
              (APlannerItem.ItemPos = GridCoord.Y - RowOffset) and
              (X > R.Left + ImgSize)))
          and not APlannerItem.Background and not APlannerItem.FixedPos and
          (FPlanner.UserMode in [puNormal, puReadOnly]) then
        begin
          FItemXY := Point(APlannerItem.ItemBegin, APlannerItem.ItemPos);
          FItemXYS := Rect(APlannerItem.ItemPos, APlannerItem.ItemBegin,
            APlannerItem.ItemEnd, 0);
          FMouseDownMove := not APlannerItem.FixedPos;
          FMouseStart := FMouseDownMove;
          if FMemo.Visible then
            FMemo.DoExit;

          HintShowXY(X, Y, APlannerItem, APlannerItem.ItemSpanTimeStr);
          Exit;
        end;

        if Assigned(FPlanner.PlannerImages) and Assigned(FPlanner.FOnItemImageClick) then
        begin
          if APlannerItem.ImagePosition = ipHorizontal then
          begin
            if (X > R.Left) and (X < R.Left + ImgSize) and (Y > GridRect.Top) and
              (Y < GridRect.Top + FPlanner.PlannerImages.Height + 3) and
              ((APlannerItem.ImageID >= 0) or
                (APlannerItem.FImageIndexList.Count > 0)) then
            begin
              iw := FPlanner.PlannerImages.Width + 1;

              if (((X - R.Left) div iw) >= 0) and
                (((X - R.Left) div iw) < APlannerItem.ImageIndexList.Count) then
                FPlanner.FOnItemImageClick(FPlanner, APlannerItem,
                  ((X - R.Left) div iw));

              Exit;
            end;
          end
          else
          begin
            if (X > R.Left) and (X < R.Left + FPlanner.PlannerImages.Width + 3) and
              (Y >= GridRect.Top) and (Y < GridRect.Top + ImgVSize) and
              ((APlannerItem.ImageID >= 0) or (APlannerItem.FImageIndexList.Count > 0)) then
            begin
              iw := FPlanner.PlannerImages.Width + 1;

              if (X < R.Left + iw) and (iw > 0) then
              begin
                if (((X - R.Left + 8) div iw) <= APlannerItem.FImageIndexList.Count) or (APlannerItem.ImageID >= 0) then
                  FPlanner.FOnItemImageClick(FPlanner, APlannerItem, ((Y - GridRect.Top) div iw));
              end;
              Exit;
            end;
          end;
        end;

        if nplIt.NotEditable and FPlanner.DirectMove and not nplIt.FixedPos and
          (FPlanner.UserMode in [puNormal, puReadOnly]) then
        begin
          FItemXY := Point(nplIt.ItemBegin, nplIt.ItemPos);
          FItemXYS := Rect(nplIt.ItemPos, nplIt.ItemBegin, nplIt.ItemEnd, 0);
          FMouseDownMove := not nplIt.FixedPos;
          FMouseStart := FMouseDownMove;

          HintShowXY(X, Y, nplIt, nplIt.ItemSpanTimeStr);
          Exit;
        end;

        if APlannerItem.Focus then
        begin
          s := ConcatenateTextStrings(APlannerItem.Text);

          GridRect := CellRectEx(GridCoord.X, GridCoord.Y);
          APlannerItem.CalcConflictRect(GridRect, ColWidthEx(nplIt.ItemPos),
            RowHeightEx(nplIt.ItemPos),
            FPlanner.Sidebar.Orientation = soVertical);

          GridRect.Top := GridRect.Top + FPlanner.TrackWidth;
          GridRect.Left := GridRect.Left -
            ((GridCoord.X - APlannerItem.ItemBegin) * DefaultColWidth) + 4;
          GridRect.Right := GridRect.Right +
            ((APlannerItem.ItemEnd - GridCoord.X - 1) * DefaultColWidth) + 4;

          if (APlannerItem.CaptionType <> ctNone) then
            GridRect.Top := GridRect.Top + APlannerItem.FCaptionHeight;

          if IsHtml(APlannerItem, s, False) then
          begin
            Canvas.Font := APlannerItem.Font;

            if APlannerItem.Shadow and not APlannerItem.Background and
              (APlannerItem.Shape = psRect) and not FPlanner.TrackOnly then
            begin
              GridRect.Right := GridRect.Right - 3;
              GridRect.Bottom := GridRect.Bottom - 3;
            end;
            GridRect.Left := GridRect.Left + 2;

            APlannerItem.CompletionAdapt(GridRect);
            APlannerItem.ImageListAdapt(GridRect);

            if HTMLDrawEx(Canvas, s, GridRect, FPlanner.PlannerImages, X, Y,
              -1, -1, 1, True, False, False, True, True, False,
              APlannerItem.WordWrap
              , False
              , 1.0, FPlanner.URLColor, clNone, clNone, clGray, Anchor,
              StrippedHTMLString, FocusAnchor, XSize, YSize, ml, hl, hr
              , CR, CID, CV, CT, FPlanner.FImageCache, FPlanner.FContainer,
              Handle
            ) then

            begin
              if Assigned(FPlanner.FOnItemAnchorClick) then
                FPlanner.FOnItemAnchorClick(FPlanner, APlannerItem, Anchor);
            end;
          end;
        end;

        if APlannerItem.NotEditable then
          Exit;

        if FPlanner.EditOnSelectedClick then
        begin
          GridRect := CellRectEx(APlannerItem.ItemBegin,
            APlannerItem.ItemPos + RowOffset);

          StartEditRow(GridRect, APlannerItem, X, Y);
        end;
      end
      else
        if not Assigned(nplIt) then
          inherited;
    end;
  end;

  if OrigButton = mbRight then
  begin
    ColOffset := FPlanner.FSidebar.FColOffset;
    RowOffset := FPlanner.FSidebar.FRowOffset;

    if FMouseDownMove or FMouseDownSizeUp or FMouseDownSizeDown then
      Exit;

    GridCoord := MouseCoord(X, Y);
    GridRect := CellRectEx(GridCoord.X, GridCoord.Y);

    if FPlanner.Sidebar.Orientation = soVertical then
      APlannerItem := FPlanner.Items.FindItemPos(GridCoord.Y - RowOffset,
        GridCoord.X - ColOffset, X - GridRect.Left)
    else
      APlannerItem := FPlanner.Items.FindItemPos(GridCoord.X - ColOffset,
        GridCoord.Y - RowOffset, Y - GridRect.Top);

    if not Assigned(APlannerItem) or
      ((FPlanner.Sidebar.Orientation = soVertical) and
        (X > GridRect.Right - FPlanner.FItemGap)) or
      ((FPlanner.Sidebar.Orientation = soHorizontal) and
        (Y > GridRect.Bottom - FPlanner.FItemGap)) then
    begin
      if Assigned(FPlanner.FOnPlannerRightClick) then
      begin
        if FPlanner.Sidebar.Orientation = soVertical then
        begin
          FromSel := Selection.Top + FPlanner.Display.DisplayStart;
          ToSel := 1 + Selection.Bottom + FPlanner.Display.DisplayStart;
          FromSelPrecis := FromSel * FPlanner.Display.DisplayUnit +
            FPlanner.Display.DisplayOffset;
          ToSelPrecis := ToSel * FPlanner.Display.DisplayUnit +
            FPlanner.Display.DisplayOffset;

          FPlanner.FOnPlannerRightClick(FPlanner, Col - ColOffset, FromSel,
            FromSelPrecis, ToSel, ToSelPrecis);
        end
        else
        begin
          FromSel := Selection.Left + FPlanner.Display.DisplayStart;
          ToSel := 1 + Selection.Right + FPlanner.Display.DisplayStart;
          FromSelPrecis := FromSel * FPlanner.Display.DisplayUnit +
            FPlanner.Display.DisplayOffset;
          ToSelPrecis := ToSel * FPlanner.Display.DisplayUnit +
            FPlanner.Display.DisplayOffset;
          FPlanner.FOnPlannerRightClick(FPlanner, Row - RowOffset, FromSel,
            FromSelPrecis, ToSel, ToSelPrecis);
        end;
      end;
    end;

    if Assigned(APlannerItem) then
    begin
      ScreenPoint := ClientToScreen(Point(X, Y));

      if Assigned(FPlanner.OnItemRightClick) then
        FPlanner.OnItemRightClick(FPlanner, APlannerItem);

      if Assigned(APlannerItem.PopupMenu) then
      begin
        if Assigned(FPlanner.OnItemPopupPrepare) then
          FPlanner.OnItemPopupPrepare(FPlanner, APlannerItem.PopupMenu,
            APlannerItem);

        FPlanner.PopupPlannerItem := APlannerItem;
        APlannerItem.PopupMenu.PopupComponent := FPlanner;
        APlannerItem.PopupMenu.Popup(ScreenPoint.X, ScreenPoint.Y);
      end;

      if (Assigned(FPlanner.FItemPopup)) then
      begin
        if Assigned(FPlanner.OnItemPopupPrepare) then
          FPlanner.OnItemPopupPrepare(FPlanner, FPlanner.ItemPopup,
            APlannerItem);

        FPlanner.PopupPlannerItem := APlannerItem;
        FPlanner.ItemPopup.PopupComponent := FPlanner;
        FPlanner.FItemPopup.Popup(ScreenPoint.X, ScreenPoint.Y);
      end;
    end;

    if (Assigned(FPlanner.FGridPopup)) and (APlannerItem = nil) then
    begin
      ScreenPoint := ClientToScreen(Point(X, Y));
      FPlanner.PopupPlannerItem := nil;
      FPlanner.GridPopup.PopupComponent := FPlanner;
      FPlanner.GridPopup.Popup(ScreenPoint.X, ScreenPoint.Y);
    end;
  end;

  SyncPlanner;
end;

procedure TPlannerGrid.MouseUp(Button: TMouseButton; Shift: TShiftState;
  X, Y: Integer);
var
  R, C, i, frompos, topos: Integer;
  isSideBar: Boolean;
  plIt: TPlannerItem;
begin
  if (csDesigning in ComponentState) then
  begin
    Exit;
  end;
  if Button = mbLeft then
    ReleaseCapture;

  if FCurrCtrlR.Right <> 0 then
    InvalidateRect(Handle, @FCurrCtrlR, False);
  inherited;

  FPlanner.DoMouseUp(FPlanner, Button, Shift, X, Y);

  MouseToCell(X, Y, C, R);

  if FMouseDown or (Button = mbRight) then
  begin
    if FPlanner.Sidebar.Orientation = soVertical then
    begin
      isSideBar := False;
      case FPlanner.Sidebar.Position of
        spLeft:
          isSideBar := (C = 0);
        spRight:
          isSideBar := (C = ColCount - 1);
        spLeftRight:
          isSideBar := (C = 0) or (C = ColCount - 1);
      end;

      if isSideBar then
      begin
        if Button = mbLeft then
          FPlanner.DoSideBarClick(FPlanner, R);
        if Button = mbRight then
          FPlanner.DoSideBarRightClick(FPlanner, R);
      end;
    end
    else
    begin
      if FPlanner.Sidebar.Visible and (R = 0) then
      begin
        if Button = mbLeft then
          FPlanner.DoSideBarClick(FPlanner, C);
        if Button = mbRight then
          FPlanner.DoSideBarRightClick(FPlanner, C);
      end;
    end;
  end;

  if FMouseRelease then
  begin
    FMouseRelease := False;
    FMouseDown := False;
    FMouseDownMove := False;
    FMouseDownSizeUp := False;
    FMouseDownSizeDown := False;
    HintHide;
    Exit;
  end;

  if Button = mbLeft then
  begin
    if FPlanner.Mode.FullHalfDay then
      CorrectSelection;


    if not FMouseDownMove and not FMouseDownSizeUp and not FMouseDownSizeDown
      and not FMouseUnSelect and FPlanner.ContinuousSelect
      and FPlanner.DisjunctSelect then
    begin
      if FPlanner.Sidebar.Position = spTop then
      begin
        frompos := Selection.Top;
        topos := Selection.Bottom - 1;
      end
      else
      begin
        frompos := Selection.Left;
        topos := Selection.Right - 1;
      end;

      for i := frompos to topos do
      begin
        with FPlanner.FSelections.Add do
        begin
          SelBegin := FPlanner.SelItemBegin;
          SelEnd := FPlanner.SelItemEnd;
          SelPos := i;
        end;
        FPlanner.UpdateSelection(FPlanner.SelItemBegin, FPlanner.SelItemEnd,
         i, True);
      end;
    end;


    if not FMouseDownMove and not FMouseDownSizeUp and not FMouseDownSizeDown
      and not FMouseUnSelect and (ssCtrl in Shift)
      and FPlanner.DisjunctSelect then
    begin
      with FPlanner.FSelections.Add do
      begin
        SelBegin := FPlanner.SelItemBegin;
        SelEnd := FPlanner.SelItemEnd;
        SelPos := FPlanner.SelPosition;
      end;
      FPlanner.UpdateSelection(FPlanner.SelItemBegin, FPlanner.SelItemEnd, FPlanner.SelPosition, True);
    end;

    if not(ssCtrl in Shift) and FPlanner.DisjunctSelect then
    begin
      with FPlanner.FSelections.Add do
      begin
        SelBegin := FPlanner.SelItemBegin;
        SelEnd := FPlanner.SelItemEnd;
        SelPos := FPlanner.SelPosition;
        FPlanner.UpdateSelection(SelBegin, SelEnd, SelPos, True);
      end;
    end;

    {
    if not (ssCtrl in Shift) and (FPlanner.Selections.Count > 0) and FPlanner.DisjunctSelect then
    begin
      FPlanner.Selections.Clear;
    end;
    }

    with FPlanner.Items do
    begin
      if Assigned(Selected) then
      begin
        if FMouseDownMove then
        begin
          HintHide;
          if (FItemXYS.Top <> Selected.ItemBegin) or
            (FItemXYS.Left <> Selected.ItemPos) or
            (FItemXYS.Right <> Selected.ItemEnd) or
            (Selected.BeginOffset <> 0) or (Selected.EndOffset <> 0) then
            try
              FPlanner.ItemMoved(Selected, FItemXYS.Top, FItemXYS.Right,
                FItemXYS.Left, Selected.ItemBegin, Selected.ItemEnd,
                Selected.ItemPos);
              // call item moved too for linked items!
              FPlanner.Items.MoveLinks(Selected);

            except
              FMouseDown := False;
              FMouseDownMove := False;
              FMouseDownSizeUp := False;
              FMouseDownSizeDown := False;
            end;
        end;

        if FMouseDownSizeUp then
        begin
          HintHide;
          try
            FPlanner.ItemSized(Selected, FItemXYS.Top, FItemXYS.Right,
              Selected.ItemBegin, Selected.ItemEnd);
            SizeLinks(Selected);
          except
            FMouseDown := False;
            FMouseDownMove := False;
            FMouseDownSizeUp := False;
            FMouseDownSizeDown := False;
          end;
        end;

        if FMouseDownSizeDown then
        begin
          HintHide;
          try
            FPlanner.ItemSized(Selected, FItemXYS.Top, FItemXYS.Right,
              Selected.ItemBegin, Selected.ItemEnd);
            SizeLinks(Selected);
          except

            FMouseDown := False;
            FMouseDownMove := False;
            FMouseDownSizeUp := False;
            FMouseDownSizeDown := False;
          end;
        end;
      end;
    end;
    FMouseDown := False;
    FMouseDownMove := False;
    FMouseDownSizeUp := False;
    FMouseDownSizeDown := False;
  end;

  if not FPlanner.FDownOnItem and FPlanner.AutoCreateOnSelect then
  begin
    if not FPlanner.Items.HasItemInt(FPlanner.SelItemBegin, FPlanner.SelItemEnd, FPLanner.SelPosition) then
    begin
      plIt := FPlanner.CreateItemAtSelection;
      if Assigned(FPlanner.FOnItemCreated) then
        FPlanner.FOnItemCreated(FPlanner, plIt);
    end;
    FPlanner.FDownOnItem := False;
  end;
end;


procedure TPlannerGrid.WMNotify(var Message: TWMNotify);
var
  buffer: array [0 .. 255] of Char;
  pt: TPoint;
  plIt: TPlannerItem;
  di: PNMTTDispInfo;
  ATitle, AText: string;
  AIcon: Integer;
  cell: TPoint;
  len1, len2, i: Integer;

begin
  if not(Integer(Message.NMHdr^.hwndFrom) = Integer(FHToolTip)) then
    Exit;
  with Message.NMHdr^ do
    case Code of
    TTN_NEEDTEXT:
      begin
        if not FPlanner.Balloon.Enable then
          Exit;
        di := PNMTTDispInfo(TMessage(Message).LParam);
        GetCursorPos(pt);
        pt := ScreenToClient(pt);

        plIt := FPlanner.XYToItem(pt.X, pt.Y);

        cell := FPlanner.XYToCell(pt.X, pt.Y);

        if Assigned(plIt) then
        begin
          if (plIt.CaptionType = ctTime) or (plIt.CaptionText = '') then
          begin
            ATitle := plit.ItemSpanTimeStr;
          end
          else
          begin
            ATitle := HTMLStrip(plIt.CaptionText);
            ATitle := UnFixMarkUp(ATitle);
          end;

          if IsRtf(plIt.NotesText) then
          begin
            if not FPlanner.RichEdit.Visible then
            begin
              FPlanner.TextToRich(plIt.NotesText);
              AText := FPlanner.FRichEdit.Text;
            end;
          end
          else
            AText := HTMLStrip(plIt.NotesText);

          AText := UnFixMarkUp(AText);
          len1 := Length(AText);
          len2 := SizeOf(FToolTipBuffer) div 4;

          // balloon tooltip cannot handle tabs well
          i := 1;
          while i < len1 do
          begin
            if (AText[i] = #9) then
              AText[i] := #32;
            Inc(i);
          end;

          i := 1;
          if (AText <> '') then
            while ((AText[i] = #13) or (AText[i] = #10) or (AText[i] = #9)) do
              Inc(i);

          if len1 > len2 then
            AText := Copy(AText, i, len2 - 3) + '...'
          else if i > 1 then
            AText := Copy(AText, i, len1 - i + 1);
          AIcon := 1;
          // for some reason, balloon tips will not show multiline when there is no title  ...
          if ATitle = '' then
            ATitle := ' ';
          if Assigned(FPlanner.OnItemBalloon) then
            FPlanner.OnItemBalloon(FPlanner, plIt, ATitle, AText, AIcon);
        end
        else
        begin
          AText := '';
          ATitle := '';
          AIcon := 1;
          if Assigned(FPlanner.OnPlannerBalloon) then
            FPlanner.OnPlannerBalloon(FPlanner, cell.X, cell.Y, ATitle,
              AText, AIcon);
        end;
        strpcopy(FToolTipBuffer, AText);

        if Length(ATitle) > 99 then
          ATitle := Copy(ATitle, 1, 96) + '...';

        strpcopy(buffer, ATitle);

        di^.lpszText := @FToolTipBuffer;
        if FPlanner.Balloon.TextColor <> clNone then
          SendMessage(FHToolTip, TTM_SETTIPTEXTCOLOR,
            ColorToRGB(FPlanner.Balloon.TextColor), 0);
        if FPlanner.Balloon.BackgroundColor <> clNone then
          SendMessage(FHToolTip, TTM_SETTIPBKCOLOR,
            ColorToRGB(FPlanner.Balloon.BackgroundColor), 0);

        SendMessage(FHToolTip, TTM_SETMAXTIPWIDTH, 0, 400);
        SendMessage(FHToolTip, TTM_SETTITLE, AIcon, LParam(@buffer));
      end;
      TTN_SHOW:
        begin
        end;
      TTN_POP:
        begin
        end;
      end;
end;

procedure TPlannerGrid.MouseMove(Shift: TShiftState; X, Y: Integer);
var
  GridCoord: TGridCoord;
  CR, R, tr, ir, hr, cor: TRect;
  APlannerItem, plIt: TPlannerItem;
  dx, dy, h: Integer;
  s, Anchor, StrippedHTMLString, FocusAnchor: string;
  XSize, YSize, ml, hl: Integer;
  ColOffset, RowOffset: Integer;
  Allow: Boolean;
  MaxCol: Integer;
  ImgSize: Integer;
  NoClip: Boolean;
  CanSelect: Boolean;
  SideCorr: Integer;
  CID, CV, CT: string;
  minrow,maxrow,temprow: integer;
  samepos: boolean;

begin
  ColOffset := FPlanner.FSidebar.FColOffset;
  RowOffset := FPlanner.FSidebar.FRowOffset;
  GridCoord := MouseCoord(X, Y);
  FMouseRC := MouseCoord(X, Y);

  NoClip := (FPlanner.Mode.PlannerType in [plDay, plDayPeriod, plActiveDayPeriod, plMonth,
    plHalfDayPeriod, plWeek, plTimeLine]) and not FPlanner.Mode.Clip;

  if FPlanner.Sidebar.Visible and (FPlanner.Sidebar.Position in [spLeftRight,
    spRight]) then
  begin
    if GridCoord.X = ColCount - 1 then
      Exit;
  end;

  if FPlanner.Sidebar.Visible and (FPlanner.Sidebar.Position in [spLeft, spTop]) then
    SideCorr := 1
  else
    SideCorr := 0;

  if FScrolling then
  begin
    if GetTickCount - FScrollTime > FPlanner.FScrollDelay then
    FScrolling := False;
    inherited;
    Exit;
  end;

  if (gsSelecting = FGridState) and ((GridCoord.X <> Col) or (GridCoord.Y <> Row))  then
  begin
    if Assigned(FPlanner.OnPlannerSelectCell) then
    begin
      CanSelect := (GridCoord.X >= 0) and (GridCoord.Y >= 0);

      if CanSelect then
      begin
        if FPlanner.Sidebar.Position in [spLeft, spRight, spLeftRight] then
          FPlanner.OnPlannerSelectCell(FPlanner, GridCoord.Y, GridCoord.X, CanSelect)
        else
          FPlanner.OnPlannerSelectCell(FPlanner, GridCoord.X, GridCoord.Y, CanSelect);

        if not CanSelect then
          FGridState := gsNormal;
      end;

      if not CanSelect then
        Exit;
    end;
  end;

  FScrollTime := GetTickCount;

  if FMouseDownMove and FPlanner.DirectDrag and FPlanner.DragItem and
     Assigned(FPlanner.Items.Selected) then
  begin
    if (Cursor <> crSizeAll) and (Cursor <> crSizeNS) and (Cursor <> crSizeWE) then
    begin
      Allow := True;

      if Assigned(FPlanner.OnItemDrag) then
        FPlanner.OnItemDrag(FPlanner, FPlanner.Items.Selected, Allow);

      if Allow then
      begin
        inherited;

        HintHide;

        if FPlanner.DragItemImage then
        begin
          FPlanner.CreateDragImage(FPlanner.Items.Selected);
          FPlanner.Items.Selected.Visible := false;
        end;

        FPlanner.BeginDrag(True, -1);
        FMouseDownMove := False;
        Exit;
      end;
    end;
  end;

  if (ssCtrl in Shift)
    or (GetKeyState(VK_MENU) and $8000 = $8000) or FPlanner.DragItemAlways
  then
  begin
    if FMouseDownMove and FPlanner.DragItem and Assigned(FPlanner.Items.Selected)
      and not FPlanner.Dragging and ((Abs(FMouseXY.X - X) > 4) or (Abs(FMouseXY.Y - Y) > 4)) then
    begin
      Allow := True;

      if Assigned(FPlanner.OnItemDrag) then
        FPlanner.OnItemDrag(FPlanner, FPlanner.Items.Selected, Allow);

      if Allow then
      begin
        inherited;

        HintHide;

        if FPlanner.DragItemImage then
        begin
          FPlanner.CreateDragImage(FPlanner.Items.Selected);
          FPlanner.Items.Selected.Visible := false;
        end;

        FPlanner.BeginDrag(True, -1);
        FMouseDownMove := False;
        Exit;
      end;
    end;
  end;

  { Handles vertical planner mode }
  if FPlanner.Sidebar.Orientation = soVertical then
  begin
    if FMouseDownMove and Assigned(FPlanner.Items.Selected) then
    begin
      if (ssCtrl in Shift) and FMouseDownMoveFirst and FPlanner.CtrlDragCopy then
      begin
        FMouseDownMoveFirst := False;
        plIt := FPlanner.CreateItem;
        plIt.Assign(FPlanner.Items.Selected);

        if Assigned(FPlanner.OnItemCreated) then
          FPlanner.OnItemCreated(FPlanner, plIt);

        FPlanner.UpdateItem(plIt);
      end;

      dy := (Y - FMouseXY.Y) div DefaultRowHeight;
      dx := (GridCoord.X - ColOffset - FItemXY.X);

      if FPlanner.Items.Selected.FixedPosition then
        dx := 0;

      if FPlanner.Items.Selected.FixedTime then
        dy := 0;

      case FPlanner.Sidebar.Position of
        spLeft:
          MaxCol := ColCount - 1;
        spRight:
          MaxCol := ColCount - 2;
        spLeftRight:
          MaxCol := ColCount - 3
        else
          MaxCol := ColCount - 1;
      end;

      if not FPlanner.Sidebar.Visible then
        MaxCol := ColCount - 1;

      with FPlanner.Items.Selected do
      begin
        h := ItemEnd - ItemBegin + BeginOffset + EndOffset;

        if ((ItemBegin <> FItemXY.Y + dy) or (ItemPos <> FItemXY.X + dx)) and
          (FItemXY.X + dx >= 0) and not FPlanner.Items.HasItemInt(FItemXY.Y + dy, FItemXY.Y + dy + h, FItemXY.X + dx) and
          FPlanner.ItemInSel(FItemXY.Y + dy, FItemXY.Y + dy + h, FItemXY.X + dx) and
          (((FItemXY.Y + dy + h <= RowCount) and (FItemXY.Y + dy >= 0)) or NoClip) and (FItemXY.X + dx <= MaxCol) then
        begin
          Allow := True;

          if Assigned(FPlanner.FOnItemMoving) then
            FPlanner.FOnItemMoving(FPlanner, FPlanner.Items.Selected,
              (FItemXY.Y + dy) - ItemBegin,
              (FItemXY.X + dx) - ItemPos, Allow);

          if not Allow then
          begin
            FMouseRelease := True;
            SendMessage(Handle, WM_LBUTTONUP, 0, 0);
            Exit;
          end;

          ir := FPlanner.Items.Selected.GetGridRect;
          FPlanner.Items.BeginUpdate;

          MoveItem(FItemXY.Y + dy, FItemXY.Y + dy + h, FItemXY.X + dx, FItemXY.Y);
          FPlanner.Items.ResetUpdate;

          FPlanner.FGrid.InvalidateCellRect(ir);

          FPlanner.Items.Selected.Repaint;

          // Check here if scroll required
          if (ItemEnd - TopRow >= VisibleRowCount) and
            (TopRow + VisibleRowCount < RowCount) and (Y > FMouseXY.Y) then
          begin
            TopRow := TopRow + 1;

            if FPlanner.ScrollSmooth then
              FScrolling := True;

            FMouseXY.Y := FMouseXY.Y - DefaultRowHeight;
          end;

          if (ItemBegin <= TopRow) and (TopRow > 0) then
          begin
            TopRow := TopRow - 1;
            if FPlanner.ScrollSmooth then
              FScrolling := True;
            FMouseXY.Y := FMouseXY.Y + DefaultRowHeight;
          end;

          if FPlanner.ScrollSmooth then
          begin
            if (ItemPos + SideCorr <= LeftCol) and (LeftCol > SideCorr) and
              (LeftCol > FixedCols) then
            begin
              LeftCol := LeftCol - 1;
              FScrolling := True;
            end;

            if (ItemPos + SideCorr >= VisibleColCount + LeftCol) and
              (LeftCol + VisibleColCount < ColCount) then
            begin
              LeftCol := LeftCol + 1;
              FScrolling := True;
            end;
          end;

          HintShowXY(X, Y, FPlanner.Items.Selected, FPlanner.Items.Selected.ItemSpanTimeStr);
        end;
      end;
      Exit;
    end;

    if FMouseDownSizeUp and Assigned(FPlanner.Items.Selected) then
    begin
      dy := (Y - FMouseXY.Y) div DefaultRowHeight;
      with FPlanner.Items.Selected do
      begin
        if (ItemBegin <> FItemXY.Y + dy) and (FItemXY.Y + dy >= 0) and
          FPlanner.ItemInSel(FItemXY.Y + dy, ItemEnd, ItemPos) and
          (FItemXY.Y + dy < ItemEnd) and not FPlanner.Items.HasItemInt(FItemXY.Y + dy, ItemEnd, ItemPos) then
        begin
          Allow := True;

          if Assigned(FPlanner.FOnItemSizing) then
            FPlanner.FOnItemSizing(FPlanner, FPlanner.Items.Selected,
              FItemXY.Y + dy - ItemBegin, 0, Allow);

          if not Allow then
          begin
            FMouseRelease := True;
            SendMessage(Handle, WM_LBUTTONUP, 0, 0);
            Exit;
          end;

          ir := FPlanner.Items.Selected.GetGridRect;
          FPlanner.Items.BeginUpdate;
          SizeItem(FItemXY.Y + dy, ItemEnd);
          FPlanner.Items.ResetUpdate;

          FPlanner.FGrid.InvalidateCellRect(ir);
          FPlanner.Items.Selected.Repaint;

          { Check here if scroll required }
          if (ItemBegin <= TopRow) and (TopRow > 0) then
          begin
            TopRow := TopRow - 1;
            if FPlanner.ScrollSmooth then
              FScrolling := True;

            FMouseXY.Y := FMouseXY.Y + DefaultRowHeight;
          end;

          HintShowXY(X, Y, FPlanner.Items.Selected, FPlanner.Items.Selected.ItemStartTimeStr);
        end;
      end;
      Exit;
    end;

    if FMouseDownSizeDown and Assigned(FPlanner.Items.Selected) then
    begin
      dy := (Y - FMouseXY.Y) div DefaultRowHeight;
      with FPlanner.Items.Selected do
      begin

        if ((ItemEnd <> FItemXY.Y + dy)) and (FItemXY.Y + dy >= 0) and
          (FItemXY.Y + dy <= RowCount) and (FItemXY.Y + dy > ItemBegin) and
          FPlanner.ItemInSel(ItemBegin, FItemXY.Y + dy, ItemPos)
          and not FPlanner.Items.HasItemInt(ItemBegin, FItemXY.Y + dy, ItemPos) then
        begin
          Allow := True;

          if Assigned(FPlanner.FOnItemSizing) then
            FPlanner.FOnItemSizing(FPlanner, FPlanner.Items.Selected, 0, FItemXY.Y + dy - ItemEnd, Allow);

          if not Allow then
          begin
            FMouseRelease := True;
            SendMessage(Handle, WM_LBUTTONUP, 0, 0);
            Exit;
          end;

          ir := FPlanner.Items.Selected.GetGridRect;
          FPlanner.Items.BeginUpdate;
          SizeItem(ItemBegin, FItemXY.Y + dy);

          FPlanner.Items.ResetUpdate;
          FPlanner.FGrid.InvalidateCellRect(ir);
          FPlanner.Items.Selected.Repaint;

          { Check here if scroll required }
          if (ItemEnd - TopRow >= VisibleRowCount) and
            (TopRow + VisibleRowCount < RowCount) then
          begin
            TopRow := TopRow + 1;
            if FPlanner.ScrollSmooth then
              FScrolling := True;

            FMouseXY.Y := FMouseXY.Y - DefaultRowHeight;
          end;

          HintShowXY(X, Y, FPlanner.Items.Selected, FPlanner.Items.Selected.ItemEndTimeStr);
        end;
      end;
      Exit;
    end;
  end
  else

  // Handles horizontal planner mode
  begin
    if FMouseDownMove and Assigned(FPlanner.Items.Selected) then
    begin
      if (ssCtrl in Shift) and FMouseDownMoveFirst and FPlanner.CtrlDragCopy then
      begin
        FMouseDownMoveFirst := False;
        plIt := FPlanner.CreateItem;
        plIt.Assign(FPlanner.Items.Selected);
        if Assigned(FPlanner.OnItemCreated) then
          FPlanner.OnItemCreated(Self, plIt);
      end;

      dx := (X - FMouseXY.X) div DefaultColWidth;
      dy := (GridCoord.Y - RowOffset - FItemXY.Y);

      if FPlanner.Items.Selected.FixedPosition then
        dy := 0;

      if FPlanner.Items.Selected.FixedTime then
        dx := 0;

      if FPlanner.Mode.FullHalfDay then
        if not Odd(FPlanner.Items.Selected.BeginOffset + FItemXY.X + dx)
        {or (FItemXY.X + dx <= 0)} then
          Exit;
{$IFDEF TMSDEBUG}
      outputdebugstring(PChar('dx:' + IntToStr(dx)));
{$ENDIF}
      with FPlanner.Items.Selected do
      begin
        h := ItemEnd - ItemBegin;
        if ((ItemBegin <> FItemXY.X + dx) or (ItemPos <> FItemXY.Y + dy)) and
          (FItemXY.Y + dy >= 0) and not FPlanner.Items.HasItemInt(FItemXY.X + dx, FItemXY.X + dx + h, FItemXY.Y + dy) and
          FPlanner.ItemInSel(FItemXY.X + dx, FItemXY.X + dx + h, FItemXY.Y + dy) and
          (((FItemXY.X + dx + h <= ColCount) and (FItemXY.X + dx >= 0)
            ) or NoClip) then
        begin
          Allow := True;
          if Assigned(FPlanner.FOnItemMoving) then
            FPlanner.FOnItemMoving(FPlanner, FPlanner.Items.Selected,
              (FItemXY.X + dx) - ItemBegin,
              (FItemXY.Y + dy) - ItemPos, Allow);

          if not Allow then
          begin
            FMouseRelease := True;
            SendMessage(Handle, WM_LBUTTONUP, 0, 0);
            Exit;
          end;

          ir := FPlanner.Items.Selected.GetGridRect;

          FPlanner.Items.BeginUpdate;

          samepos := (FPlanner.Items.Selected.ItemPos = FItemXY.Y + dy);

          MoveItem(FItemXY.X + dx, FItemXY.X + dx + h, FItemXY.Y + dy, FItemXY.X);
          FPlanner.Items.ResetUpdate;

          if FPlanner.ShowLinks and Assigned(FPlanner.Items.Selected.LinkedItem) then
          begin
            if samepos then
            begin
              minrow := FPlanner.Items.Selected.ItemPos + FPlanner.FGrid.FixedRows;
              maxrow := FPlanner.Items.Selected.LinkedItem.ItemPos + FPlanner.FGrid.FixedRows;

              if minrow > maxrow then
              begin
                temprow := maxrow;
                maxrow := minrow;
                minrow := temprow;
              end;

              FPlanner.FGrid.RepaintRect(Rect(FPlanner.FGrid.LeftCol, minrow,
                                         FPlanner.FGrid.LeftCol + FPlanner.FGrid.VisibleColCount - 1, maxrow))
            end
            else
              Invalidate;
          end
          else
          begin
            FPlanner.FGrid.InvalidateCellRect(ir);
            FPlanner.Items.Selected.Repaint;
          end;

          // Check here if scroll required
          if (ItemEnd - LeftCol >= VisibleColCount) and (EndOffset = 0) and
            (BeginOffset = 0) and (LeftCol + VisibleColCount < ColCount) then
          begin
            LeftCol := LeftCol + 1;
            if FPlanner.ScrollSmooth then
              FScrolling := True;
            FMouseXY.X := FMouseXY.X - DefaultColWidth;
          end;

          if (ItemBegin <= LeftCol) and (LeftCol > 0) and (EndOffset = 0) and
            (BeginOffset = 0) then
          begin
            LeftCol := LeftCol - 1;
            if FPlanner.ScrollSmooth then
              FScrolling := True;
            FMouseXY.X := FMouseXY.X + DefaultColWidth;
          end;

          if (ItemPos - TopRow + SideCorr >= VisibleRowCount) and
            (TopRow + VisibleRowCount < RowCount) then
          begin
            TopRow := TopRow + 1;
            if FPlanner.ScrollSmooth then
              FScrolling := True;
            FMouseXY.Y := FMouseXY.Y + DefaultRowHeight;
          end;

          if (ItemPos + SideCorr <= TopRow) and (TopRow > SideCorr) then
          begin
            TopRow := TopRow - 1;
            if FPlanner.ScrollSmooth then
              FScrolling := True;
            FMouseXY.Y := FMouseXY.Y - DefaultRowHeight;
          end;

          HintShowXY(X, Y, FPlanner.Items.Selected, FPlanner.Items.Selected.ItemSpanTimeStr);
        end;
      end;
      Exit;
    end;

    if FMouseDownSizeUp and Assigned(FPlanner.Items.Selected) then
    begin
      dx := (X - FMouseXY.X) div DefaultColWidth;

      if FPlanner.Mode.FullHalfDay then
        if not Odd(FItemXY.X + dx) or (FItemXY.X + dx <= 0) then
          Exit;

      with FPlanner.Items.Selected do
      begin
        if (ItemBegin <> FItemXY.X + dx) and (FItemXY.X + dx >= 0) and
          FPlanner.ItemInSel(FItemXY.X + dx, ItemEnd, ItemPos) and
          (FItemXY.X + dx < ItemEnd) and not FPlanner.Items.HasItemInt(FItemXY.X + dx, ItemEnd, ItemPos) then
        begin
          Allow := True;

          if Assigned(FPlanner.FOnItemSizing) then
            FPlanner.FOnItemSizing(FPlanner, FPlanner.Items.Selected,
              (FItemXY.X + dx) - ItemBegin, 0, Allow);

          if not Allow then
          begin
            FMouseRelease := True;
            SendMessage(Handle, WM_LBUTTONUP, 0, 0);
            Exit;
          end;

          ir := FPlanner.Items.Selected.GetGridRect;
          FPlanner.Items.BeginUpdate;
          SizeItem(FItemXY.X + dx, ItemEnd);
          FPlanner.Items.ResetUpdate;

          if FPlanner.ShowLinks and Assigned(FPlanner.Items.Selected.LinkedItem) then
          begin
            minrow := FPlanner.Items.Selected.ItemPos + FPlanner.FGrid.FixedRows;
            maxrow := FPlanner.Items.Selected.LinkedItem.ItemPos + FPlanner.FGrid.FixedRows;

            if minrow > maxrow then
            begin
              temprow := maxrow;
              maxrow := minrow;
              minrow := temprow;
            end;

            FPlanner.FGrid.RepaintRect(Rect(FPlanner.FGrid.LeftCol, minrow,
                                       FPlanner.FGrid.LeftCol + FPlanner.FGrid.VisibleColCount - 1, maxrow))
          end
          else
            FPlanner.FGrid.InvalidateCellRect(ir);

          FPlanner.Items.Selected.Repaint;

          { Check here if scroll required }
          if (ItemBegin <= LeftCol) and (LeftCol > 0) then
          begin
            LeftCol := LeftCol - 1;
            if FPlanner.ScrollSmooth then
              FScrolling := True;

            FMouseXY.X := FMouseXY.X + DefaultColWidth;
          end;

          HintShowXY(X, Y, FPlanner.Items.Selected, FPlanner.Items.Selected.ItemStartTimeStr);
        end;
      end;
      Exit;
    end;

    if FMouseDownSizeDown and Assigned(FPlanner.Items.Selected) then
    begin
      dx := (X - FMouseXY.X) div DefaultColWidth;

      if FPlanner.Mode.FullHalfDay then
        if not Odd(FItemXY.X + dx) or (FItemXY.X + dx <= 0) then
          Exit;

      with FPlanner.Items.Selected do
      begin
        if ((ItemEnd <> FItemXY.X + dx)) and (FItemXY.X + dx >= 0) and
          (FItemXY.X + dx <= ColCount) and (FItemXY.X + dx > ItemBegin) and
          FPlanner.ItemInSel(ItemBegin, FItemXY.X + dx, ItemPos)
          and not FPlanner.Items.HasItemInt(ItemBegin, FItemXY.X + dx, ItemPos) then
        begin
          Allow := True;

          if Assigned(FPlanner.FOnItemSizing) then
            FPlanner.FOnItemSizing(FPlanner, FPlanner.Items.Selected, 0,
              (FItemXY.X + dx) - ItemEnd, Allow);

          if not Allow then
          begin
            FMouseRelease := True;
            SendMessage(Handle, WM_LBUTTONUP, 0, 0);
            Exit;
          end;

          ir := FPlanner.Items.Selected.GetGridRect;
          FPlanner.Items.BeginUpdate;
          SizeItem(ItemBegin, FItemXY.X + dx);
          FPlanner.Items.ResetUpdate;

          if FPlanner.ShowLinks and Assigned(FPlanner.Items.Selected.LinkedItem) then
          begin
            minrow := FPlanner.Items.Selected.ItemPos + FPlanner.FGrid.FixedRows;
            maxrow := FPlanner.Items.Selected.LinkedItem.ItemPos + FPlanner.FGrid.FixedRows;

            if minrow > maxrow then
            begin
              temprow := maxrow;
              maxrow := minrow;
              minrow := temprow;
            end;

            FPlanner.FGrid.RepaintRect(Rect(FPlanner.FGrid.LeftCol, minrow,
                                       FPlanner.FGrid.LeftCol + FPlanner.FGrid.VisibleColCount - 1, maxrow))
          end
          else
            FPlanner.FGrid.InvalidateCellRect(ir);

          FPlanner.Items.Selected.Repaint;

          { Check here if scroll required }
          if (ItemEnd - LeftCol >= VisibleColCount) and
            (LeftCol + VisibleColCount < ColCount) then
          begin
            LeftCol := LeftCol + 1;
            if FPlanner.ScrollSmooth then
              FScrolling := True;

            FMouseXY.X := FMouseXY.X - DefaultColWidth;
          end;

          HintShowXY(X, Y, FPlanner.Items.Selected, FPlanner.Items.Selected.ItemEndTimeStr);
        end;
      end;
      Exit;
    end;
  end;

  inherited;

  if FMouseDown then
    SelChanged;

  if Assigned(FPlanner.FOnPlannerMouseMove) then
  begin
    FPlanner.FOnPlannerMouseMove(FPlanner, Shift, X, Y);
  end;

  if FMouseDown then
    CorrectSelection;

  if (FLastHintPos.X <> -1) then
    if (GridCoord.X <> FLastHintPos.X) or (GridCoord.Y <> FLastHintPos.Y) then
    begin
      Application.CancelHint;
      FLastHintPos := Point(-1, -1);
      FLastHintItem := nil;
    end;
  if (GridCoord.X <> FToolTipPos.X) or (GridCoord.Y <> FToolTipPos.Y) then
  begin
    SendMessage(FHToolTip, TTM_POP, 0, 0);
  end;
  FToolTipPos.X := GridCoord.X;
  FToolTipPos.Y := GridCoord.Y;

  CR := CellRectEx(GridCoord.X, GridCoord.Y);

  if FPlanner.Sidebar.Orientation = soVertical then
  begin
    APlannerItem := FPlanner.Items.FindItemPos(GridCoord.Y,
      GridCoord.X - ColOffset, X - CR.Left);

    if Assigned(APlannerItem) and (APlannerItem <> FLastHintItem) and
      (FLastHintPos.X <> -1) then
    begin
      FLastHintItem := nil;
      FLastHintPos := Point(-1, -1);
      Application.CancelHint;
    end;

    if Assigned(APlannerItem) and (APlannerItem = FPlanner.Items.Selected) then
    begin
      APlannerItem.CalcConflictRect(CR, ColWidthEx(APlannerItem.ItemPos),
        RowHeightEx(1), FPlanner.Sidebar.Orientation = soVertical);

      ImgSize := 0;

      if APlannerItem.Focus then
      begin
        s := ConcatenateTextStrings(APlannerItem.Text);

        R := CR;
        R.Left := R.Left + FPlanner.TrackWidth;
        R.Top := R.Top - ((GridCoord.Y - APlannerItem.ItemBegin)
            * DefaultRowHeight) + 4;
        R.Bottom := R.Bottom + ((APlannerItem.ItemEnd - GridCoord.Y - 1)
            * DefaultRowHeight) + 4;

        if Assigned(FPlanner.PlannerImages) and
          ((APlannerItem.ImageID >= 0) or
            (APlannerItem.FImageIndexList.Count > 0)) then
        begin
          ImgSize := FPlanner.PlannerImages.Width;
          if (APlannerItem.ImagePosition = ipHorizontal) and
            (APlannerItem.FImageIndexList.Count > 0) then
            ImgSize := 8 + (ImgSize * APlannerItem.FImageIndexList.Count - 1);
        end;

        if (APlannerItem.CaptionType <> ctNone) then
        begin
          tr := R;
          tr.Bottom := tr.Top + 16;
          tr.Right := tr.Right - FPlanner.ItemGap;

          if APlannerItem.ShowDeleteButton then
          begin
            tr.Left := tr.Right - FPlanner.DeleteGlyph.Width;

            if PtInRect(tr, Point(X, Y)) then
            begin
              if Self.Cursor <> crHandPoint then
              begin
                Self.Cursor := crHandPoint;
              end;
              Exit;
            end;
            tr.Right := tr.Right - FPlanner.DeleteGlyph.Width;
          end;

          if APlannerItem.Attachement <> '' then
          begin
            tr.Left := tr.Right - FPlanner.AttachementGlyph.Width;

            if PtInRect(tr, Point(X, Y)) then
            begin
              if Self.Cursor <> crHandPoint then
              begin
                Self.Cursor := crHandPoint;
              end;
              Exit;
            end;

            tr.Right := tr.Right - FPlanner.AttachementGlyph.Width;
          end;

          if APlannerItem.URL <> '' then
          begin
            tr.Left := tr.Right - FPlanner.URLGlyph.Width;

            if PtInRect(tr, Point(X, Y)) then
            begin
              if Self.Cursor <> crHandPoint then
              begin
                Self.Cursor := crHandPoint;
              end;
              Exit;
            end;
          end;

          if APlannerItem.CaptionType in [ctText, ctTimeText] then
          begin
            if IsHtml(APlannerItem, APlannerItem.CaptionText, True) then
            begin
              Canvas.Font := APlannerItem.CaptionFont;

              if HTMLDrawEx(Canvas, APlannerItem.CaptionText, R,
                FPlanner.PlannerImages, X, Y, -1, -1, 1, True, False, False,
                True, True, False, APlannerItem.WordWrap
                , False
                , 1.0, FPlanner.URLColor, clNone, clNone, clGray, Anchor,
                StrippedHTMLString, FocusAnchor, XSize, YSize, ml, hl, hr
                , cor, CID, CV, CT, FPlanner.FImageCache,
                FPlanner.FContainer, Handle
              ) then

              begin
                if Self.Cursor <> crHandPoint then
                begin
                  Self.Cursor := crHandPoint;
                  if Assigned(FPlanner.OnItemAnchorEnter) then
                    FPlanner.OnItemAnchorEnter(FPlanner, APlannerItem,
                      Anchor);
                end;
                Exit;
              end
              else if Self.Cursor = crHandPoint then
              begin
                if Assigned(FPlanner.OnItemAnchorExit) then
                  FPlanner.OnItemAnchorExit(FPlanner, APlannerItem, Anchor);
              end;

            end;
          end;
          R.Top := R.Top + APlannerItem.FCaptionHeight;
        end
        else
        begin
          if (APlannerItem.ImageID >= 0) and Assigned(FPlanner.PlannerImages) then
            R.Left := R.Left + ImgSize;
        end;

        if IsHtml(APlannerItem, s, False) then
        begin
          Canvas.Font := APlannerItem.Font;

          if APlannerItem.Shadow and not APlannerItem.Background and
            (APlannerItem.Shape = psRect) and not FPlanner.TrackOnly then
          begin
            R.Right := R.Right - 5;
            R.Bottom := R.Bottom - 2;
          end
          else
          begin
            R.Right := R.Right - 2;
          end;

          R.Left := R.Left + 2;

          APlannerItem.CompletionAdapt(R);
          APlannerItem.ImageListAdapt(R);

          if HTMLDrawEx(Canvas, s, R, FPlanner.PlannerImages, X, Y, -1, -1,
            1, True, False, False, True, False, False, APlannerItem.WordWrap
            , False
            , 1.0, FPlanner.URLColor, clNone, clNone, clGray, Anchor,
            StrippedHTMLString, FocusAnchor, XSize, YSize, ml, hl, hr
            , cor, CID, CV, CT, FPlanner.FImageCache, FPlanner.FContainer,
            Handle
          ) then

          begin
            if (Self.Cursor <> crHandPoint)
            or (CID <> FCurrCtrlID)
            then
            begin
              Self.Cursor := crHandPoint;
              if (cor.Right <> 0) and IsWinXP then
              begin
                if FCurrCtrlR.Right <> 0 then
                  InvalidateRect(Handle, @FCurrCtrlR, False);
{$IFDEF TMSDEBUG}
                outputdebugstring('control hot');
{$ENDIF}
                FCurrCtrlID := CID;
                FCurrCtrlR := cor;
                InvalidateRect(Handle, @cor, False);
              end;
              if Assigned(FPlanner.OnItemAnchorEnter) then
                FPlanner.OnItemAnchorEnter(FPlanner, APlannerItem, Anchor);
            end;
            Exit;
          end
          else if (Self.Cursor = crHandPoint)
          or (CID <> FCurrCtrlID)
          then
          begin
            if (FCurrCtrlR.Right <> 0) and IsWinXP then
            begin
{$IFDEF TMSDEBUG}
              outputdebugstring(PChar('control cold:' + IntToStr(FCurrCtrlR.Right)));
{$ENDIF}
              InvalidateRect(Handle, @FCurrCtrlR, False);
              if CID = '' then
                FCurrCtrlR := Rect(0, 0, 0, 0)
              else
                FCurrCtrlR := cor;

              FCurrCtrlID := CID;
            end;
            if Assigned(FPlanner.OnItemAnchorExit) then
              FPlanner.OnItemAnchorExit(FPlanner, APlannerItem, Anchor);
          end;
        end;
      end;

      if APlannerItem.Focus and (APlannerItem.ItemBegin = GridCoord.Y) and
        (Y < CR.Top + 3) and not APlannerItem.FixedSize and
        (FPlanner.UserMode in [puNormal, puReadOnly]) then
      begin
        if APlannerItem.Cursor = crNone then
          Self.Cursor := crSizeNS
        else
          Self.Cursor := APlannerItem.Cursor;

        FSelItem := APlannerItem;
        Exit;
      end;

      if APlannerItem.Focus and (APlannerItem.ItemEnd - 1 = GridCoord.Y) and
        (Y > CR.Bottom - 5) and not APlannerItem.FixedSize and
        (FPlanner.UserMode in [puNormal, puReadOnly]) then
      begin
        if APlannerItem.Cursor = crNone then
          Self.Cursor := crSizeNS
        else
          Self.Cursor := APlannerItem.Cursor;

        FSelItem := APlannerItem;
        Exit;
      end;

      if (((X > CR.Left) and (X < CR.Left + FPlanner.TrackWidth)) or
          ((Y > CR.Top + 3) and (Y < CR.Top + APlannerItem.GetCaptionHeight)
            and (APlannerItem.ItemBegin = GridCoord.Y) and
            (X > CR.Left + ImgSize))) and not APlannerItem.FixedPos and
        (FPlanner.UserMode in [puNormal, puReadOnly]) then
      begin
        if APlannerItem.Cursor = crNone then
          Self.Cursor := crSizeAll
        else
          Self.Cursor := APlannerItem.Cursor;
        FSelItem := APlannerItem;
        Exit;
      end;

      if APlannerItem.Focus and APlannerItem.NotEditable and FPlanner.
        DirectMove and not APlannerItem.Background and not APlannerItem.
        FixedPos and (FPlanner.UserMode in [puNormal, puReadOnly]) then
      begin
        if APlannerItem.Cursor = crNone then
          Self.Cursor := crSizeAll
        else
          Self.Cursor := APlannerItem.Cursor;
        FSelItem := APlannerItem;
        Exit;
      end;
    end
    else if Assigned(APlannerItem) then
      if (APlannerItem.Cursor <> crNone) and FPlanner.DirectMove then
      begin
        Self.Cursor := APlannerItem.Cursor;
        Exit;
      end;
  end
  else
  begin
    APlannerItem := FPlanner.Items.FindItemPos(GridCoord.X - ColOffset,
      GridCoord.Y - RowOffset, Y - CR.Top);

    if Assigned(APlannerItem) and (APlannerItem = FPlanner.Items.Selected)
      then
    begin
      APlannerItem.CalcConflictRect(CR, ColWidthEx(APlannerItem.ItemPos),
        RowHeightEx(APlannerItem.ItemPos),
        FPlanner.Sidebar.Orientation = soVertical);

      ImgSize := 0;

      if APlannerItem.Focus then
      begin
        s := ConcatenateTextStrings(APlannerItem.Text);

        R := CR;

        R.Top := R.Top + FPlanner.TrackWidth;
        R.Left := R.Left - ((GridCoord.X - APlannerItem.ItemBegin) * DefaultColWidth) + 4;
        R.Right := R.Right + ((APlannerItem.ItemEnd - GridCoord.X - 1) * DefaultColWidth) + 4;

        if Assigned(FPlanner.PlannerImages) and
          ((APlannerItem.ImageID >= 0) or
            (APlannerItem.FImageIndexList.Count > 0)) then
        begin
          ImgSize := FPlanner.PlannerImages.Width;
          if (APlannerItem.ImagePosition = ipHorizontal) and
            (APlannerItem.FImageIndexList.Count > 0) then
            ImgSize := 8 + (ImgSize * APlannerItem.FImageIndexList.Count - 1);
        end;

        if (APlannerItem.CaptionType <> ctNone) then
        begin
          tr := R;
          tr.Right := tr.Right - 4 - FPlanner.TrackWidth;

          tr.Bottom := tr.Top + 16;

          if APlannerItem.ShowDeleteButton then
          begin
            tr.Left := tr.Right - FPlanner.DeleteGlyph.Width;

            if PtInRect(tr, Point(X, Y)) then
            begin
              if Self.Cursor <> crHandPoint then
              begin
                Self.Cursor := crHandPoint;
              end;
              Exit;
            end;
            tr.Right := tr.Right - FPlanner.DeleteGlyph.Width;
          end;

          if APlannerItem.Attachement <> '' then
          begin
            tr.Left := tr.Right - FPlanner.AttachementGlyph.Width;

            if PtInRect(tr, Point(X, Y)) then
            begin
              if Self.Cursor <> crHandPoint then
              begin
                Self.Cursor := crHandPoint;
              end;
              Exit;
            end;

            tr.Right := tr.Right - FPlanner.AttachementGlyph.Width;
          end;

          if APlannerItem.URL <> '' then
          begin
            tr.Left := tr.Right - FPlanner.URLGlyph.Width;

            if PtInRect(tr, Point(X, Y)) then
            begin
              if Self.Cursor <> crHandPoint then
              begin
                Self.Cursor := crHandPoint;
              end;
              Exit;
            end;
          end;

          if (APlannerItem.CaptionType in [ctText, ctTimeText]) then
          begin
            if IsHtml(APlannerItem, APlannerItem.CaptionText, True) then
            begin
              Canvas.Font := APlannerItem.CaptionFont;

              if HTMLDrawEx(Canvas, APlannerItem.CaptionText, R,
                FPlanner.PlannerImages, X, Y, -1, -1, 1, True, False, False,
                True, True, False, APlannerItem.WordWrap
                , False
                , 1.0, FPlanner.URLColor, clNone, clNone, clGray, Anchor,
                StrippedHTMLString, FocusAnchor, XSize, YSize, ml, hl, hr
                , cor, CID, CV, CT, FPlanner.FImageCache,
                FPlanner.FContainer, Handle
              ) then

              begin
                if (Self.Cursor <> crHandPoint) then
                begin
                  Self.Cursor := crHandPoint;
                  if Assigned(FPlanner.OnItemAnchorEnter) then
                    FPlanner.OnItemAnchorEnter(FPlanner, APlannerItem,
                      Anchor);
                end;
                Exit;
              end
              else if (Self.Cursor = crHandPoint) then
              begin
                if Assigned(FPlanner.OnItemAnchorExit) then
                  FPlanner.OnItemAnchorExit(FPlanner, APlannerItem, Anchor);
              end;

            end;
          end;
          R.Top := R.Top + APlannerItem.FCaptionHeight;
        end;

        if IsHtml(APlannerItem, s, False) then
        begin
          Canvas.Font := APlannerItem.Font;

          if APlannerItem.Shadow and not APlannerItem.Background and
            (APlannerItem.Shape = psRect) and not FPlanner.TrackOnly then
          begin
            R.Right := R.Right - 5;
            R.Bottom := R.Bottom - 2;
          end
          else
          begin
            R.Right := R.Right - 2;
          end;

          R.Left := R.Left + 2;

          APlannerItem.CompletionAdapt(R);
          APlannerItem.ImageListAdapt(R);

          if HTMLDrawEx(Canvas, s, R, FPlanner.PlannerImages, X, Y, -1, -1,
            1, True, False, False, True, True, False, APlannerItem.WordWrap
            , False
            , 1.0, FPlanner.URLColor, clNone, clNone, clGray, Anchor,
            StrippedHTMLString, FocusAnchor, XSize, YSize, ml, hl, hr
            , cor, CID, CV, CT, FPlanner.FImageCache, FPlanner.FContainer,
            Handle
          ) then

          begin
            if (Self.Cursor <> crHandPoint)
            or (CID <> FCurrCtrlID)
            then

            begin
              Self.Cursor := crHandPoint;
              if (cor.Right <> 0) and IsWinXP then
              begin
                if FCurrCtrlR.Right <> 0 then
                  InvalidateRect(Handle, @FCurrCtrlR, False);
                InflateRect(cor, 0, 2);
                FCurrCtrlID := CID;
                FCurrCtrlR := cor;
                InvalidateRect(Handle, @cor, False);
              end;
              if Assigned(FPlanner.OnItemAnchorEnter) then
                FPlanner.OnItemAnchorEnter(FPlanner, APlannerItem, Anchor);
            end;
            Exit;
          end
          else if (Self.Cursor = crHandPoint)
          or (CID <> FCurrCtrlID)
          then
          begin
            if (FCurrCtrlR.Right <> 0) and IsWinXP then
            begin
              InflateRect(FCurrCtrlR, 0, 2);
              InvalidateRect(Handle, @FCurrCtrlR, False);
              if CID = '' then
                FCurrCtrlR := Rect(0, 0, 0, 0)
              else
                FCurrCtrlR := cor;

              FCurrCtrlID := CID;
            end;
            if Assigned(FPlanner.OnItemAnchorExit) then
              FPlanner.OnItemAnchorExit(FPlanner, APlannerItem, Anchor);
          end;
        end;
      end;

      if APlannerItem.Focus and (APlannerItem.ItemBegin = GridCoord.X) and
        (X < CR.Left + 3) and not APlannerItem.FixedSize and
        (FPlanner.UserMode in [puNormal, puReadOnly]) then
      begin
        if APlannerItem.Cursor = crNone then
          Self.Cursor := crSizeWE
        else
          Self.Cursor := APlannerItem.Cursor;

        FSelItem := APlannerItem;
        Exit;
      end;

      if APlannerItem.Focus and (APlannerItem.ItemEnd - 1 = GridCoord.X) and
        (X > CR.Right - 5) and not APlannerItem.FixedSize and
        (FPlanner.UserMode in [puNormal, puReadOnly]) then
      begin
        if APlannerItem.Cursor = crNone then
          Self.Cursor := crSizeWE
        else
          Self.Cursor := APlannerItem.Cursor;

        FSelItem := APlannerItem;
        Exit;
      end;

      if (((Y > CR.Top) and (Y < CR.Top + FPlanner.TrackWidth)) or
          ((Y > CR.Top + FPlanner.TrackWidth) and
            (Y < CR.Top + FPlanner.TrackWidth +
              APlannerItem.GetCaptionHeight) and
            (APlannerItem.ItemPos = GridCoord.Y - RowOffset) and
            (X > R.Left + ImgSize))) and not APlannerItem.FixedPos and
        (FPlanner.UserMode in [puNormal, puReadOnly]) then
      begin
        if APlannerItem.Cursor = crNone then
          Self.Cursor := crSizeAll
        else
          Self.Cursor := APlannerItem.Cursor;
        FSelItem := APlannerItem;
        Exit;
      end;

      if APlannerItem.Focus and APlannerItem.NotEditable and FPlanner.
        DirectMove and not APlannerItem.Background and not APlannerItem.
        FixedPos and (FPlanner.UserMode in [puNormal, puReadOnly]) then
      begin
        if APlannerItem.Cursor = crNone then
          Self.Cursor := crSizeAll
        else
          Self.Cursor := APlannerItem.Cursor;
        FSelItem := APlannerItem;
        Exit;
      end;
    end
    else if Assigned(APlannerItem) then
      if (APlannerItem.Cursor <> crNone) and FPlanner.DirectMove then
      begin
        Self.Cursor := APlannerItem.Cursor;
        Exit;
      end;
  end;

  if not FMouseDown then
    FSelItem := nil;

  if (Self.Cursor <> FPlanner.Cursor) then
  begin
    if (FCurrCtrlR.Right <> 0) and IsWinXP then
    begin
      InvalidateRect(Handle, @FCurrCtrlR, False);
      FCurrCtrlR := Rect(0, 0, 0, 0);
    end;
    Self.Cursor := FPlanner.Cursor;
  end;
end;


procedure TPlannerGrid.WMSetCursor(var Msg: TWMSetCursor);
var
  p: TPoint;
  nc: Integer;
begin
  if (csDesigning in ComponentState) and FPlanner.ShowDesignHelper then
  begin
    GetCursorPos(p);
    p := ScreenToClient(p);
    nc := MouseOverDesignChoice(p.X, p.Y);
    if nc in [1, 2, 3] then
      Windows.SetCursor(Screen.Cursors[crHandPoint])
    else
      Windows.SetCursor(Screen.Cursors[crDefault])
  end
  else
    inherited;
end;


procedure TPlannerGrid.CMDesignHitTest(var Msg: TCMDesignHitTest);
var
  R: TRect;
  p: TPoint;
  nc: Integer;
begin
  inherited;

  if (csDesigning in ComponentState) and FPlanner.ShowDesignHelper then
  begin
    GetCursorPos(p);
    p := ScreenToClient(p);

    nc := MouseOverDesignChoice(p.X, p.Y);

    if nc <> FLastDesignChoice then
    begin
      R := ClientRect;
      R := Rect(R.Right - 150, R.Bottom - 70, R.Right, R.Bottom);
      InvalidateRect(Handle, @R, True);
    end;

    FLastDesignChoice := nc;

    if nc in [1, 2, 3] then
    begin
      Msg.Result := 1;
    end;
  end;
end;

procedure TPlannerGrid.CMHintShow(var Message: TMessage);
type
  PHintInfo = ^THintInfo;
var
  CanShow: Boolean;
  Hi: PHintInfo;
  CR, hr, cor, ir: TRect;
  APlannerItem: TPlannerItem;
  GridCoord: TGridCoord;
  s, CID, CV, CT: string;
  Anchor, StrippedHTMLString, FocusAnchor: string;
  XSize, YSize, ml, hl: Integer;
  sideb: Boolean;
begin
  if FMouseDownMove or FMouseDownSizeUp or FMouseDownSizeDown then
    Exit;

  if not FPlanner.ShowHint then
    Exit;

  if FPlanner.EditMode then
    Exit;

  Hi := PHintInfo(Message.LParam);

  GridCoord := MouseCoord(Hi.CursorPos.X, Hi.CursorPos.Y);
  CR := CellRectEx(GridCoord.X, GridCoord.Y);

  FLastHintPos := Point(GridCoord.X, GridCoord.Y);

  if FPlanner.Sidebar.Orientation = soVertical then
    APlannerItem := FPlanner.Items.FindItemPos(GridCoord.Y,
      GridCoord.X - 1, Hi.CursorPos.X - CR.Left)
  else
    APlannerItem := FPlanner.Items.FindItemPos(GridCoord.X,
      GridCoord.Y - 1, Hi.CursorPos.Y - CR.Top);

  if not Assigned(APlannerItem) then
  begin
    if FPlanner.Sidebar.Orientation = soVertical then
      APlannerItem := FPlanner.Items.FindBkgPos(GridCoord.Y,
        GridCoord.X - 1, Hi.CursorPos.X - CR.Left)
    else
      APlannerItem := FPlanner.Items.FindBkgPos(GridCoord.X,
        GridCoord.Y - 1, Hi.CursorPos.Y - CR.Top);
  end;

  sideb := False;
  FLastHintItem := APlannerItem;

  if Assigned(APlannerItem) then
  begin
    s := APlannerItem.ItemText;
    if IsRtf(s) then
    begin
      if not FPlanner.RichEdit.Visible then
      begin
        FPlanner.TextToRich(s);
        s := FPlanner.FRichEdit.Text;
      end;
    end;
    if APlannerItem.Hint <> '' then
    begin
      s := APlannerItem.Hint;

      if APlannerItem.HintIndicator then
      begin
        ir := APlannerItem.GetItemPaintRect;

        Hi.HintPos := ClientToScreen(Point(ir.Right, ir.Top));
        if APlannerItem.Shadow then
          Hi.HintPos := Point(Hi.HintPos.X - 2, Hi.HintPos.Y);
      end;
    end;

    if IsHtml(APlannerItem, s, False) then
    begin
      {Change ? if HTML Hint is enabled ?}
      if APlannerItem.Hint = '' then
        s := ConcatenateTextStrings(APlannerItem.Text);
      CR := ClientRect;
      if not FPlanner.HTMLHint then
      begin
        HTMLDrawEx(Canvas, s, CR, FPlanner.PlannerImages, 0, 0, -1, -1, 1,
          True, True, False, True, True, False, APlannerItem.WordWrap
          , False
          , 1.0, FPlanner.URLColor, clNone, clNone, clGray, Anchor,
          StrippedHTMLString, FocusAnchor, XSize, YSize, ml, hl, hr
          , cor, CID, CV, CT, FPlanner.FImageCache, FPlanner.FContainer,
          Handle
        );

        s := StrippedHTMLString;
      end;
    end;
{$IFDEF TMSCODESITE}
    CodeSite.SendMsg(s + '*');
{$ENDIF}
    Hi.HintStr := s;
    if Assigned(FPlanner.OnItemHint) then
      FPlanner.OnItemHint(FPlanner, APlannerItem, Hi.HintStr);
  end
  else
  begin
    if FPlanner.Sidebar.Orientation = soVertical then
    begin
      if GridCoord.X = 0 then
      begin
        if Assigned(FPlanner.OnSideBarHint) then
          FPlanner.OnSideBarHint(Self, GridCoord.Y, Hi.HintStr);
        sideb := Hi.HintStr <> '';
      end;
    end
    else
    begin
      if GridCoord.Y = 0 then
      begin
        if Assigned(FPlanner.OnSideBarHint) then
          FPlanner.OnSideBarHint(Self, GridCoord.X, Hi.HintStr);
        sideb := Hi.HintStr <> '';
      end;

    end;
  end;

  if FPlanner.HintColor <> clNone then
    Hi.HintColor := FPlanner.HintColor;

  Hi.HideTimeOut := FPlanner.HintPause;

  CanShow := Assigned(APlannerItem) or sideb;

  Message.Result := Ord(not CanShow);
end;

procedure TPlannerGrid.WMLButtonDown(var Message: TWMLButtonDown);
begin
  if (csDesigning in ComponentState) then
  begin
    if FLastDesignChoice <> -1 then
      inherited
    else
      message.Result := 1
  end
  else
    inherited;
end;

procedure TPlannerGrid.WMLButtonDblClk(var Message: TWMLButtonDblClk);
var
  FromSel, FromSelPrecis: Integer;
  ToSel, ToSelPrecis: Integer;
  GridCoord: TGridCoord;
  APlannerItem: TPlannerItem;
  GridRect: TRect;
  ColOffset, RowOffset: Integer;
  isSideBar: Boolean;
begin
  if (csDesigning in ComponentState) then
  begin
    Message.Result := 1;
    Exit;
  end;

  ColOffset := FPlanner.FSidebar.FColOffset;
  RowOffset := FPlanner.FSidebar.FRowOffset;

  GridCoord := MouseCoord(Message.XPos, Message.YPos);
  GridRect := CellRectEx(GridCoord.X, GridCoord.Y);

  if FPlanner.Sidebar.Orientation = soVertical then
  begin
    isSideBar := False;
    case FPlanner.Sidebar.Position of
      spLeft:
        isSideBar := (GridCoord.X = 0);
      spRight:
        isSideBar := (GridCoord.X = ColCount - 1);
      spLeftRight:
        isSideBar := (GridCoord.X = 0) or (GridCoord.X = ColCount - 1);
    end;

    if isSideBar then
    begin
      FPlanner.DoSideBarDblClick(FPlanner, GridCoord.Y);
    end;
  end
  else
  begin
    if FPlanner.Sidebar.Visible and (GridCoord.Y = 0) then
    begin
      FPlanner.DoSideBarDblClick(FPlanner, GridCoord.X);
    end;
  end;

  if FPlanner.Sidebar.Orientation = soVertical then
    APlannerItem := FPlanner.Items.FindItemPos(GridCoord.Y - RowOffset,
      GridCoord.X - ColOffset, Message.XPos - GridRect.Left)
  else
    APlannerItem := FPlanner.Items.FindItemPos(GridCoord.X - ColOffset,
      GridCoord.Y - RowOffset, Message.YPos - GridRect.Top);

  if (Assigned(APlannerItem)) then
  begin
    if Assigned(APlannerItem.Editor) then
      if APlannerItem.Editor.EditorUse = euDblClick then
        APlannerItem.FPopupEdit := True;
  end;

  inherited;

  if not Assigned(APlannerItem) then
  begin
    if FPlanner.Sidebar.Orientation = soVertical then
      APlannerItem := FPlanner.Items.FindBkgItem(GridCoord.Y - RowOffset,
        GridCoord.X - ColOffset, Message.XPos - GridRect.Left)
    else
      APlannerItem := FPlanner.Items.FindBkgItem(GridCoord.X - ColOffset,
        GridCoord.Y - RowOffset, Message.YPos - GridRect.Top);
  end;

  if (Assigned(APlannerItem)) then
  begin
    HintHide;
    FMouseDown := False;
    FMouseDownMove := False;
    FMouseDownSizeUp := False;
    FMouseDownSizeDown := False;

    if Assigned(APlannerItem.Editor) then
      if APlannerItem.Editor.EditorUse = euDblClick then
      begin
        APlannerItem.PopupEdit;
        APlannerItem.FPopupEdit := False;
      end;

    if Assigned(FPlanner.OnItemDblClick) then
      FPlanner.OnItemDblClick(FPlanner, APlannerItem);
  end
  else
  begin
    if (Message.XPos < GridRect.Right - 10) or (1 > 0) then
    begin
      if Assigned(FPlanner.FOnPlannerDblClick) then
      begin
        if FPlanner.Sidebar.Position = spTop then
        begin
          FromSel := Selection.Left + FPlanner.Display.DisplayStart;
          ToSel := 1 + Selection.Right + FPlanner.Display.DisplayStart;
          FromSelPrecis := FromSel * FPlanner.Display.DisplayUnit +
            FPlanner.Display.DisplayOffset;
          ToSelPrecis := ToSel * FPlanner.Display.DisplayUnit +
            FPlanner.Display.DisplayOffset;
          FPlanner.FOnPlannerDblClick(FPlanner, Row - 1, FromSel,
            FromSelPrecis, ToSel, ToSelPrecis)
        end
        else
        begin
          FromSel := Selection.Top + FPlanner.Display.DisplayStart;
          ToSel := 1 + Selection.Bottom + FPlanner.Display.DisplayStart;
          FromSelPrecis := FromSel * FPlanner.Display.DisplayUnit +
            FPlanner.Display.DisplayOffset;
          ToSelPrecis := ToSel * FPlanner.Display.DisplayUnit +
            FPlanner.Display.DisplayOffset;
          if (FPlanner.Sidebar.Position = spRight) then
            FPlanner.FOnPlannerDblClick(FPlanner, Col, FromSel,
              FromSelPrecis, ToSel, ToSelPrecis)
          else
            FPlanner.FOnPlannerDblClick(FPlanner, Col - 1, FromSel,
              FromSelPrecis, ToSel, ToSelPrecis);
        end;
      end;
    end;
  end;
end;

procedure TPlannerGrid.WMEraseBkGnd(var Message: TWMEraseBkgnd);
begin
  if FEraseBkGnd then
    inherited
  else
    Message.Result := 0 // Avoid erase backgnd to reduce flicker !
end;

procedure TPlannerGrid.CNKeyDown(var Message: TWMKeydown);
var
  APlannerItem: TPlannerItem;
begin
  APlannerItem := nil;

  if (GetKeyState(VK_CONTROL) and $8000 = $8000) then
  begin
    inherited;
    Exit;
  end;

  if (Message.CharCode = VK_TAB) then
  begin
    if (GetKeyState(VK_SHIFT) and $8000 > 0) then
      APlannerItem := FPlanner.Items.SelectPrev
    else
      APlannerItem := FPlanner.Items.SelectNext;
  end;

  inherited;

  if Assigned(APlannerItem) then
  begin
    SetFocus;
    FPlanner.ItemSelected(APlannerItem);
  end;
end;

procedure TPlannerGrid.KeyDown(var Key: Word; ShiftState: TShiftState);
var
  APlannerItem, NewPlannerItem, plIt: TPlannerItem;
  GridRect: TRect;
  FromSel, FromSelPrecis: Integer;
  ToSel, ToSelPrecis: Integer;
  CharCode: Word;
  Allow: Boolean;
begin
  if Assigned(FPlanner.OnPlannerBeforeKeyDown) then
    FPlanner.OnPlannerBeforeKeyDown(FPlanner, Key, ShiftState);

  APlannerItem := FPlanner.Items.Selected;

  CharCode := Key;

  if not FPlanner.EnableKeyboard then
    if (Key in [VK_UP, VK_LEFT, VK_RIGHT, VK_DOWN]) and
      (Assigned(FPlanner.Items.Selected)) then
      Exit;

  if FPlanner.Sidebar.Orientation = soHorizontal then
  begin // Map keyboard movement from Horizontal to Vertical
    case CharCode of
      VK_RIGHT:
        CharCode := VK_DOWN;
      VK_LEFT:
        CharCode := VK_UP;
      VK_UP:
        CharCode := VK_LEFT;
      VK_DOWN:
        CharCode := VK_RIGHT;
    end;
  end;

  case CharCode of
    Ord('C'), Ord('c'):
      begin
        if (ssCtrl in ShiftState) and FPlanner.AllowClipboardShortCuts then
        begin
          if Assigned(FPlanner.Items.Selected) then
          begin
            Allow := true;
            if Assigned(FPlanner.OnItemCopying) then
              FPlanner.OnItemCopying(FPlanner, FPlanner.Items.Selected, Allow);

            if Allow then
            begin
              FPlanner.Items.CopyToClipboard;
              if Assigned(FPlanner.OnItemCopied) then
              begin
                FPlanner.OnItemCopied(FPlanner, FPlanner.Items.Selected);
              end;
            end;
          end;
        end;
      end;
    Ord('X'), Ord('x'):
      begin
        if (ssCtrl in ShiftState) and FPlanner.AllowClipboardShortCuts then
        begin
          if Assigned(FPlanner.Items.Selected) then
          begin
            Allow := true;

            if Assigned(FPlanner.OnItemCutting) then
              FPlanner.OnItemCutting(FPlanner, FPlanner.Items.Selected, Allow);

            if Allow then
            begin  
              FPlanner.Items.CutToClipboard;
              if Assigned(FPlanner.OnItemCut) then
              begin
                FPlanner.OnItemCut(FPlanner);
              end;
            end;
          end;
        end;
      end;
    Ord('V'), Ord('v'):
      begin
        if (ssCtrl in ShiftState) and FPlanner.AllowClipboardShortCuts then
        begin

          Allow := True;
          if Assigned(FPlanner.OnItemPasting) then
          begin
            FPlanner.OnItemPasting(FPlanner, Allow);

            if Allow then
            begin
              NewPlannerItem := FPlanner.Items.PasteFromClipboardAtXY;

              if Assigned(FPlanner.OnItemPasted) then
                FPlanner.OnItemPasted(FPlanner, NewPlannerItem);
            end;
          end;
        end;
      end;

    VK_RETURN, VK_SPACE, VK_F2:
      begin
        if Assigned(APlannerItem) then
        begin
          if not APlannerItem.NotEditable then
          begin
            if FPlanner.Sidebar.Orientation = soVertical then
            begin
              GridRect := CellRectEx(APlannerItem.ItemPos + 1,
                APlannerItem.ItemBegin);
              StartEditCol(GridRect, APlannerItem, -1, -1);
            end
            else
            begin
              GridRect := CellRectEx(APlannerItem.ItemBegin,
                APlannerItem.ItemPos + FPlanner.FSidebar.FRowOffset);
              StartEditRow(GridRect, APlannerItem, -1, -1);
            end;
          end;
        end;
      end;
    VK_INSERT:
      begin
        if FPlanner.AutoInsDel then
        begin
          plIt := FPlanner.CreateItemAtSelection;
          if Assigned(FPlanner.FOnItemCreated) then
            FPlanner.FOnItemCreated(FPlanner, plIt);

          if FPlanner.ItemSelection.AutoSelectOnAutoInsert or FPlanner.
            ItemSelection.AutoEditOnAutoInsert then
            FPlanner.Items.Select(plIt);
          if FPlanner.ItemSelection.AutoEditOnAutoInsert then
            plIt.Edit;
        end;

        if Assigned(FPlanner.FOnItemInsert) then
        begin
          if FPlanner.Sidebar.Orientation = soHorizontal then
          begin
            FromSel := Selection.Left;
            ToSel := 1 + Selection.Right;
            FromSelPrecis := FromSel * FPlanner.Display.DisplayUnit +
              FPlanner.Display.DisplayOffset;
            ToSelPrecis := ToSel * FPlanner.Display.DisplayUnit +
              FPlanner.Display.DisplayOffset;

            if FPlanner.InsertAlways or not FPlanner.Items.HasItemInt(FromSel, ToSel, Row - 1) then
              FPlanner.FOnItemInsert(FPlanner, Row - 1, FromSel,
                FromSelPrecis, ToSel, ToSelPrecis);
          end
          else
          begin
            FromSel := Selection.Top;
            ToSel := 1 + Selection.Bottom;
            FromSelPrecis := FromSel * FPlanner.Display.DisplayUnit +
              FPlanner.Display.DisplayOffset;
            ToSelPrecis := ToSel * FPlanner.Display.DisplayUnit +
              FPlanner.Display.DisplayOffset;

            if FPlanner.InsertAlways or not FPlanner.Items.HasItemInt(FromSel, ToSel, Col - 1) then
              FPlanner.FOnItemInsert(FPlanner, Col - 1, FromSel,
                FromSelPrecis, ToSel, ToSelPrecis);
          end;
        end;
      end;

    VK_DELETE:
      begin
        if not(ssShift in ShiftState) then
        begin
          if Assigned(APlannerItem) then
          begin
            if Assigned(FPlanner.OnItemDelete) then
              FPlanner.OnItemDelete(FPlanner, APlannerItem);

            if FPlanner.AutoInsDel then
            begin
              if Assigned(FPlanner.OnItemDeleted) then
                FPlanner.OnItemDeleted(FPlanner, APlannerItem);
              FPlanner.FreeItem(APlannerItem);
            end
            else
            end;
          end;
        end;

      VK_RIGHT:
        begin
          if Assigned(FPlanner.Items.Selected) then
          begin
            with FPlanner.Items.Selected do
            begin
              if (ItemPos < FPlanner.Positions - 1)
                and not FPlanner.Items.HasItemInt(ItemBegin, ItemEnd, ItemPos + 1)
                and not FixedPos and not FixedPosition and
                (FPlanner.UserMode in [puNormal, puReadOnly]) then
              begin
                Allow := True;

                if Assigned(FPlanner.FOnItemMoving) then
                begin
                  FPlanner.FOnItemMoving(FPlanner, FPlanner.Items.Selected,
                    0, +1, Allow);
                end;

                if Allow then
                begin
                  ItemPos := ItemPos + 1;
                  FPlanner.Items.SetConflicts;

                  with FPlanner.Items do
                  begin
                    FPlanner.ItemMoved(Selected, Selected.ItemBegin,
                      Selected.ItemEnd, Selected.ItemPos - 1,
                      Selected.ItemBegin, Selected.ItemEnd,
                      Selected.ItemPos);
                    MoveLinks(Selected);
                  end;

                  try
                    if (FPlanner.PositionWidth > 0) then
                      if FPlanner.Sidebar.Orientation = soHorizontal then
                      begin
                        if ItemPos >= VisibleRowCount + TopRow then
                          TopRow := TopRow + 1;
                      end
                      else
                      begin
                        if ItemPos >= VisibleColCount + LeftCol then
                          LeftCol := LeftCol + 1;
                      end;
                  except
                  end;
                end;
              end;
              Key := 0;
            end
          end
          else
          begin
            if (FPlanner.SelPosition = FPlanner.Positions - 1) and FPlanner.AutoPositionPrevNext then
            begin
              FPlanner.NextPosition(Self);
            end;
          end;
        end;
      VK_LEFT:
        begin
          if Assigned(FPlanner.Items.Selected) then
          begin
            with FPlanner.Items.Selected do
            begin
              if (ItemPos > 0) and not FPlanner.Items.HasItemInt(ItemBegin, ItemEnd, ItemPos - 1)
                and not FixedPos and not FixedPosition and
                (FPlanner.UserMode in [puNormal, puReadOnly]) then
              begin
                Allow := True;

                if Assigned(FPlanner.FOnItemMoving) then
                begin
                  FPlanner.FOnItemMoving(FPlanner, FPlanner.Items.Selected,
                    0, -1, Allow);
                end;

                if Allow then
                begin
                  ItemPos := ItemPos - 1;
                  FPlanner.Items.SetConflicts;

                  with FPlanner.Items do
                  begin
                    FPlanner.ItemMoved(Selected, Selected.ItemBegin,
                      Selected.ItemEnd, Selected.ItemPos + 1,
                      Selected.ItemBegin, Selected.ItemEnd,
                      Selected.ItemPos);
                    MoveLinks(Selected);
                  end;

                  try
                    if (FPlanner.PositionWidth > 0) then
                      if FPlanner.Sidebar.Orientation = soHorizontal then
                      begin
                        if (ItemPos < TopRow - 1) and (TopRow > 1) then
                          TopRow := TopRow - 1;
                      end
                      else
                      begin
                        if (ItemPos < LeftCol - 1) and (LeftCol > 1) then
                          LeftCol := LeftCol - 1;
                      end;
                  except
                  end;

                end;
              end;
              Key := 0;
            end;
            (*
            else if (Col = 1) and (FPlanner.Sidebar.Visible) and not
              (FPlanner.Sidebar.Position = spRight) and
              (FPlanner.Sidebar.Orientation = soVertical) then
              Key := 0; *)
          end
          else
          begin
            if (FPlanner.SelPosition = 0) and FPlanner.AutoPositionPrevNext then
            begin
              FPlanner.PrevPosition(Self);
            end;
          end;
        end;
      VK_UP:
        begin
          if Assigned(FPlanner.Items.Selected) then
          begin
            with FPlanner.Items.Selected do
            begin
              if (GetKeyState(VK_SHIFT) and $8000 = 0)
                and not FixedPos and not FixedTime and
                (FPlanner.UserMode in [puNormal, puReadOnly]) then
              begin
                if not FPlanner.Items.HasItemInt(ItemBegin - 1, ItemEnd - 1, ItemPos) and (ItemBegin > 0) then
                begin
                  Allow := True;

                  if Assigned(FPlanner.FOnItemMoving) then
                  begin
                    FPlanner.FOnItemMoving(FPlanner,
                      FPlanner.Items.Selected, -1, 0, Allow);
                  end;

                  if Allow then
                  begin
                    ItemBegin := ItemBegin - 1;
                    ItemEnd := ItemEnd - 1;
                    RealTime := False;
                    FPlanner.Items.SetConflicts;

                    with FPlanner.Items do
                    begin
                      FPlanner.ItemMoved(Selected, Selected.ItemBegin + 1,
                        Selected.ItemEnd + 1, Selected.ItemPos,
                        Selected.ItemBegin, Selected.ItemEnd,
                        Selected.ItemPos);
                      MoveLinks(Selected);
                    end;
                  end;
                end;
              end
              else
              begin
                if (ItemEnd > ItemBegin + 1) and not FPlanner.Items.HasItem
                  (ItemBegin, ItemEnd - 1, ItemPos) and not FixedSize and
                  (FPlanner.UserMode in [puNormal, puReadOnly]) then
                begin
                  Allow := True;

                  if Assigned(FPlanner.FOnItemSizing) then
                  begin
                    FPlanner.FOnItemSizing(FPlanner,
                      FPlanner.Items.Selected, 0, -1, Allow);
                  end;

                  if Allow then
                  begin
                    ItemEnd := ItemEnd - 1;
                    RealTime := False;
                    FPlanner.Items.SetConflicts;

                    with FPlanner.Items do
                    begin
                      FPlanner.ItemSized(Selected, Selected.ItemBegin,
                        Selected.ItemEnd + 1, Selected.ItemBegin,
                        Selected.ItemEnd);
                      SizeLinks(Selected);
                    end;
                  end;
                end;
              end;

              try
                if FPlanner.Sidebar.Orientation = soHorizontal then
                begin
                  if (ItemBegin < LeftCol) then
                    LeftCol := LeftCol - 1;
                end
                else
                begin
                  if ItemBegin < TopRow then
                    TopRow := TopRow - 1;
                end;
              except
              end;
            end;
            Key := 0;
          end;
        end;
      VK_DOWN:
        begin
          if Assigned(FPlanner.Items.Selected) then
            with FPlanner.Items.Selected do
            begin
              if ItemEnd + FPlanner.Display.DisplayStart <= FPlanner.Display.DisplayEnd then
              begin
                if (GetKeyState(VK_SHIFT) and $8000 = 0)
                  and not FixedPos and not FixedTime and
                  (FPlanner.UserMode in [puNormal, puReadOnly]) then
                begin
                  if not FPlanner.Items.HasItemInt(ItemBegin + 1, ItemEnd + 1, ItemPos) then
                  begin
                    Allow := True;

                    if Assigned(FPlanner.FOnItemMoving) then
                    begin
                      FPlanner.FOnItemMoving(FPlanner,
                        FPlanner.Items.Selected, +1, 0, Allow);
                    end;

                    if Allow then
                    begin
                      ItemBegin := ItemBegin + 1;
                      ItemEnd := ItemEnd + 1;
                      RealTime := False;
                      FPlanner.Items.SetConflicts;

                      with FPlanner.Items do
                      begin
                        FPlanner.ItemMoved(Selected,
                          Selected.ItemBegin - 1, Selected.ItemEnd - 1,
                          Selected.ItemPos, Selected.ItemBegin,
                          Selected.ItemEnd, Selected.ItemPos);
                        MoveLinks(Selected);
                      end;
                    end;
                  end;
                  Key := 0;
                end
                else
                begin
                  if not FPlanner.Items.HasItemInt(ItemBegin, ItemEnd + 1, ItemPos) and not FixedSize and
                    (FPlanner.UserMode in [puNormal, puReadOnly]) then
                  begin
                    Allow := True;

                    if Assigned(FPlanner.FOnItemSizing) then
                    begin
                      FPlanner.FOnItemSizing(FPlanner,
                        FPlanner.Items.Selected, 0, +1, Allow);
                    end;

                    if Allow then
                    begin
                      ItemEnd := ItemEnd + 1;
                      RealTime := False;
                      FPlanner.Items.SetConflicts;

                      with FPlanner.Items do
                      begin
                        FPlanner.ItemSized(Selected, Selected.ItemBegin,
                          Selected.ItemEnd - 1, Selected.ItemBegin,
                          Selected.ItemEnd);
                        SizeLinks(Selected);
                      end;
                    end;
                  end;
                end;

                try
                  if FPlanner.Sidebar.Orientation = soHorizontal then
                  begin
                    if (ItemEnd > VisibleColCount) then
                      LeftCol := LeftCol + 1;
                  end
                  else
                  begin
                    if ItemEnd > TopRow + VisibleRowCount then
                      TopRow := TopRow + 1;
                  end;
                except
                end;
              end;
              Key := 0;
            end;
        end;
      end;

  if not FPlanner.SelectionAlways and Assigned(APlannerItem) then
  begin
    Key := 0;
    Exit;
  end;

  if FPlanner.Mode.FullHalfDay then
  begin
    case Key of
      VK_LEFT:
        begin
          if ssShift in ShiftState then
            ChangeSelection(0, 0, -1, 0)
          else
            ChangeSelection(-1, 0, 0, 0);
          Key := 0;
        end;
      VK_RIGHT:
        begin
          if ssShift in ShiftState then
            ChangeSelection(0, 0, +1, 0)
          else
            ChangeSelection(+1, 0, 0, 0);
          Key := 0;
        end;
      VK_UP:
        begin
          if ssShift in ShiftState then
            ChangeSelection(0, 0, 0, -1)
          else
            ChangeSelection(0, -1, 0, 0);
          Key := 0;
        end;
      VK_DOWN:
        begin
          if ssShift in ShiftState then
            ChangeSelection(0, 0, 0, +1)
          else
            ChangeSelection(0, +1, 0, 0);
          Key := 0;
        end;
    end;
  end;

  inherited;
  if Key in [VK_UP, VK_LEFT, VK_RIGHT, VK_DOWN, VK_PRIOR, VK_NEXT, VK_HOME, VK_END] then
    SelChanged;

  CorrectSelection;

  if Assigned(FPlanner.FOnPlannerKeyDown) then
  begin
    if FPlanner.Sidebar.Orientation = soVertical then
    begin
      FromSel := Selection.Top;
      ToSel := 1 + Selection.Bottom;
      FromSelPrecis := FromSel * FPlanner.Display.DisplayUnit + FPlanner.Display.DisplayOffset;
      ToSelPrecis := ToSel * FPlanner.Display.DisplayUnit + FPlanner.Display.DisplayOffset;
      FPlanner.FOnPlannerKeyDown(FPlanner, Key, ShiftState, Col - 1, FromSel, FromSelPrecis, ToSel, ToSelPrecis)
    end
    else
    begin
      FromSel := Selection.Left;
      ToSel := 1 + Selection.Right;
      FromSelPrecis := FromSel * FPlanner.Display.DisplayUnit + FPlanner.Display.DisplayOffset;
      ToSelPrecis := ToSel * FPlanner.Display.DisplayUnit + FPlanner.Display.DisplayOffset;
      FPlanner.FOnPlannerKeyDown(FPlanner, Key, ShiftState, Row - 1,
        FromSel, FromSelPrecis, ToSel, ToSelPrecis)
    end;
  end;

  SyncPlanner;
end;

procedure TPlannerGrid.DoExit;
begin
  inherited;
  if Assigned(FPlanner.OnExit) then
    FPlanner.OnExit(FPlanner);
end;

procedure TPlannerGrid.DoEnter;
var
  GridRect: TGridRect;

begin
  inherited;

  if (Selection.Left = -1) or (Selection.Top = -1) then
  begin
    FillChar(GridRect, SizeOf(GridRect), 0);
    Selection := GridRect;
    SelChanged;
  end;
  if Assigned(FPlanner.OnEnter) then
    FPlanner.OnEnter(FPlanner);
end;

procedure TPlannerGrid.KeyPress(var Key: Char);
var
  FromSel, FromSelPrecis: Integer;
  ToSel, ToSelPrecis: Integer;

begin
  if Assigned(FPlanner.FOnPlannerKeypress) then
  begin
    if FPlanner.Sidebar.Orientation = soVertical then
    begin
      FromSel := Selection.Top;
      ToSel := 1 + Selection.Bottom;
      FromSelPrecis := FromSel * FPlanner.Display.DisplayUnit +
        FPlanner.Display.DisplayOffset;
      ToSelPrecis := ToSel * FPlanner.Display.DisplayUnit +
        FPlanner.Display.DisplayOffset;
      FPlanner.FOnPlannerKeypress(FPlanner, Key, Col - 1, FromSel,
        FromSelPrecis, ToSel, ToSelPrecis)
    end
    else
    begin
      FromSel := Selection.Left;
      ToSel := 1 + Selection.Right;
      FromSelPrecis := FromSel * FPlanner.Display.DisplayUnit +
        FPlanner.Display.DisplayOffset;
      ToSelPrecis := ToSel * FPlanner.Display.DisplayUnit +
        FPlanner.Display.DisplayOffset;
      FPlanner.FOnPlannerKeypress(FPlanner, Key, Row - 1, FromSel,
        FromSelPrecis, ToSel, ToSelPrecis)
    end;
  end;
end;

function LongMulDiv(Mult1, Mult2, Div1: Integer): Integer; stdcall; external 'kernel32.dll' Name 'MulDiv';

procedure TPlannerGrid.WMVScroll(var WMScroll: TWMScroll);
begin
  if (Row < FixedRows) or (Col < FixedCols) then
  begin
    Selection := TGridRect(Rect(FixedCols, FixedRows, FixedCols, FixedRows));
    SelChanged;
  end;

  if (WMScroll.ScrollCode = SB_THUMBTRACK) and (FPlanner.FScrollSynch) then
  begin
    TopRow := FixedRows + LongMulDiv(WMScroll.Pos,
      RowCount - VisibleRowCount - FixedRows, MaxShortInt);
  end;

  FOldTopRow := TopRow;

  inherited;

  UpdateVScrollBar;
end;

procedure TPlannerGrid.DestroyWnd;
begin
  inherited;
end;

procedure TPlannerGrid.HintHide;
begin
  FScrollHintWindow.ReleaseHandle;
end;

procedure TPlannerGrid.HintShowXY(X, Y: Integer; AItem: TPlannerItem; Caption: TCaption);
var
  HintRect: TRect;
  ScreenPoint: TPoint;
  Hint: string;
begin
  if not FPlanner.HintOnItemChange then
    Exit;

  Hint := Caption;

  if Assigned(FPlanner.OnItemHintTime) then
    FPlanner.OnItemHintTime(Self, AItem, Hint);

  HintRect := FScrollHintWindow.CalcHintRect(FPlanner.MaxHintWidth,
    Hint, nil);

  FScrollHintWindow.Caption := Hint;
  FScrollHintWindow.Color := FPlanner.HintColor;
  ScreenPoint := ClientToScreen(Point(X, Y));
  HintRect.Left := HintRect.Left + ScreenPoint.X + 10;
  HintRect.Right := HintRect.Right + ScreenPoint.X + 10;
  HintRect.Top := HintRect.Top + ScreenPoint.Y + 10;
  HintRect.Bottom := HintRect.Bottom + ScreenPoint.Y + 10;
  FScrollHintWindow.ActivateHint(HintRect, Caption);
end;

procedure TPlannerGrid.WndProc(var Msg: TMessage);
{ Experimental gesture handling code
var
  gif: TGestureInfo;
  pt,ptc: tpoint;
  plit: tplanneritem;
  d: integer;
}
begin
{ Experimental gesture handling code
  if (msg.Msg = WM_GESTURE) and (FPLanner.DirectMove) then
  begin
    FillChar(gif,sizeof(gif),0);
    gif.cbSize := Sizeof(gif);
    GetGestureInfo(msg.LParam, gif);

    if (gif.dwID = GID_PAN) and Assigned(FPLanner.Items.Selected) then
    begin
      pt := Point(gif.ptsLocation.x, gif.ptsLocation.y);
      pt := ScreenToClient(pt);

      if Assigned(FPLanner.Items.Selected) then
      begin
        ptc := FPLanner.XYToCell(pt.x, pt.Y);

        outputdebugstring(pchar('pan:'+inttostr(ptc.Y)));

        d := FPLanner.Items.Selected.ItemEnd - FPLanner.Items.Selected.ItemBegin;
        FPLanner.Items.Selected.ItemBegin := ptc.y;
        FPLanner.Items.Selected.ItemEnd := ptc.y + d;
        FPLanner.Items.Selected.ItemPos := ptc.x;
      end;
      Msg.Result := 1;
      Exit;
    end;

    if gif.dwID = GID_BEGIN then
    begin
      pt := Point(gif.ptsLocation.x, gif.ptsLocation.y);

      outputdebugstring(pchar('gesture begin:'+ inttostr(pt.X)+':'+inttostr(pt.y)));

      pt := ScreenToClient(pt);

      plit := FPlanner.XYToItem(pt.X, pt.Y);

      if Assigned(plit) then
      begin
        FPlanner.Items.Select(plit);
      end;
    end;
  end;
  }
  inherited;
end;

procedure TPlannerGrid.Paint;
var
  R: TRect;
  fh, i, j, idx, M: Integer;
  p: TPoint;
  vn: integer;
  vs: string;
  t1,t2,dt,cur: TDateTime;
  fpos: double;
  bc: TRect;

begin
  FPlanner.Items.ClearRepaints;

  inherited;
{$IFDEF FREEWARE}
  if (TopRow = RowCount - VisibleRowCount) then
  begin
    Canvas.Font.Name := 'Tahoma';
    Canvas.Font.Size := 8;
    Canvas.Font.Color := clGray;
    Canvas.Brush.Style := bsClear;

    R := CellRect(1, RowCount - 1);
    Canvas.TextOut(R.Left + 4, R.Top + 4, FPlanner.ClassName +
        ' : Copyright © 1999 - 2014 by TMS software');
  end;
{$ENDIF}
  if (csDesigning in ComponentState) and FPlanner.ShowDesignHelper then
  begin
    R := ClientRect;
    Canvas.Font.Name := 'Tahoma';
    Canvas.Font.Size := 8;
    Canvas.Brush.Color := clInfoBk;
    Canvas.Pen.Color := clRed;
    R.Left := R.Right - 150;
    R.Top := R.Bottom - 70;
    Canvas.Rectangle(R);
    Canvas.Font.Color := clNavy;
    Canvas.Font.Style := [fsUnderline];
    fh := Canvas.TextHeight('gh') + 2;

    vn := FPlanner.GetVersionNr;
    vs := IntToStr(Hi(Hiword(vn))) + '.' + IntToStr(Lo(Hiword(vn)))
          + '.' + IntToStr(Hi(Loword(vn))) + '.' + IntToStr(Lo(Loword(vn)));

    Canvas.TextOut(R.Left + 4, R.Top + 4, s_QuickConfig + '[' + vs + ']');

    GetCursorPos(p);
    p := ScreenToClient(p);

    i := MouseOverDesignChoice(p.X, p.Y);

    if i = 1 then
      Canvas.Font.Style := [fsUnderline]
    else
      Canvas.Font.Style := [];

    if (FPlanner.Sidebar.Position in [spLeft, spLeftRight, spRight])
      then
      Canvas.TextOut(R.Left + 4, R.Top + 4 + fh, s_HTimeAxis)
    else
      Canvas.TextOut(R.Left + 4, R.Top + 4 + fh, s_VTimeAxis);

    if i = 2 then
      Canvas.Font.Style := [fsUnderline]
    else
      Canvas.Font.Style := [];

    if (FPlanner.Items.Count) > 0 then
      Canvas.TextOut(R.Left + 4, R.Top + 4 + 2 * fh, s_HideDesignItem)
    else
      Canvas.TextOut(R.Left + 4, R.Top + 4 + 2 * fh, s_ShowDesignItem);

    if i = 3 then
      Canvas.Font.Style := [fsUnderline]
    else
      Canvas.Font.Style := [];

    M := 0;
    case FPlanner.Mode.PlannerType of
      plDay:
        M := 1;
      plMonth:
        M := 2;
      plDayPeriod:
        M := 3;
      plHalfDayPeriod:
        M := 4;
      plMultiMonth:
        M := 5;
      plTimeLine:
        M := 0;
    end;

    Canvas.TextOut(R.Left + 4, R.Top + 4 + 3 * fh, s_Modes[M]);
  end;

  if FPlanner.ShowLinks then
  begin
    PaintLinks;
  end;

  if FPlanner.Sidebar.TimeIndicator and (FPlanner.Sidebar.TimeIndicatorType = tiFullLine) then
  begin
    cur := Now;

    idx := FPlanner.AbsTimeToCell(cur);

    FPlanner.CellToAbsTime(idx, t1, t2);

    if (FPlanner.Sidebar.Position <> spTop) then
    begin
      r := CellRect(0,idx);
      if (cur >= t1) and (cur <= t2) and (r.Top <> r.Bottom) then
      begin
        fpos := FPlanner.Display.DisplayScale * ((cur - t1) / (t2 - t1));
        Canvas.Pen.Color := FPlanner.Sidebar.TimeIndicatorColor;
        Canvas.Pen.Width := 1;
        Canvas.MoveTo(0,r.Top + round(fpos));
        Canvas.LineTo(Width,r.Top + round(fpos));
      end;
    end
    else
    begin
      r := CellRect(idx,0);

      if (cur >= t1) and (cur <= t2) and (r.Left <> r.Right) then
      begin
        fpos := FPlanner.Display.DisplayScale * ((cur - t1) / (t2 - t1));
        Canvas.Pen.Color := FPlanner.Sidebar.TimeIndicatorColor;
        Canvas.Pen.Width := 1;
        Canvas.MoveTo(r.Left + round(fpos), 0);
        Canvas.LineTo(r.Left + round(fpos), Height);
      end;
    end;
  end;

  if FPlanner.TimePointers.Count > 0 then
  begin
    if (FPlanner.Sidebar.Position <> spTop) then
      bc := CellRect(LeftCol + VisibleColCount - 1,0)
    else
      bc := CellRect(LeftCol,TopRow + VisibleRowCount - 1);

    for i := 0 to FPlanner.TimePointers.Count - 1 do
    begin
      dt := FPlanner.TimePointers[i].DateTime;
      idx := FPlanner.AbsTimeToCell(dt);

      FPlanner.CellToAbsTime(idx, t1, t2);

      if (FPlanner.Sidebar.Position <> spTop) then
      begin
        if (idx >= TopRow) and (idx < TopRow + VisibleRowCount)  then
        begin
          r := CellRect(LeftCol,idx);
          if (Frac(dt) >= Frac(t1)) and (Frac(dt) <= Frac(t2)) and (r.Top <> r.Bottom) then
          begin
            fpos := FPlanner.Display.DisplayScale * ((Frac(dt) - Frac(t1)) / (Frac(t2) - Frac(t1)));
            Canvas.Brush.Color := Color;
            Canvas.Pen.Color := FPlanner.TimePointers[i].Color;
            Canvas.Pen.Style := FPlanner.TimePointers[i].Style;

            if Canvas.Pen.Style = psSolid then
            begin
              Canvas.Pen.Width := FPlanner.TimePointers[i].Width;
              Canvas.MoveTo(r.Left,r.Top + round(fpos));
              Canvas.LineTo(bc.Right,r.Top + round(fpos));
            end
            else
            begin
              Canvas.Pen.Width := 1;

              for j := -(FPlanner.TimePointers[i].Width div 2) to (FPlanner.TimePointers[i].Width div 2) do
              begin
                Canvas.MoveTo(r.Left,r.Top + j + round(fpos));
                Canvas.LineTo(bc.Right,r.Top + j + round(fpos));
              end;
            end;

            Canvas.Pen.Style := psSolid;
            Canvas.Pen.Width := 1;
          end;
        end;
      end
      else
      begin
        if (idx >= LeftCol) and (idx < LeftCol + VisibleColCount)  then
        begin
          r := CellRect(idx,TopRow);
          if (Frac(dt) >= Frac(t1)) and (Frac(dt) <= Frac(t2)) and (r.Left <> r.Right) then
          begin
            fpos := FPlanner.Display.DisplayScale * ((Frac(dt) - Frac(t1)) / (Frac(t2) - Frac(t1)));

            Canvas.Brush.Color := Color;
            Canvas.Pen.Color := FPlanner.TimePointers[i].Color;
            Canvas.Pen.Style := FPlanner.TimePointers[i].Style;

            if Canvas.Pen.Style = psSolid then
            begin
              Canvas.Pen.Width := FPlanner.TimePointers[i].Width;
              Canvas.MoveTo(r.Left + round(fpos),r.Top);
              Canvas.LineTo(r.Left + round(fpos),bc.Bottom);
            end
            else
            begin
              Canvas.Pen.Width := 1;

              for j := -(FPlanner.TimePointers[i].Width div 2) to (FPlanner.TimePointers[i].Width div 2) do
              begin
                Canvas.MoveTo(r.Left + j + round(fpos),r.Top);
                Canvas.LineTo(r.Left + j + round(fpos),bc.Bottom);
              end;
            end;

            Canvas.Pen.Style := psSolid;
            Canvas.Pen.Width := 1;
          end;
        end;
      end;
    end;
  end;

  FPlanner.DoAfterPaint;
end;

procedure TPlannerGrid.PaintLinks;
var
  i,m: integer;
  LR1F,LR1T: TRect;
  APlannerItem: TPlannerItem;
  pol: array of TPoint;
begin
  // resolve link painting here after all other painting is done
  for i := 0 to FPlanner.Items.Count - 1 do
  begin
    APlannerItem := FPlanner.Items[i];
    if Assigned(APlannerItem.LinkedItem) and not APlannerItem.InHeader and not APlannerItem.LinkedItem.InHeader then
    begin
      // get rect from - to

      LR1F := APlannerItem.GetItemPaintRect;
      LR1T := APlannerItem.LinkedItem.GetItemPaintRect;

      Canvas.Pen.Color := APlannerItem.LinkColor;

      if (lr1f.Top = 0) and (lr1t.Top = 0) then
        Continue;

      if (lr1f.Left = 0) and (lr1t.Left = 0) then
        Continue;

      SetLength(pol,3);

      if (LR1F.Right < LR1T.Left) then
      begin
        m := LR1F.Right + (LR1T.Left - LR1F.Right) div 2;

        // 1
        Canvas.MoveTo(m,Min(LR1F.Bottom, LR1F.Top + (LR1F.Bottom -  LR1F.Top) div 2));
        Canvas.LineTo(m,Min(LR1T.Bottom, LR1T.Top + (LR1T.Bottom -  LR1T.Top) div 2));

        // 2
        if LR1F.Bottom > 0 then
        begin
          Canvas.MoveTo(LR1F.Right, LR1F.Top + (LR1F.Bottom -  LR1F.Top) div 2);
          Canvas.LineTo(m + 1, LR1F.Top + (LR1F.Bottom -  LR1F.Top) div 2);

          if (APLannerItem.LinkArrow in [laToFrom, laBoth]) then
          begin
            if FPlanner.LinkArrowShape = asNormal then
            begin
              Canvas.MoveTo(LR1F.Right,LR1F.Top + (LR1F.Bottom -  LR1F.Top) div 2);
              Canvas.LineTo(LR1F.Right + FPlanner.LinkArrowSize,FPlanner.LinkArrowSize+ LR1F.Top + (LR1F.Bottom -  LR1F.Top) div 2);

              Canvas.MoveTo(LR1F.Right,LR1F.Top + (LR1F.Bottom -  LR1F.Top) div 2);
              Canvas.LineTo(LR1F.Right + FPlanner.LinkArrowSize, -FPlanner.LinkArrowSize+ LR1F.Top + (LR1F.Bottom -  LR1F.Top) div 2);
            end;

            if FPlanner.LinkArrowShape = asFilled then
            begin
              pol[0].X := LR1F.Right;
              pol[0].Y := LR1F.Top + (LR1F.Bottom -  LR1F.Top) div 2;
              pol[1].X := LR1F.Right + FPlanner.LinkArrowSize;
              pol[1].Y := FPlanner.LinkArrowSize+ LR1F.Top + (LR1F.Bottom -  LR1F.Top) div 2;
              pol[2].X := LR1F.Right + FPlanner.LinkArrowSize;
              pol[2].Y := -FPlanner.LinkArrowSize+ LR1F.Top + (LR1F.Bottom -  LR1F.Top) div 2;

              Canvas.Brush.Color := Canvas.Pen.Color;
              Canvas.Brush.Style := bsSolid;
              Canvas.Polygon(pol);
            end;
          end;
        end;

        // 3
        if LR1T.Bottom > 0 then
        begin
          Canvas.MoveTo(LR1T.Left, Min(LR1T.Bottom, LR1T.Top + (LR1T.Bottom -  LR1T.Top) div 2));
          Canvas.LineTo(m - 1, Min(LR1T.Bottom, LR1T.Top + (LR1T.Bottom -  LR1T.Top) div 2));


          if (APLannerItem.LinkArrow in [laFromTo, laBoth]) then
          begin
            if FPlanner.LinkArrowShape = asNormal then
            begin
              Canvas.MoveTo(LR1T.Left,LR1T.Top + (LR1T.Bottom -  LR1T.Top) div 2);
              Canvas.LineTo(LR1T.Left - FPlanner.LinkArrowSize,FPlanner.LinkArrowSize + LR1T.Top + (LR1T.Bottom -  LR1T.Top) div 2);

              Canvas.MoveTo(LR1T.Left,LR1T.Top + (LR1T.Bottom -  LR1T.Top) div 2);
              Canvas.LineTo(LR1T.Left - FPlanner.LinkArrowSize, -FPlanner.LinkArrowSize + LR1T.Top + (LR1T.Bottom -  LR1T.Top) div 2);
            end;

            if FPlanner.LinkArrowShape = asFilled then
            begin
              pol[0].X := LR1T.Left;
              pol[0].Y := LR1T.Top + (LR1T.Bottom -  LR1T.Top) div 2;
              pol[1].X := LR1T.Left - FPlanner.LinkArrowSize;
              pol[1].Y := FPlanner.LinkArrowSize + LR1T.Top + (LR1T.Bottom -  LR1T.Top) div 2;
              pol[2].X := LR1T.Left - FPlanner.LinkArrowSize;
              pol[2].Y := -FPlanner.LinkArrowSize + LR1T.Top + (LR1T.Bottom -  LR1T.Top) div 2;

              Canvas.Brush.Color := Canvas.Pen.Color;
              Canvas.Brush.Style := bsSolid;
              Canvas.Polygon(pol);
            end;
          end;
        end;
      end
      else
      if (LR1F.Left > LR1T.Right) then
      begin
        m := LR1F.Left - (LR1F.Left - LR1T.Right) div 2;

        Canvas.MoveTo(m,Min(LR1F.Bottom, LR1F.Top + (LR1F.Bottom -  LR1F.Top) div 2));
        Canvas.LineTo(m,Min(LR1T.Bottom, LR1T.Top + (LR1T.Bottom -  LR1T.Top) div 2));

        if LR1F.Bottom > 0 then
        begin
          Canvas.MoveTo(LR1F.Left, Min(LR1F.Bottom, LR1F.Top + (LR1F.Bottom -  LR1F.Top) div 2));
          Canvas.LineTo(m - 1, Min(LR1F.Bottom, LR1F.Top + (LR1F.Bottom -  LR1F.Top) div 2));

          if (APLannerItem.LinkArrow in [laToFrom, laBoth]) then
          begin
            if FPlanner.LinkArrowShape = asNormal then
            begin
              Canvas.MoveTo(LR1F.Left,LR1F.Top + (LR1F.Bottom -  LR1F.Top) div 2);
              Canvas.LineTo(LR1F.Left - FPlanner.LinkArrowSize,FPlanner.LinkArrowSize + LR1F.Top + (LR1F.Bottom -  LR1F.Top) div 2);

              Canvas.MoveTo(LR1F.Left,LR1F.Top + (LR1F.Bottom -  LR1F.Top) div 2);
              Canvas.LineTo(LR1F.Left - FPlanner.LinkArrowSize, -FPlanner.LinkArrowSize + LR1F.Top + (LR1F.Bottom -  LR1F.Top) div 2);
            end;

            if FPlanner.LinkArrowShape = asFilled then
            begin
              pol[0].X := LR1F.Left;
              pol[0].Y := LR1F.Top + (LR1F.Bottom -  LR1F.Top) div 2;
              pol[1].X := LR1F.Left - FPlanner.LinkArrowSize;
              pol[1].Y := FPlanner.LinkArrowSize + LR1F.Top + (LR1F.Bottom -  LR1F.Top) div 2;
              pol[2].X := LR1F.Left - FPlanner.LinkArrowSize;
              pol[2].Y := -FPlanner.LinkArrowSize + LR1F.Top + (LR1F.Bottom -  LR1F.Top) div 2;

              Canvas.Brush.Color := Canvas.Pen.Color;
              Canvas.Brush.Style := bsSolid;
              Canvas.Polygon(pol);
            end;
          end;
        end;

        if LR1T.Bottom > 0 then
        begin
          Canvas.MoveTo(LR1T.Right,LR1T.Top + (LR1T.Bottom -  LR1T.Top) div 2);
          Canvas.LineTo(m + 1,LR1T.Top + (LR1T.Bottom -  LR1T.Top) div 2);

          if (APLannerItem.LinkArrow in [laFromTo, laBoth]) then
          begin
            if FPlanner.LinkArrowShape = asNormal then
            begin
              Canvas.MoveTo(LR1T.Right,LR1T.Top + (LR1T.Bottom -  LR1T.Top) div 2);
              Canvas.LineTo(LR1T.Right + FPlanner.LinkArrowSize,FPlanner.LinkArrowSize + LR1T.Top + (LR1T.Bottom -  LR1T.Top) div 2);

              Canvas.MoveTo(LR1T.Right,LR1T.Top + (LR1T.Bottom -  LR1T.Top) div 2);
              Canvas.LineTo(LR1T.Right + FPlanner.LinkArrowSize, -FPlanner.LinkArrowSize + LR1T.Top + (LR1T.Bottom -  LR1T.Top) div 2);
            end;

            if FPlanner.LinkArrowShape = asFilled then
            begin
              pol[0].X := LR1T.Right;
              pol[0].Y := LR1T.Top + (LR1T.Bottom -  LR1T.Top) div 2;
              pol[1].X := LR1T.Right + FPlanner.LinkArrowSize;
              pol[1].Y := FPlanner.LinkArrowSize + LR1T.Top + (LR1T.Bottom -  LR1T.Top) div 2;
              pol[2].X := LR1T.Right + FPlanner.LinkArrowSize;
              pol[2].Y := -FPlanner.LinkArrowSize + LR1T.Top + (LR1T.Bottom -  LR1T.Top) div 2;

              Canvas.Brush.Color := Canvas.Pen.Color;
              Canvas.Brush.Style := bsSolid;
              Canvas.Polygon(pol);
            end;
          end;
        end;
      end
      else
      if (LR1F.Bottom < LR1T.Top) then
      begin
        m := LR1F.Bottom  + (LR1T.Top - LR1F.Bottom) div 2;

        Canvas.MoveTo(LR1F.Left + (LR1F.Right - LR1F.Left) div 2, m);
        Canvas.LineTo(LR1T.Left + (LR1T.Right - LR1T.Left) div 2, m);

        Canvas.MoveTo(LR1F.Left + (LR1F.Right - LR1F.Left) div 2, m);
        Canvas.LineTo(LR1F.Left + (LR1F.Right - LR1F.Left) div 2, LR1F.Bottom);

        if (APLannerItem.LinkArrow in [laToFrom, laBoth]) then
        begin
          if FPlanner.LinkArrowShape = asNormal then
          begin
            Canvas.MoveTo(LR1F.Left + (LR1F.Right - LR1F.Left) div 2, LR1F.Bottom);
            Canvas.LineTo(LR1F.Left + FPlanner.LinkArrowSize + (LR1F.Right - LR1F.Left) div 2, LR1F.Bottom + FPlanner.LinkArrowSize);

            Canvas.MoveTo(LR1F.Left + (LR1F.Right - LR1F.Left) div 2, LR1F.Bottom);
            Canvas.LineTo(LR1F.Left - FPlanner.LinkArrowSize + (LR1F.Right - LR1F.Left) div 2, LR1F.Bottom + FPlanner.LinkArrowSize);
          end;

          if FPlanner.LinkArrowShape = asFilled then
          begin
            pol[0].X := LR1F.Left + (LR1F.Right - LR1F.Left) div 2;
            pol[0].Y := LR1F.Bottom;
            pol[1].X := LR1F.Left + FPlanner.LinkArrowSize + (LR1F.Right - LR1F.Left) div 2;
            pol[1].Y := LR1F.Bottom + FPlanner.LinkArrowSize;
            pol[2].X := LR1F.Left - FPlanner.LinkArrowSize + (LR1F.Right - LR1F.Left) div 2;
            pol[2].Y := LR1F.Bottom + FPlanner.LinkArrowSize;

            Canvas.Brush.Color := Canvas.Pen.Color;
            Canvas.Brush.Style := bsSolid;
            Canvas.Polygon(pol);
          end;
        end;

        Canvas.MoveTo(LR1T.Left + (LR1T.Right - LR1T.Left) div 2, m);
        Canvas.LineTo(LR1T.Left + (LR1T.Right - LR1T.Left) div 2, LR1T.Top);

        if (APLannerItem.LinkArrow in [laFromTo, laBoth]) then
        begin
          if FPlanner.LinkArrowShape = asNormal then
          begin
            Canvas.MoveTo(LR1T.Left + (LR1T.Right - LR1T.Left) div 2, LR1T.Top);
            Canvas.LineTo(LR1T.Left + FPlanner.LinkArrowSize + (LR1T.Right - LR1T.Left) div 2, LR1T.Top - FPlanner.LinkArrowSize );

            Canvas.MoveTo(LR1T.Left  + (LR1T.Right - LR1T.Left) div 2, LR1T.Top);
            Canvas.LineTo(LR1T.Left - FPlanner.LinkArrowSize + (LR1T.Right - LR1T.Left) div 2, LR1T.Top - FPlanner.LinkArrowSize);
          end;

          if FPlanner.LinkArrowShape = asFilled then
          begin
            pol[0].X := LR1T.Left + (LR1T.Right - LR1T.Left) div 2;
            pol[0].Y := LR1T.Top;
            pol[1].X := LR1T.Left + FPlanner.LinkArrowSize + (LR1T.Right - LR1T.Left) div 2;
            pol[1].Y := LR1T.Top - FPlanner.LinkArrowSize;
            pol[2].X := LR1T.Left - FPlanner.LinkArrowSize + (LR1T.Right - LR1T.Left) div 2;
            pol[2].Y := LR1T.Top - FPlanner.LinkArrowSize;

            Canvas.Brush.Color := Canvas.Pen.Color;
            Canvas.Brush.Style := bsSolid;
            Canvas.Polygon(pol);
          end;
        end;
      end
      else
      if (LR1F.Top > LR1T.Bottom) then
      begin
        m := LR1T.Bottom  + (LR1F.Top - LR1T.Bottom) div 2;

        Canvas.MoveTo(LR1F.Left + (LR1F.Right - LR1F.Left) div 2, m);
        Canvas.LineTo(LR1T.Left + (LR1T.Right - LR1T.Left) div 2, m);

        Canvas.MoveTo(LR1T.Left + (LR1T.Right - LR1T.Left) div 2, m);
        Canvas.LineTo(LR1T.Left + (LR1T.Right - LR1T.Left) div 2, LR1T.Bottom);

        if (APLannerItem.LinkArrow in [laFromTo, laBoth]) then
        begin
          if FPlanner.LinkArrowShape = asNormal then
          begin
            Canvas.MoveTo(LR1T.Left + (LR1T.Right - LR1T.Left) div 2, LR1T.Bottom);
            Canvas.LineTo(LR1T.Left + FPlanner.LinkArrowSize + (LR1T.Right - LR1T.Left) div 2, LR1T.Bottom + FPlanner.LinkArrowSize);

            Canvas.MoveTo(LR1T.Left + (LR1T.Right - LR1T.Left) div 2, LR1T.Bottom);
            Canvas.LineTo(LR1T.Left - FPlanner.LinkArrowSize + (LR1T.Right - LR1T.Left) div 2, LR1T.Bottom + FPlanner.LinkArrowSize);
          end;

          if FPlanner.LinkArrowShape = asFilled then
          begin
            pol[0].X := LR1T.Left + (LR1T.Right - LR1T.Left) div 2;
            pol[0].Y := LR1T.Bottom;
            pol[1].X := LR1T.Left + FPlanner.LinkArrowSize + (LR1T.Right - LR1T.Left) div 2;
            pol[1].Y := LR1T.Bottom + FPlanner.LinkArrowSize;
            pol[2].X := LR1T.Left - FPlanner.LinkArrowSize + (LR1T.Right - LR1T.Left) div 2;
            pol[2].Y := LR1T.Bottom + FPlanner.LinkArrowSize;

            Canvas.Brush.Color := Canvas.Pen.Color;
            Canvas.Brush.Style := bsSolid;
            Canvas.Polygon(pol);
          end;
        end;

        Canvas.MoveTo(LR1F.Left + (LR1F.Right - LR1F.Left) div 2, m);
        Canvas.LineTo(LR1F.Left + (LR1F.Right - LR1F.Left) div 2, LR1F.Top);

        if (APLannerItem.LinkArrow in [laToFrom, laBoth]) then
        begin
          if FPlanner.LinkArrowShape = asNormal then
          begin
            Canvas.MoveTo(LR1F.Left + (LR1F.Right - LR1F.Left) div 2, LR1F.Top);
            Canvas.LineTo(LR1F.Left + FPlanner.LinkArrowSize + (LR1F.Right - LR1F.Left) div 2, LR1F.Top - FPlanner.LinkArrowSize);

            Canvas.MoveTo(LR1F.Left + (LR1F.Right - LR1F.Left) div 2, LR1F.Top);
            Canvas.LineTo(LR1F.Left - FPlanner.LinkArrowSize + (LR1F.Right - LR1F.Left) div 2, LR1F.Top - FPlanner.LinkArrowSize);
          end;

          if FPlanner.LinkArrowShape = asFilled then
          begin
            pol[0].X := LR1F.Left + (LR1F.Right - LR1F.Left) div 2;
            pol[0].Y := LR1F.Top;
            pol[1].X := LR1F.Left + FPlanner.LinkArrowSize + (LR1F.Right - LR1F.Left) div 2;
            pol[1].Y := LR1F.Top - FPlanner.LinkArrowSize;
            pol[2].X := LR1F.Left - FPlanner.LinkArrowSize + (LR1F.Right - LR1F.Left) div 2;
            pol[2].Y := LR1F.Top - FPlanner.LinkArrowSize;

            Canvas.Brush.Color := Canvas.Pen.Color;
            Canvas.Brush.Style := bsSolid;
            Canvas.Polygon(pol);
          end;
        end;
      end;
    end;
  end;
end;

procedure TPlannerGrid.RepaintSelection(ASelection: TGridRect);
var
  i: Integer;
  R: TRect;
begin
  if ActiveCellShow = assRow then
  begin
    for i := ASelection.Left to ASelection.Right do
    begin
      R := CellRect(i, 0);
      InvalidateRect(Handle, @R, True);
      if FPlanner.Sidebar.ShowInPositionGap then
      begin
        R := CellRect(i, 1);
        InvalidateRect(Handle, @R, True);
      end;
    end;
  end;

  if (ActiveCellShow = assCol) or (FPlanner.Display.DisplayText > 0) then
  begin
    for i := ASelection.Top to ASelection.Bottom do
    begin
      R := CellRect(0, i);
      InflateRect(R, 2, 2);
      InvalidateRect(Handle, @R, True);
      if FPlanner.Sidebar.ShowInPositionGap then
      begin
        R := CellRect(1, i);
        InvalidateRect(Handle, @R, True);
      end;
      if (FPlanner.Sidebar.Position in [spRight, spLeftRight]) then
      begin
        R := CellRect(ColCount - 1, i);
        InflateRect(R, 2, 2);
        InvalidateRect(Handle, @R, True);
      end;
    end;
  end;
end;

function TPlannerGrid.SelectCell(AColumn, ARow: Integer): Boolean;
var
  CanSelect: Boolean;
  PF: TCustomForm;
begin
  PF := GetParentForm(Self);

  if (FPlanner.Sidebar.Position in [spRight, spLeftRight])
    and FPlanner.Sidebar.Visible and (AColumn = ColCount - 1) then
  begin
    Result := False;
    Exit;
  end;

  if AutoFocus then
  begin
    try
      if Assigned(PF) then
      begin
        if PF.Visible and Visible then
          SetFocus;
      end
      else if Visible then
        SetFocus;
    except
    end;
  end;

  CanSelect := inherited SelectCell(AColumn, ARow);
  Result := CanSelect;

  if Assigned(FPlanner.OnPlannerSelectCell) then
  begin
    if FPlanner.Sidebar.Position in [spLeft, spRight, spLeftRight] then
      FPlanner.OnPlannerSelectCell(FPlanner, ARow, AColumn, CanSelect)
    else
      FPlanner.OnPlannerSelectCell(FPlanner, AColumn, ARow, CanSelect);

    Result := CanSelect;

    if not Result then
      Abort;
  end;
end;

function TPlannerGrid.CellRectEx(X, Y: Integer): TRect;
begin

  if Y > TopRow + VisibleRowCount then
    Y := TopRow + VisibleRowCount - 1;

  if Y < TopRow then
    Y := TopRow;

  if X > LeftCol + VisibleColCount then
    X := LeftCol + VisibleColCount - 1;

  if (X < LeftCol) and (FPlanner.Sidebar.Position <> spRight) then
    X := LeftCol;

  Result := CellRect(X, Y);

  if (FPlanner.Sidebar.Position in [spLeft, spLeftRight]) and
    (FPlanner.FPositionGap > 0) and FPlanner.GapAtColumn(X) then
  begin
    Result.Left := Result.Left + FPlanner.FPositionGap;
  end;
end;

function TPlannerGrid.ColWidthEx(ItemPos: Integer): Integer;
begin
  if FPlanner.Sidebar.Position <> spRight then
    Inc(ItemPos);

  if (FPlanner.PositionGap > 0) and FPlanner.GapAtColumn(ItemPos) then
    Result := ColWidths[ItemPos] - FPlanner.FPositionGap
  else
    Result := ColWidths[ItemPos];
end;

function TPlannerGrid.RowHeightEx(ItemPos: Integer): Integer;
begin
  //if not FPlanner.FSideBar.Visible then
  Inc(ItemPos);

  //  Result := RowHeights[ItemPos] - FPlanner.FPositionGap;
  Result := RowHeights[ItemPos];
end;

procedure TPlannerGrid.GetSideBarLines(Index, Position: Integer;
  var Line1, Line2, Line3: string; var HS: Boolean);
var
  Mins: Integer;
  DT, dte: TDateTime;
  h, M, s, s100: Word;
  dbl: double;
begin
  Line1 := '';
  Line2 := '';
  Line3 := '';

  case FPlanner.FMode.FPlannerType of
    plDay:
      begin
        Mins := (Index + FPlanner.Display.DisplayStart)
          * FPlanner.Display.DisplayUnit +
          FPlanner.Display.DisplayOffset;

        HS := (Mins div 60) <> ((Mins - FPlanner.Display.DisplayUnit)
            div 60);

        if (Mins = 0) then
          HS := True;

        FPlanner.PlanTimeToStrings(Mins, Line1, Line2, Line3);
      end;
    plTimeLine:
      begin
        FPlanner.CellToAbsTime(Index, DT, dte);

        DecodeTime(DT, h, M, s, s100);

        Mins := h * 60 + M;

        {
         Mins := (Index + FPlanner.Display.DisplayStart) * FPlanner.Display.DisplayUnit
         + FPlanner.Display.DisplayOffset;
         }

        HS := (Mins div 60) <> ((Mins - FPlanner.Display.DisplayUnit)
            div 60);

        FPlanner.PlanTimeToStrings(Mins, Line1, Line2, Line3);
      end;
    plWeek:
      begin
        if FPlanner.Sidebar.ShowDayName then
          Line2 := FPlanner.GetDayName
            (Index - FPlanner.FMode.WeekStart);
        if FPlanner.Sidebar.FDateTimeFormat <> '' then
          Line2 := Line2 + ' ' + FormatDateTime
            (FPlanner.Sidebar.FDateTimeFormat,
            FPlanner.Mode.StartOfMonth + Index);
        HS := True;
      end;
    plMonth:
      begin
        if FPlanner.Sidebar.ShowDayName then
          Line1 := FPlanner.GetDayName
            (DayOfWeek(Index + FPlanner.FMode.StartOfMonth));
        Line2 := FormatDateTime(FPlanner.Sidebar.FDateTimeFormat,
          FPlanner.Mode.StartOfMonth + Index);
        HS := True;
      end;
    plActiveDayPeriod:
      begin
        dt := FPlanner.AddActiveDays(FPlanner.Mode.PeriodStartDate, Index);
        if FPlanner.Sidebar.ShowDayName then
          Line1 := FPlanner.GetDayName(DayOfWeek(dt));
        Line2 := FormatDateTime(FPlanner.Sidebar.DateTimeFormat, dt);
      end;
    plDayPeriod:
      begin
        dt := Index + FPlanner.FMode.PeriodStartDate;
        if FPlanner.Sidebar.ShowDayName then
          Line1 := FPlanner.GetDayName(DayOfWeek(dt));
        Line2 := FormatDateTime(FPlanner.Sidebar.DateTimeFormat, dt);
        HS := True;
      end;
    plHalfDayPeriod:
      begin
        if FPlanner.Sidebar.ShowDayName then
        begin
          dbl := Index / 2;
          Line1 := FPlanner.GetDayName
            (DayOfWeek(Trunc(dbl) + FPlanner.FMode.PeriodStartDate));
        end;
        Line2 := FormatDateTime(FPlanner.Sidebar.DateTimeFormat,
          Trunc(FPlanner.Mode.PeriodStartDate + Index / 2));
        if Odd(Index) then
          Line3 := 'PM'
        else
          Line3 := 'AM';
        HS := True;
      end;
    plMultiMonth:
      begin
        if Index < 31 then
          Line2 := IntToStr(Index + 1);
        HS := True;
      end;
    plCustom, plCustomList:
      begin
        DT := FPlanner.IndexToTime(Index);
        Line1 := FormatDateTime(FPlanner.Sidebar.DateTimeFormat, DT);
        HS := True;
      end;
  end;

  if Assigned(FPlanner.OnPlannerGetSideBarLines) then
  begin
    FPlanner.OnPlannerGetSideBarLines(FPlanner, Index, Position, Line1, Line2, Line3);
    HS := Line1 <> '';
  end;
end;

procedure TPlannerGrid.KeyUp(var Key: Word; ShiftState: TShiftState);
var
  FromSel, FromSelPrecis: Integer;
  ToSel, ToSelPrecis: Integer;
begin
  inherited;
  if Assigned(FPlanner.FOnPlannerKeyUp) then
  begin
    if FPlanner.Sidebar.Orientation = soVertical then
    begin
      FromSel := Selection.Top;
      ToSel := 1 + Selection.Bottom;
      FromSelPrecis := FromSel * FPlanner.Display.DisplayUnit +
        FPlanner.Display.DisplayOffset;
      ToSelPrecis := ToSel * FPlanner.Display.DisplayUnit +
        FPlanner.Display.DisplayOffset;
      FPlanner.FOnPlannerKeyUp(FPlanner, Key, ShiftState, Col - 1,
        FromSel, FromSelPrecis, ToSel, ToSelPrecis)
    end
    else
    begin
      FromSel := Selection.Left;
      ToSel := 1 + Selection.Right;
      FromSelPrecis := FromSel * FPlanner.Display.DisplayUnit +
        FPlanner.Display.DisplayOffset;
      ToSelPrecis := ToSel * FPlanner.Display.DisplayUnit +
        FPlanner.Display.DisplayOffset;
      FPlanner.FOnPlannerKeyUp(FPlanner, Key, ShiftState, Row - 1,
        FromSel, FromSelPrecis, ToSel, ToSelPrecis)
    end;
  end;
end;

procedure TPlannerGrid.SyncPlanner;
begin
  if Assigned(FPlanner.SyncPlanner.Planner) then
  begin
    FPlanner.SyncPlanner.Planner.GridControl.AutoFocus := false;

    if FPlanner.SyncPlanner.SelectionColumn then
      FPlanner.SyncPlanner.Planner.GridControl.Col := Col;

    if FPlanner.SyncPlanner.SelectionRow then
      FPlanner.SyncPlanner.Planner.GridControl.Row := Row;

    FPlanner.SyncPlanner.Planner.GridControl.AutoFocus := true;
  end;

end;

procedure TPlannerGrid.UpdateHScrollBar;
var
  ScrollInfo: TScrollInfo;
begin
  if not(ScrollBars in [ssBoth, ssHorizontal]) then
    Exit;

  if not FPlanner.ScrollBarStyle.Flat then
    Exit;

  ScrollInfo.FMask := SIF_ALL;
  ScrollInfo.cbSize := SizeOf(ScrollInfo);
  GetScrollInfo(Self.Handle, SB_HORZ, ScrollInfo);
  ScrollInfo.FMask := SIF_ALL;
  ScrollInfo.cbSize := SizeOf(ScrollInfo);
  FlatSetScrollInfo(SB_HORZ, ScrollInfo, True)
end;

procedure TPlannerGrid.UpdateVScrollBar;
var
  ScrollInfo: TScrollInfo;
begin
  if not(ScrollBars in [ssBoth, ssVertical]) then
    Exit;

  if not FPlanner.ScrollBarStyle.Flat then
    Exit;

  ScrollInfo.FMask := SIF_ALL;
  ScrollInfo.cbSize := SizeOf(ScrollInfo);
  GetScrollInfo(Handle, SB_VERT, ScrollInfo);

  ScrollInfo.FMask := SIF_ALL;
  ScrollInfo.cbSize := SizeOf(ScrollInfo);
  FlatSetScrollInfo(SB_VERT, ScrollInfo, True);
end;

procedure TPlannerGrid.FlatSetScrollInfo(Code: Integer;
  var ScrollInfo: TScrollInfo; FRedraw: Bool);
var
  ComCtl32DLL: THandle;
  _FlatSB_SetScrollInfo: function(wnd: hwnd; Code: Integer;
    var ScrollInfo: TScrollInfo; FRedraw: Bool): Integer;
stdcall;
begin
  ComCtl32DLL := GetModuleHandle(ComCtrl);
  if ComCtl32DLL > 0 then
  begin

    @_FlatSB_SetScrollInfo := GetProcAddress(ComCtl32DLL,
      'FlatSB_SetScrollInfo');
    if Assigned(_FlatSB_SetScrollInfo) then
    begin
      _FlatSB_SetScrollInfo(Self.Handle, Code, ScrollInfo, FRedraw);
    end;
  end;
end;

procedure TPlannerGrid.FlatScrollInit;
var
  ComCtl32DLL: THandle;
  _InitializeFlatSB: function(wnd: hwnd): Bool stdcall;
begin
  ComCtl32DLL := GetModuleHandle(ComCtrl);
  if ComCtl32DLL > 0 then
  begin
    @_InitializeFlatSB := GetProcAddress(ComCtl32DLL,
      'InitializeFlatSB');
    if Assigned(_InitializeFlatSB) then
      _InitializeFlatSB(Self.Handle);
  end;
end;

procedure TPlannerGrid.FlatScrollDone;
var
  ComCtl32DLL: THandle;
  _UninitializeFlatSB: function(wnd: hwnd): Bool stdcall;
begin
  ComCtl32DLL := GetModuleHandle(ComCtrl);
  if ComCtl32DLL > 0 then
  begin
    @_UninitializeFlatSB := GetProcAddress(ComCtl32DLL,
      'UninitializeFlatSB');
    if Assigned(_UninitializeFlatSB) then
      _UninitializeFlatSB(Self.Handle);
  end;
end;

procedure TPlannerGrid.FormExit(Sender: TObject);
var
  s: string;
  ComboIdx: Integer;
  ComboObj: TObject;
begin
  if FInplaceEdit.Visible then
  begin
    s := FCurrCtrlItem.Text.Text;
    SetControlValue(s, FCurrCtrlEdit, FInplaceEdit.Text);
    FCurrCtrlItem.Text.Text := s;
    FInplaceEdit.Hide;
    if Assigned(FPlanner.OnItemControlEditDone) then
      FPlanner.OnItemControlEditDone(Self, 0, 0, FCurrCtrlItem,
        FCurrCtrlEdit, 'EDIT', FInplaceEdit.Text);
  end;

  if FInplaceCombo.Visible then
  begin
    s := FCurrCtrlItem.Text.Text;

    ComboIdx := FInplaceCombo.ItemIndex;
    if ComboIdx >= 0 then
      ComboObj := FInplaceCombo.Items.Objects[ComboIdx]
    else
      ComboObj := nil;

    SetControlValue(s, FCurrCtrlEdit, FInplaceCombo.Text);
    FCurrCtrlItem.Text.Text := s;
    FInplaceCombo.Hide;
    if Assigned(FPlanner.OnItemControlEditDone) then
      FPlanner.OnItemControlEditDone(Self, 0, 0, FCurrCtrlItem,
        FCurrCtrlEdit, 'COMBO', s);
    if Assigned(FPlanner.OnItemControlComboSelect) then
      FPlanner.OnItemControlComboSelect(Self, 0, 0, FCurrCtrlItem,
        FCurrCtrlEdit, s, ComboIdx, ComboObj);
  end;
end;

procedure TPlannerGrid.FormHandle(Item: TPlannerItem;
  ControlRect: TRect; ControlID, ControlType,
  ControlValue: string);
var
  s: string;
  sl: TStringList;
  Edit: Boolean;
  Dropheight: Integer;
begin
  if Item.ReadOnly or (FPlanner.UserMode in [puReadOnly, puViewOnly])
    then
    Exit;

  FCurrCtrlItem := Item;
  FCurrCtrlEdit := ControlID;

  if ControlType = 'CHECK' then
  begin
    s := Item.Text.Text;

    if Uppercase(ControlValue) = 'TRUE' then
      SetControlValue(s, ControlID, 'FALSE')
    else
      SetControlValue(s, ControlID, 'TRUE');

    Item.Text.Text := s;
  end;

  if ControlType = 'RADIO' then
  begin
    s := ClearRadioControls(Item.Text.Text);
    SetControlValue(s, ControlID, 'TRUE');
    Item.Text.Text := s;
  end;

  if Assigned(FPlanner.OnItemControlEditStart) then
    FPlanner.OnItemControlEditStart(Self, ControlRect.Left,
      ControlRect.Right, Item, ControlID, ControlType, ControlValue);

  if ControlType = 'EDIT' then
  begin
    FInplaceEdit.Width := 0;
    FInplaceEdit.Parent := Self;
    FInplaceEdit.Visible := True;
    FInplaceEdit.OnExit := FormExit;
    FInplaceEdit.Text := ControlValue;
    FInplaceEdit.BorderStyle := bsNone;
    FInplaceEdit.Left := ControlRect.Left + 2;
    FInplaceEdit.Width := ControlRect.Right - ControlRect.Left - 3;
    FInplaceEdit.Top := ControlRect.Top + 6;
    FInplaceEdit.Height := ControlRect.Bottom - ControlRect.Top - 4;
    BringWindowToTop(FInplaceEdit.Handle);
    FInplaceEdit.SetFocus;
  end;

  if ControlType = 'COMBO' then
  begin
    FInplaceCombo.Width := 0;
    FInplaceCombo.Parent := Self;

    FInplaceCombo.BKColor := ColorToRGB(Item.SelectColor);
    FInplaceCombo.Color := ColorToRGB(Item.SelectColor);
    FInplaceCombo.Visible := True;
    FInplaceCombo.OnExit := FormExit;
    FInplaceCombo.Text := ControlValue;
    FInplaceCombo.Left := ControlRect.Left + 4;
    FInplaceCombo.Width := ControlRect.Right - ControlRect.Left - 4;
    FInplaceCombo.Top := ControlRect.Top + 6;

    Dropheight := 200;

    if Assigned(FPlanner.OnItemControlComboList) then
    begin
      sl := TStringList.Create;
      Edit := True;
      FPlanner.OnItemControlComboList(Self, Item, ControlID,
        ControlValue, Edit, sl, Dropheight);

      if Edit then
        FInplaceCombo.Style := csDropDown
      else
        FInplaceCombo.Style := csDropDownList;

      FInplaceCombo.Items.Assign(sl);

      FInplaceCombo.ItemIndex := sl.IndexOf(ControlValue);

      sl.Free;
    end;

    if Edit then
      FInplaceCombo.Height := ControlRect.Bottom - ControlRect.Top - 4
    else
      FInplaceCombo.Height := Dropheight;

    BringWindowToTop(FInplaceCombo.Handle);
    FInplaceCombo.SetFocus;

    FInplaceCombo.DroppedDown := True;
  end;
end;

procedure TPlannerGrid.WMHScroll(var WMScroll: TWMScroll);
begin
  FOldLeftCol := LeftCol;

  inherited;

  if (WMScroll.ScrollCode = SB_THUMBTRACK) and (FPlanner.FScrollSynch)
    then
  begin
    LeftCol := FixedCols + LongMulDiv(WMScroll.Pos,
      ColCount - VisibleColCount - FixedCols, MaxShortInt);
  end;

  UpdateHScrollBar;
end;

procedure TPlannerGrid.FlatSetScrollProp(Index, NewValue: Integer;
  FRedraw: Bool);
var
  ComCtl32DLL: THandle;
  _FlatSB_SetScrollProp: function(wnd: hwnd; Index, NewValue: Integer;
    FRedraw: Bool): Bool stdcall;
begin
  ComCtl32DLL := GetModuleHandle(ComCtrl);
  if ComCtl32DLL > 0 then
  begin
    @_FlatSB_SetScrollProp := GetProcAddress(ComCtl32DLL,
      'FlatSB_SetScrollProp');
    if Assigned(_FlatSB_SetScrollProp) then
      _FlatSB_SetScrollProp(Self.Handle, Index, NewValue, FRedraw);
  end;
end;

procedure TPlannerGrid.FlatShowScrollBar(Code: Integer; Show: Bool);
var
  ComCtl32DLL: THandle;
  _FlatSB_ShowScrollBar: function(wnd: hwnd; Code: Integer;
    Show: Bool): Integer;
stdcall;
begin
  case Code of
    SB_VERT:
      if not(ScrollBars in [ssBoth, ssVertical]) then
        Exit;
    SB_HORZ:
      if not(ScrollBars in [ssBoth, ssHorizontal]) then
        Exit;
  end;

  ComCtl32DLL := GetModuleHandle(ComCtrl);
  if ComCtl32DLL > 0 then
  begin
    @_FlatSB_ShowScrollBar := GetProcAddress(ComCtl32DLL,
      'FlatSB_ShowScrollBar');
    if Assigned(_FlatSB_ShowScrollBar) then
      _FlatSB_ShowScrollBar(Self.Handle, Code, Show);
  end;
end;

procedure TPlannerGrid.MouseToCell(X, Y: Integer;
  var ACol, ARow: LongInt);
var
  Coord: TGridCoord;
begin
  Coord := MouseCoord(X, Y);
  ACol := Coord.X;
  ARow := Coord.Y;
end;

procedure TPlannerGrid.RepaintRect(R: TRect);
var
  r1, r2, ur: TRect;
begin
  r1 := CellRect(R.Left, R.Top);
  r2 := CellRect(R.Right, R.Bottom);
  UnionRect(ur, r1, r2);

  if IsRectEmpty(r1) or IsRectEmpty(r2) then
    Repaint
  else
    InvalidateRect(Handle, @ur, True);
end;

procedure TPlannerGrid.InvalidateCellRect(R: TRect);
var
  i, j: Integer;
begin
  for i := R.Left to R.Right do
    for j := R.Top to R.Bottom do
      InvalidateCell(i, j);

  if (FPlanner.Sidebar.Orientation = soVertical)
    and FPlanner.Sidebar.Visible and FPlanner.Sidebar.ShowOccupied then
    for i := R.Top to R.Bottom do
    begin
      InvalidateCell(0, i);
    end;

  if (FPlanner.Sidebar.Orientation = soHorizontal)
    and FPlanner.Sidebar.Visible and FPlanner.Sidebar.ShowOccupied then
    for i := R.Left to R.Right do
    begin
      InvalidateCell(i, 0);
    end;
end;


function TPlannerGrid.DoMouseWheelDown(Shift: TShiftState;
  MousePos: TPoint): Boolean;
begin
  if FPlanner.WheelAction = pwaSelect then
  begin
    if (Row < 0) or (Col < 0) or (Row >= RowCount) or (Col >= ColCount)
      then
    begin
      Selection := TGridRect(Rect(FixedCols, FixedRows, FixedCols,
          FixedRows));
      SelChanged;
    end;

    if Row + FPlanner.WheelDelta < RowCount - 1 then
      Row := Row + FPlanner.WheelDelta
    else
      Row := RowCount - 1;

    Result := True;
    CorrectSelection;
    SelChanged;
  end
  else
  begin
    Result := False;
    if TopRow < RowCount - VisibleRowCount then
    begin
      TopRow := TopRow + 1;
      Result := True;
    end;
  end;

end;

function TPlannerGrid.DoMouseWheelUp(Shift: TShiftState;
  MousePos: TPoint): Boolean;
begin
  if FPlanner.WheelAction = pwaSelect then
  begin
    if (Row < 0) or (Col < 0) or (Row >= RowCount) or (Col >= ColCount)
      then
    begin
      Selection := TGridRect(Rect(FixedCols, FixedRows, FixedCols,
          FixedRows));
      SelChanged;
    end;

    if Row - FPlanner.WheelDelta >= FixedRows then
      Row := Row - FPlanner.WheelDelta
    else
      Row := FixedRows;

    Result := True;
    CorrectSelection;
    SelChanged;
  end
  else
  begin
    Result := False;
    if TopRow > FixedRows then
    begin
      Result := True;
      TopRow := TopRow - 1;
    end;
  end;
end;

procedure TPlannerGrid.ChangeSelection(X, Y, dx, dy: Integer);
var
  gr: TGridRect;
begin
  gr := Selection;

  if (dx = 0) then
  begin
    gr.Left := gr.Left + X;
    if gr.Left <= 0 then
    begin
      gr.Left := 1;
      LeftCol := FixedCols;
    end;
    gr.Right := gr.Left;
  end
  else
  begin
    if (FMouseRCD.X = gr.Left) then
    begin
      if (dx < 0) and (gr.Right - gr.Left = 1) then
        gr.Left := gr.Left + dx
      else
      begin
        gr.Right := gr.Right + dx;
        if dx < 0 then
          gr.Right := gr.Right - 1;
      end;
    end
    else
    begin
      if (FMouseRCD.X > gr.Left) then
        gr.Left := gr.Left + dx
      else
        gr.Right := gr.Right + dx;
    end;
  end;

  if gr.Left = 0 then
    gr.Left := 1;

  gr.Top := gr.Top + Y;

  if gr.Top <= TopRow then
    gr.Top := TopRow;
  if gr.Top >= RowCount then
    gr.Top := RowCount - 1;

  gr.Bottom := gr.Bottom + dy;
  if gr.Bottom >= RowCount then
    gr.Bottom := RowCount - 1;

  if not Odd(gr.Left) then
  begin
    if (dx < 0) or (X < 0) then
      gr.Left := gr.Left - 1
    else
      gr.Left := gr.Left + 1;
  end;

  if Odd(gr.Right) then
  begin
    gr.Right := gr.Right + 1;
  end;

  if (gr.Left >= gr.Right) then
  begin
    gr.Right := gr.Left + 1;
  end;

  if (dx = 0) then
    FMouseRCD.X := gr.Left;

  Selection := gr;
end;

procedure TPlannerGrid.CorrectSelection;
var
  GridRect: TGridRect;
  MinSel, MaxSel: Integer;
  Swp: Integer;

begin
  if FPlanner.ContinuousSelect then
    Exit;

  MinSel := 0;
  MaxSel := 0;

  GridRect := Selection;

{$IFDEF TMSDEBUG}
  outputdebugstring(PChar('corr sel:' + IntToStr(FMouseRCD.X) + ':' + IntToStr(GridRect.Left) + '->' + IntToStr(GridRect.Right)));
{$ENDIF}

  if FPlanner.Sidebar.Orientation = soVertical then
  begin
    FPlanner.GetSelMinMax(Selection.Left, MinSel, MaxSel);

    if Selection.Left <> Selection.Right then
    begin
      if Col < GridRect.Right then
        GridRect.Left := GridRect.Right
      else
        GridRect.Right := GridRect.Left;

      Selection := GridRect;
    end;

    if MinSel > 0 then
      if GridRect.Top <= MinSel then
      begin
        GridRect.Top := MinSel;
        if GridRect.Bottom <= MinSel then
          GridRect.Bottom := MinSel;
        Selection := GridRect;
      end;

    if MaxSel > 0 then
      if GridRect.Bottom >= MaxSel then
      begin
        GridRect.Bottom := MaxSel - 1;
        if GridRect.Top >= MaxSel then
          GridRect.Top := MaxSel - 1;
        Selection := GridRect;
      end;
  end
  else
  begin
    FPlanner.GetSelMinMax(Selection.Top, MinSel, MaxSel);

    if Selection.Top <> Selection.Bottom then
    begin
      if Row < GridRect.Bottom then
        GridRect.Top := GridRect.Bottom
      else
        GridRect.Bottom := GridRect.Top;

      Selection := GridRect;
    end;

    if MinSel > 0 then
      if GridRect.Left <= MinSel then
      begin
        GridRect.Left := MinSel;
        if GridRect.Right <= MinSel then
          GridRect.Right := MinSel;
        Selection := GridRect;
      end;

    if MaxSel > 0 then
      if GridRect.Right >= MaxSel then
      begin
        GridRect.Right := MaxSel - 1;
        if GridRect.Left >= MaxSel then
          GridRect.Left := MaxSel - 1;
        Selection := GridRect;
      end;

    if FPlanner.Mode.FullHalfDay and (FMouseRCD.X >= 0) then
    begin
      if (GridRect.Left = GridRect.Right) and
        ((FMouseRCD.X = GridRect.Left) or
          (FMouseRCD.X = GridRect.Left - 1)) then
      begin
        if not Odd(GridRect.Left) then
        begin
          if (GridRect.Left > 1) then
            GridRect.Left := GridRect.Left - 1
          else
            GridRect.Left := 1;
        end;
        GridRect.Right := GridRect.Left + 1;

        FMouseRCD.X := GridRect.Left;
        Selection := GridRect;
      end
      else
      begin
        if (GridRect.Left < FMouseRCD.X) then
        begin
          if Odd(GridRect.Right) then
          begin
            GridRect.Right := GridRect.Right + 1;
          end;

          if not Odd(GridRect.Left) then
          begin

            if (GridRect.Left > 1) then
              GridRect.Left := GridRect.Left - 1
            else
              GridRect.Left := 1;

            Selection := GridRect;
          end;
        end
        else
        begin
          if Odd(GridRect.Right) then
          begin
            if GridRect.Right < FPlanner.Display.DisplayEnd - 1 then
              GridRect.Right := GridRect.Right + 1
            else
              GridRect.Right := GridRect.Right - 1;
          end;

          if (GridRect.Left < ColCount) and
            (GridRect.Bottom < RowCount) then
          begin
            Col := FMouseRCD.X;
            GridRect.Left := FMouseRCD.X;

            Swp := GridRect.Left;
            GridRect.Left := GridRect.Right;
            GridRect.Right := Swp;

            Selection := GridRect;
          end;
        end;
      end;
    end;
  end;
end;

{ TPlannerCaption }

constructor TPlannerCaption.Create(AOwner: TCustomPlanner);
begin
  inherited Create;
  FFont := TFont.Create;
  FFont.Color := clWhite;
  FFont.Size := 10;
  FFont.Style := [];
  FFont.Name := 'Verdana';

  FFont.OnChange := FontChanged;
  FOwner := AOwner;
  FHeight := 32;
  FBackGround := clGray;
  FBackGroundTo := clWhite;
  FBackgroundSteps := 128;
  UpdatePanel;
  FTitle := 'TMS software <b>' + AOwner.ClassName + '</b>';
  FVisible := True;
end;

destructor TPlannerCaption.Destroy;
begin
  FFont.Free;
  inherited Destroy;
end;

procedure TPlannerCaption.UpdatePanel;
begin

  FOwner.FPanel.Font.Assign(FFont);
  FOwner.FPanel.Color := FBackGround;
  FOwner.FPanel.Alignment := FAlignment;
  FOwner.FPanel.Caption := FTitle;
  FOwner.FPanel.Visible := FVisible;

  if FOwner.FPanel.Visible then
    FOwner.FPanel.Height := FHeight
  else
    FOwner.FPanel.Height := 0;

  FOwner.FPanel.Repaint;

  if not Assigned(FOwner.FSidebar) then
    Exit;

  if (FOwner.Sidebar.Orientation = soVertical) then
  begin
    if FOwner.FHeader.Visible then
    begin
      FOwner.FHeader.Top := FOwner.FPanel.Height;
      FOwner.FHeader.Height := FOwner.FPlannerHeader.Height;
    end
    else
    begin
      FOwner.FHeader.Top := FOwner.FPanel.Height;
      FOwner.FHeader.Height := 0;
    end;

    if FOwner.FFooter.Visible then
    begin
      FOwner.FFooter.Top :=
        FOwner.Height - FOwner.FPlannerFooter.Height;
      FOwner.FFooter.Height := FOwner.FPlannerFooter.Height;
    end
    else
    begin
      FOwner.FFooter.Height := 0;
    end;

    if not FOwner.FNavigatorButtons.Visible then
    begin
      FOwner.FPrev.Visible := False;
      FOwner.FNext.Visible := False;
      FOwner.FHeader.Width := FOwner.Width;
      FOwner.FHeader.Left := 0;
    end
    else
    begin
      FOwner.FPrev.Visible := True;
      FOwner.FNext.Visible := True;

      FOwner.FHeader.Left := BtnWidth;
      FOwner.FHeader.Width := FOwner.Width - 2 * BtnWidth - 2;

      FOwner.FFooter.Width := FOwner.Width;

      FOwner.FPrev.Top := FOwner.FPanel.Height;
      FOwner.FPrev.Left := 0;
      FOwner.FPrev.Width := BtnWidth;
      FOwner.FPrev.Height := FOwner.FHeader.Height;

      FOwner.FNext.Top := FOwner.FPanel.Height;
      FOwner.FNext.Left := FOwner.Width - BtnWidth;
      FOwner.FNext.Width := BtnWidth;
      FOwner.FNext.Height := FOwner.FHeader.Height;

      if not FOwner.FHeader.Flat then
      begin
        FOwner.FHeader.Left := FOwner.FHeader.Left + 1;
        FOwner.FHeader.Width := FOwner.FHeader.Width - 1;
      end;
    end;

    FOwner.FGrid.Height := FOwner.Height - FOwner.FPanel.Height -
      FOwner.FHeader.Height - FOwner.FFooter.Height;
    FOwner.FGrid.Top := FOwner.FPanel.Height + FOwner.FHeader.Height;
  end
  else
  begin
    if FOwner.FHeader.Visible then
    begin
      FOwner.FHeader.Top := FOwner.FPanel.Height;
      FOwner.FHeader.Width := FOwner.FPlannerHeader.Height;
      FOwner.FHeader.Height := FOwner.Height - FHeight;
    end
    else
    begin
      FOwner.FHeader.Top := FOwner.FPanel.Height;
      FOwner.FHeader.Width := 0;
    end;

    if FOwner.FFooter.Visible then
    begin
      FOwner.FFooter.Left := FOwner.Width - FOwner.Footer.Height;
      FOwner.FFooter.Top := FOwner.FPanel.Height;
      FOwner.FFooter.Height := FOwner.Height;
      FOwner.FFooter.Width := FOwner.Footer.Height;
    end
    else
    begin
      FOwner.FFooter.Height := 0;
    end;

    FOwner.FGrid.Height := FOwner.Height - FOwner.FPanel.Height;
    FOwner.FGrid.Width := FOwner.Width - FOwner.FHeader.Width -
      FOwner.FFooter.Width;
    FOwner.FGrid.Top := FOwner.FPanel.Height;
    FOwner.FGrid.Left := FOwner.FHeader.Width;

    FOwner.FPrev.Visible := False;
    FOwner.FNext.Visible := False;
  end;

end;

procedure TPlannerCaption.FontChanged(Sender: TObject);
begin
  UpdatePanel;
end;

procedure TPlannerCaption.SetAlignment(const value: TAlignment);
begin
  if Alignment <> value then
  begin
    FAlignment := value;
    UpdatePanel;
  end;
end;

procedure TPlannerCaption.SetBackground(const value: TColor);
begin
  if Background <> value then
  begin
    FBackGround := value;
    UpdatePanel;
  end;
end;

procedure TPlannerCaption.SetFont(const value: TFont);
begin
  FFont.Assign(value);
  FontChanged(Self);
end;

procedure TPlannerCaption.SetHeigth(const value: Integer);
begin
  if FHeight <> value then
  begin
    FHeight := value;
    UpdatePanel;
  end;
end;

procedure TPlannerCaption.SetTitle(const value: string);
begin
  if FTitle <> value then
  begin
    FTitle := value;
    FOwner.FPanel.Caption := FTitle;
    FOwner.FPanel.Repaint;
  end;
end;

procedure TPlannerCaption.SetVisible(const value: Boolean);
begin
  if FVisible <> value then
  begin
    FVisible := value;
    UpdatePanel;
  end;
end;

procedure TPlannerCaption.SetBackgroundTo(const value: TColor);
begin
  if BackgroundTo <> value then
  begin
    FBackGroundTo := value;
    UpdatePanel;
  end;
end;

procedure TPlannerCaption.SetBackgroundSteps(const value: Integer);
begin
  if (BackgroundSteps <> value) then
  begin
    FBackgroundSteps := value;
    UpdatePanel;
  end;
end;

procedure TPlannerCaption.Assign(Source: TPersistent);
begin
  if Assigned(Source) then
  begin
    Title := (Source as TPlannerCaption).Title;
    Font.Assign((Source as TPlannerCaption).Font);
    Alignment := (Source as TPlannerCaption).Alignment;
    Background := (Source as TPlannerCaption).Background;
    BackgroundSteps := (Source as TPlannerCaption).BackgroundSteps;
    BackgroundTo := (Source as TPlannerCaption).BackgroundTo;
    Height := (Source as TPlannerCaption).Height;
    Visible := (Source as TPlannerCaption).Visible;
  end;
end;

procedure TPlannerCaption.SetGradientDirection
  (const value: TPlannerGradientDirection);
begin
  if (value <> FGradientDirection) then
  begin
    FGradientDirection := value;
    UpdatePanel;
  end;
end;

{ TPlannerSideBar }

constructor TPlannerSideBar.Create(AOwner: TCustomPlanner);
begin
  inherited Create;
  FOwner := AOwner;
  FFont := TFont.Create;
  FFont.OnChange := FontChanged;
  FFont.Name := 'Arial'; // choose a truetype font by default
  FBackGround := clBtnFace;
  FBackGroundTo := clWhite;
  FOccupied := clBlue;
  FOccupiedTo := clNone;
  FOccupiedFontColor := clWhite;
  FVisible := True;
  FWidth := 40;
  FLineColor := clGray;
  FColOffset := 1;
  FRowOffset := 0;
  FFlat := True;
  FBorder := True;
  FBorderColor := clGray;
  FRotateOnTop := True;
  FShowDayName := True;
  FSeparatorLineColor := clGray;
  FActiveColor := clNone;
  FActiveColorTo := clNone;
  FTimeIndicator := False;
  FTimeIndicatorColor := clRed;
  FHourFontRatio := 1.8;
  FTimeIndicatorType := tiLine;
  FTimeIndicatorGlyph := TBitmap.Create;
end;

destructor TPlannerSideBar.Destroy;
begin
  FFont.Free;
  FTimeIndicatorGlyph.Free;
  inherited Destroy;
end;

procedure TPlannerSideBar.FontChanged(Sender: TObject);
begin
  FOwner.FGrid.Repaint;
end;

procedure TPlannerSideBar.SetAlignment(const value: TAlignment);
begin
  FAlignment := value;
  FOwner.FGrid.Repaint;
end;

procedure TPlannerSideBar.SetBackground(const value: TColor);
begin
  FBackGround := value;
  FOwner.FGrid.Repaint;
end;

procedure TPlannerSideBar.SetBackgroundTo(const value: TColor);
begin
  FBackGroundTo := value;
  FOwner.FGrid.Repaint;
end;

procedure TPlannerSideBar.SetFont(const value: TFont);
begin
  FFont.Assign(value);
  FOwner.FGrid.Repaint;
end;

procedure TPlannerSideBar.SetVisible(const value: Boolean);
begin
  if (FVisible <> value) then
  begin
    FVisible := value;
    UpdateGrid;
    FOwner.FGrid.UpdatePositions;
    Position := Position;
  end;
end;

procedure TPlannerSideBar.SetWidth(const value: Integer);
begin
  FWidth := value;
  if FVisible then
  begin
    UpdateGrid;
    FOwner.FGrid.UpdatePositions;
  end;
end;

procedure TPlannerSideBar.SetPosition(const value: TSideBarPosition);
begin
  FPosition := value;
  case FPosition of
    spLeft:
      begin
        if Visible then
          FOwner.FHeader.FOffset := 1
        else
          FOwner.FHeader.FOffset := 0;
        FColOffset := 1;
        FRowOffset := 0;
        FOwner.FGrid.ColCount := FOwner.Positions + 1;
        FOwner.FGrid.FixedCols := 1;
        FOwner.FGrid.FixedRows := 0;
        FOwner.FHeader.Orientation := hoHorizontal;
        FOwner.FFooter.Orientation := hoHorizontal;
        FOwner.UpdateCompletion;
      end;
    spLeftRight:
      begin
        if Visible then
          FOwner.FHeader.FOffset := 1
        else
          FOwner.FHeader.FOffset := 0;

        FColOffset := 1;
        FRowOffset := 0;

        if FVisible then
          FOwner.FGrid.ColCount := FOwner.Positions + 2
        else
          FOwner.FGrid.ColCount := FOwner.Positions + 1;

        FOwner.FGrid.FixedCols := 1;
        FOwner.FGrid.FixedRows := 0;
        FOwner.FHeader.Orientation := hoHorizontal;
        FOwner.FFooter.Orientation := hoHorizontal;
        FOwner.UpdateCompletion;
      end;
    spRight:
      begin
        FOwner.FHeader.FOffset := 0;
        FColOffset := 0;
        FRowOffset := 0;
        FOwner.FGrid.ColCount := FOwner.Positions + 1;
        FOwner.FGrid.FixedCols := 0;
        FOwner.FGrid.FixedRows := 0;
        FOwner.FHeader.Orientation := hoHorizontal;
        FOwner.FFooter.Orientation := hoHorizontal;
        FOwner.UpdateCompletion;
      end;
    spTop:
      begin

        FOwner.FGrid.RowCount := FOwner.Positions + 1;

        FColOffset := 0;
        FRowOffset := 1;
        FOwner.FHeader.FOffset := 1;
        FOwner.FGrid.FixedCols := 0;
        FOwner.FGrid.FixedRows := 1;
        FOwner.FHeader.Orientation := hoVertical;
        FOwner.FFooter.Orientation := hoVertical;
        FOwner.UpdateCompletion;
      end;
  end;

  UpdateGrid;
  ActiveColor := ActiveColor;
  FOwner.UpdateSizes;
  FOwner.FGrid.SelChanged;
  FOwner.FGrid.UpdatePositions;
  FOwner.FDisplay.UpdatePlanner;
end;

procedure TPlannerSideBar.UpdateGrid;
begin
  case FPosition of
    spLeft, spRight, spLeftRight:
      if not FVisible then
      begin
        if FColOffset = 1 then
        begin
          FOwner.FGrid.ColWidths[0] := 1;
          FOwner.FGrid.ColWidths[1] :=
            FOwner.Width - 5 - FOwner.FGrid.GetHScrollSize;
        end
        else
        begin
          FOwner.FGrid.ColWidths[1] := 1;
          FOwner.FGrid.ColWidths[0] :=
            FOwner.Width - 5 - FOwner.FGrid.GetHScrollSize;
        end;
      end
      else
      begin
        if FColOffset = 1 then
        begin
          FOwner.FGrid.ColWidths[1] := FOwner.Width - FWidth -
            FOwner.FGrid.GetHScrollSize;
          FOwner.FGrid.ColWidths[0] := FWidth;
        end
        else
        begin
          FOwner.FGrid.ColWidths[0] := FOwner.Width - FWidth -
            FOwner.FGrid.GetHScrollSize;
          FOwner.FGrid.ColWidths[1] := FWidth;
        end;
      end;
    spTop {,spBottom}:

      if not FVisible then
      begin
        if FRowOffset = 1 then
        begin
          FOwner.FGrid.RowHeights[0] := 1;
          FOwner.FGrid.RowHeights[1] :=
            FOwner.Height - 5 - FOwner.FGrid.GetVScrollSize;
        end
        else
        begin
          FOwner.FGrid.RowHeights[1] := 1;
          FOwner.FGrid.RowHeights[0] :=
            FOwner.Height - 5 - FOwner.FGrid.GetVScrollSize;
        end;
      end
      else
      begin
        if FRowOffset = 1 then
        begin
          FOwner.FGrid.RowHeights[0] := FWidth;
        end
        else
        begin
          FOwner.FGrid.RowHeights[0] := FOwner.Height - FWidth -
            FOwner.FGrid.GetVScrollSize;
          FOwner.FGrid.RowHeights[1] := FWidth;
        end;
      end;
  end;

end;

function TPlannerSideBar.GetOrientation: TSideBarOrientation;
begin
  if Position = spTop then
    Result := soHorizontal
  else
    Result := soVertical;
end;

procedure TPlannerSideBar.SetShowInPositionGap(const value: Boolean);
begin
  if FShowInPositionGap <> value then
  begin
    FShowInPositionGap := value;
    if (csDesigning in FOwner.ComponentState) then
      Visible := not value;
    FOwner.FGrid.Invalidate;
  end;
end;

procedure TPlannerSideBar.SetShowOccupied(const value: Boolean);
begin
  if FShowOccupied <> value then
  begin
    FShowOccupied := value;
    FOwner.FGrid.Invalidate;
  end;
end;

procedure TPlannerSideBar.SetFlat(const value: Boolean);
begin
  if FFlat <> value then
  begin
    FFlat := value;
    FOwner.FGrid.Invalidate;
  end;
end;

procedure TPlannerSideBar.SetOccupied(const value: TColor);
begin
  if FOccupied <> value then
  begin
    FOccupied := value;
    FOwner.FGrid.Invalidate;
  end;
end;

procedure TPlannerSideBar.SetOccupiedTo(const value: TColor);
begin
  if FOccupiedTo <> value then
  begin
    FOccupiedTo := value;
    FOwner.FGrid.Invalidate;
  end;
end;

procedure TPlannerSideBar.SetOccupiedFontColor(const value: TColor);
begin
  if FOccupiedFontColor <> value then
  begin
    FOccupiedFontColor := value;
    FOwner.FGrid.Invalidate;
  end;
end;

procedure TPlannerSideBar.SetDateTimeFormat(const value: string);
begin
  if FDateTimeFormat <> value then
  begin
    FDateTimeFormat := value;
    FOwner.FGrid.Invalidate;
  end;
end;

procedure TPlannerSideBar.SetBorderColor(const Value: TColor);
begin
  if FBorderColor <> Value then
  begin
    FBorderColor := Value;
    FOwner.FGrid.Invalidate;
  end;
end;

procedure TPlannerSideBar.SetBorder(const value: Boolean);
begin
  if FBorder <> value then
  begin
    FBorder := value;
    FOwner.FGrid.Invalidate;
  end;
end;

procedure TPlannerSideBar.SetRotateOnTop(const value: Boolean);
begin
  if FRotateOnTop <> value then
  begin
    FRotateOnTop := value;
    FOwner.FGrid.Invalidate;
  end;
end;

procedure TPlannerSideBar.SetShowDayName(const value: Boolean);
begin
  if FShowDayName <> value then
  begin
    FShowDayName := value;
    FOwner.FGrid.Invalidate;
  end;
end;

procedure TPlannerSideBar.SetSeparatorLineColor(const value: TColor);
begin
  if FSeparatorLineColor <> value then
  begin
    FSeparatorLineColor := value;
    FOwner.FGrid.Invalidate;
  end;
end;

procedure TPlannerSideBar.SetAMPMPos(const value: TAMPMPos);
begin
  if FAMPMPos <> value then
  begin
    FAMPMPos := value;
    FOwner.FGrid.Invalidate;
  end;
end;

procedure TPlannerSideBar.SetActiveColor(const value: TColor);
begin
  FActiveColor := value;

  if Position = spTop then
  begin
    if FActiveColor <> clNone then
      FOwner.FGrid.ActiveCellShow := assRow
    else
      FOwner.FGrid.ActiveCellShow := assNone;
  end
  else
  begin
    if FActiveColor <> clNone then
      FOwner.FGrid.ActiveCellShow := assCol
    else
      FOwner.FGrid.ActiveCellShow := assNone;
  end;
end;

procedure TPlannerSideBar.SetActiveColorTo(const value: TColor);
begin
  FActiveColorTo := value;
  FOwner.FGrid.Invalidate;
end;

procedure TPlannerSideBar.Assign(Source: TPersistent);
begin
  if Assigned(Source) then
  begin
    ActiveColor := (Source as TPlannerSideBar).ActiveColor;
    Alignment := (Source as TPlannerSideBar).Alignment;
    AMPMPos := (Source as TPlannerSideBar).AMPMPos;
    Background := (Source as TPlannerSideBar).Background;
    BackgroundTo := (Source as TPlannerSideBar).BackgroundTo;
    Border := (Source as TPlannerSideBar).Border;
    BorderColor := (Source as TPlannerSideBar).BorderColor;
    DateTimeFormat := (Source as TPlannerSideBar).DateTimeFormat;
    Flat := (Source as TPlannerSideBar).Flat;
    Font.Assign((Source as TPlannerSideBar).Font);
    LineColor := (Source as TPlannerSideBar).LineColor;
    Occupied := (Source as TPlannerSideBar).Occupied;
    OccupiedFontColor := (Source as TPlannerSideBar).OccupiedFontColor;
    Position := (Source as TPlannerSideBar).Position;
    RotateOnTop := (Source as TPlannerSideBar).RotateOnTop;
    SeparatorLineColor := (Source as TPlannerSideBar).SeparatorLineColor;
    ShowInPositionGap := (Source as TPlannerSideBar).ShowInPositionGap;
    ShowOccupied := (Source as TPlannerSideBar).ShowOccupied;
    ShowDayName := (Source as TPlannerSideBar).ShowDayName;
    ShowOtherTimeZone := (Source as TPlannerSideBar).ShowOtherTimeZone;
    TimeIndicator := (Source as TPlannerSideBar).TimeIndicator;
    TimeIndicatorColor := (Source as TPlannerSideBar).TimeIndicatorColor;
    TimeZoneMinDelta := (Source as TPlannerSideBar).TimeZoneMinDelta;
    TimeIndicatorType := (Source as TPlannerSideBar).TimeIndicatorType;
    TimeIndicatorGlyph.Assign((Source as TPlannerSideBar).TimeIndicatorGlyph);
    Visible := (Source as TPlannerSideBar).Visible;
    Width := (Source as TPlannerSideBar).Width;
  end;
end;

procedure TPlannerSideBar.SetLineColor(const value: TColor);
begin
  if (FLineColor <> value) then
  begin
    FLineColor := value;
    FOwner.FGrid.Invalidate;
  end;
end;

procedure TPlannerSideBar.SetTimeIndicator(const value: Boolean);
begin
  if (FTimeIndicator <> value) then
  begin
    FTimeIndicator := value;
    FOwner.FGrid.Invalidate;
  end;
end;

procedure TPlannerSideBar.SetTimeIndicatorColor(const value: TColor);
begin
  if (FTimeIndicatorColor <> value) then
  begin
    FTimeIndicatorColor := value;
    FOwner.FGrid.Invalidate;
  end;
end;

procedure TPlannerSideBar.SetTimeIndicatorGlyph(const Value: TBitmap);
begin
  FTimeIndicatorGlyph.Assign(Value);
  FOwner.FGrid.Invalidate;
end;

procedure TPlannerSideBar.SetTimeIndicatorType(const Value: TTimeIndicatorType);
begin
  if (FTimeIndicatorType <> Value) then
  begin
    FTimeIndicatorType := Value;
    FOwner.FGrid.Invalidate;
  end;
end;

procedure TPlannerSideBar.SetHourFontRatio(const value: double);
begin
  if (FHourFontRatio <> value) then
  begin
    FHourFontRatio := value;
    FOwner.FGrid.Invalidate;
  end;
end;

procedure TPlannerSideBar.SetShowOtherTimeZone(const value: Boolean);
begin
  if (FShowOtherTimeZone <> value) then
  begin
    FShowOtherTimeZone := value;
    FOwner.FGrid.Invalidate;
  end;
end;

procedure TPlannerSideBar.SetTimeZoneOffset(const value: Integer);
begin
  if (FTimeZoneOffset <> value) then
  begin
    FTimeZoneOffset := value;
    FOwner.FGrid.Invalidate;
  end;
end;

{ TPlannerDisplay }

constructor TPlannerDisplay.Create(AOwner: TCustomPlanner);
begin
  inherited Create;
  FOwner := AOwner;
  FDisplayStart := 0;
  FDisplayEnd := 47;
  FDisplayScale := 24;
  FOldScale := FDisplayScale;
  FDisplayUnit := 30;
  FDisplayOffset := 0;
  FActiveStart := 16;
  FActiveEnd := 40;
  InitPrecis;
  FColorActive := clWhite;
  FColorNonActive := $00DEDEDE;
  FColorNonSelect := clGray;
  FColorCurrent := clYellow;
  FColorCurrentItem := clLime;
  FCurrentPosFrom := -1;
  FCurrentPosTo := -1;
  FUpdateUnit := False;
  FHourLineColor := clGray;
  FBrushNonSelect := bsFDiagonal;
end;

destructor TPlannerDisplay.Destroy;
begin
  inherited;
end;

procedure TPlannerDisplay.SetDisplayEnd(const value: Integer);
begin
  FDisplayEnd := value;
  FDisplayEndPrecis := (FDisplayEnd + 1) * FDisplayUnit + FDisplayOffset;
  FUpdateUnit := true;
  UpdatePlanner;
  FUpdateUnit := false;
  if ScaleToFit then
    AutoScale;
end;

procedure TPlannerDisplay.SetDisplayStart(const value: Integer);
begin
  FDisplayStart := value;
  FDisplayStartPrecis := (FDisplayStart) * FDisplayUnit + FDisplayOffset;
  FUpdateUnit := True;
  UpdatePlanner;
  FUpdateUnit := False;
  if ScaleToFit then
    AutoScale;
end;

procedure TPlannerDisplay.SetDisplayScale(const value: Integer);
var
  ItemIndex: Integer;
begin
  FDisplayScale := value;
  { Update here all planneritems! }
  for ItemIndex := 0 to FOwner.Items.Count - 1 do
  begin
    (FOwner.Items.Items[ItemIndex] as TPlannerItem).UpdateWnd;
  end;

  UpdatePlanner;
end;

procedure TPlannerDisplay.SetDisplayUnit(const value: Integer);
var
  TopRowPrecis: Integer;
begin
  if csLoading in FOwner.ComponentState then
  begin
    if value <> 0 then
    begin
      FDisplayUnit := value;
      UpdatePlanner;
    end;
    Exit;
  end;

  if FOwner.Sidebar.Position = spTop then
  begin
    if value <> 0 then
      FDisplayUnit := value
    else
      Exit;

    TopRowPrecis := FDisplayUnit * FOwner.FGrid.LeftCol + FDisplayOffset;

    { Rescale everything }
    //FActiveStart := FActiveStartPrecis div FDisplayUnit;
    //FActiveEnd := FActiveEndPrecis div FDisplayUnit;
    FDisplayStart := FDisplayStartPrecis div FDisplayUnit;
    FDisplayEnd := ((FDisplayEndPrecis - FDisplayOffset) div FDisplayUnit) - 1;
    FActiveStart := FActiveStartPrecis div FDisplayUnit - FDisplayStart;
    FActiveEnd := FActiveEndPrecis div FDisplayUnit - FDisplayStart;

    FOwner.FGrid.LeftCol := TopRowPrecis div FDisplayUnit;
  end
  else
  begin
    TopRowPrecis := FDisplayUnit * FOwner.FGrid.TopRow + FDisplayOffset;

    if value <> 0 then
      FDisplayUnit := value
    else
      Exit;

    { Rescale everything }
    //FActiveStart := FActiveStartPrecis div FDisplayUnit;
    //FActiveEnd := FActiveEndPrecis div FDisplayUnit;
    FDisplayStart := FDisplayStartPrecis div FDisplayUnit;
    FDisplayEnd := ((FDisplayEndPrecis - FDisplayOffset) div FDisplayUnit) - 1;
    FActiveStart := FActiveStartPrecis div FDisplayUnit - FDisplayStart;
    FActiveEnd := FActiveEndPrecis div FDisplayUnit - FDisplayStart;

    FOwner.FGrid.TopRow := TopRowPrecis div FDisplayUnit;
  end;

  FUpdateUnit := True;
  UpdatePlanner;
  FUpdateUnit := False;
end;

procedure TPlannerDisplay.SetDisplayOffset(const value: Integer);
begin
  if (Value > FDisplayUnit) then
    Exit;

  if value <> FDisplayOffset then
  begin
    FUpdateUnit := True;
    FDisplayOffset := value;
    UpdatePlanner;
    FUpdateUnit := False;
  end;
end;

procedure TPlannerDisplay.UpdatePlanner;
var
  ItemIndex: Integer;
begin
  if FUpdateCount > 0 then
    Exit;

  with FOwner do
    if not (csLoading in ComponentState) then
    begin
      if not FUpdateUnit then
        for ItemIndex := 0 to Items.Count - 1 do
          (FOwner.Items.Items[ItemIndex] as TPlannerItem).DefOrganize;

      if Sidebar.Orientation = soVertical then
      begin
        if FGrid.RowCount <> 1 + FDisplayEnd - FDisplayStart then
          FGrid.RowCount := 1 + FDisplayEnd - FDisplayStart;
        FGrid.DefaultRowHeight := FDisplayScale;
      end
      else
      begin
        if FGrid.ColCount <> 1 + FDisplayEnd - FDisplayStart then
          FGrid.ColCount := 1 + FDisplayEnd - FDisplayStart;
        FGrid.DefaultColWidth := FDisplayScale;
      end;

      for ItemIndex := 0 to Items.Count - 1 do
        (FOwner.Items.Items[ItemIndex] as TPlannerItem).ReOrganize;

      FOwner.Items.SetConflicts;

      FGrid.Repaint;
    end;
end;

procedure TPlannerDisplay.SetActiveEnd(const value: Integer);
begin
  if (FActiveEnd <> value) then
  begin
    FActiveEnd := value;
    FActiveEndPrecis := (FActiveEnd + FOwner.Display.DisplayStart)
      * FOwner.Display.DisplayUnit + FOwner.Display.DisplayOffset;
    FUpdateUnit := true;
    UpdatePlanner;
    FUpdateUnit := false;
  end;
end;

procedure TPlannerDisplay.SetActiveStart(const value: Integer);
begin
  if (FActiveStart <> Value) then
  begin
    FActiveStart := value;
    FActiveStartPrecis := (FActiveStart + FOwner.Display.DisplayStart)
      * FOwner.Display.DisplayUnit + FOwner.Display.DisplayOffset;
    FUpdateUnit := true;
    UpdatePlanner;
    FUpdateUnit := false;
  end;
end;

procedure TPlannerDisplay.SetBrushNonSelect(const Value: TBrushStyle);
begin
  if (FBrushNonSelect <> Value) then
  begin
    FBrushNonSelect := Value;
    UpdatePlanner;
  end;
end;

procedure TPlannerDisplay.SetColorActive(const value: TColor);
begin
  if (FColorActive <> value) then
  begin
    FColorActive := value;
    UpdatePlanner;
  end;
end;

procedure TPlannerDisplay.SetColorNonActive(const value: TColor);
begin
  if (FColorNonActive <> value) then
  begin
    FColorNonActive := value;
    UpdatePlanner;
  end;
end;

procedure TPlannerDisplay.SetColorNonSelect(const Value: TColor);
begin
  if (FColorNonSelect <> Value) then
  begin
    FColorNonSelect := Value;
    UpdatePlanner;
  end;
end;

procedure TPlannerDisplay.SetColorCurrent(const value: TColor);
begin
  if (FColorCurrent <> value) then
  begin
    FColorCurrent := value;
    UpdatePlanner;
  end;
end;

procedure TPlannerDisplay.SetShowCurrent(const value: Boolean);
begin
  if (FShowCurrent <> value) then
  begin
    FShowCurrent := value;
    UpdatePlanner;
    FOwner.UpdateTimer;
  end;
end;

procedure TPlannerDisplay.SetColorCurrentItem(const value: TColor);
begin
  if (FColorCurrentItem <> value) then
  begin
    FColorCurrentItem := value;
    UpdatePlanner;
  end;
end;

procedure TPlannerDisplay.SetShowCurrentItem(const value: Boolean);
begin
  if (FShowCurrentItem <> value) then
  begin
    FShowCurrentItem := value;
    UpdatePlanner;
    FOwner.UpdateTimer;
    if not value then
      FOwner.Items.SetCurrent(-1);
  end;
end;

procedure TPlannerDisplay.SetScaleToFit(const value: Boolean);
begin
  if FScaleToFit <> value then
  begin
    FScaleToFit := value;

    if FScaleToFit then
    begin
      FOldScale := DisplayScale;
      AutoScale;
    end
    else
      DisplayScale := FOldScale;
  end;
end;

procedure TPlannerDisplay.AutoScale;
var
  R: TRect;
  oldUU: Boolean;
begin
  R := FOwner.FGrid.ClientRect;

  oldUU := FUpdateUnit;
  FUpdateUnit := True;

  if FOwner.Sidebar.Position = spTop then
    DisplayScale := (R.Right - R.Left) div (DisplayEnd - DisplayStart + 1)
  else
    DisplayScale := (R.Bottom - R.Top) div (DisplayEnd - DisplayStart + 1);

  FUpdateUnit := oldUU;
end;

procedure TPlannerDisplay.InitPrecis;
begin
  // initialize precise values properly after load
  FDisplayStartPrecis := FDisplayStart * FDisplayUnit + FDisplayOffset;
  FDisplayEndPrecis := (FDisplayEnd + 1)
    * FDisplayUnit + FDisplayOffset;

  FActiveStartPrecis := (FActiveStart + FDisplayStart)
    * FDisplayUnit + FDisplayOffset;

  FActiveEndPrecis := (FActiveEnd + FDisplayStart)
    * FDisplayUnit + FDisplayOffset;
end;

procedure TPlannerDisplay.BeginUpdate;
begin
  Inc(FUpdateCount);
end;

procedure TPlannerDisplay.EndUpdate;
begin
  if FUpdateCount > 0 then
  begin
    Dec(FUpdateCount);
    if FUpdateCount = 0 then
      UpdatePlanner;
  end;
end;

procedure TPlannerDisplay.SetDisplayText(const value: Integer);
begin
  if (FDisplayText <> value) then
  begin
    FDisplayText := value;
    FUpdateUnit := True;
    UpdatePlanner;
    FUpdateUnit := False;
  end;
end;

procedure TPlannerDisplay.Assign(Source: TPersistent);
begin
  if Assigned(Source) then
  begin
    ActiveStart := (Source as TPlannerDisplay).ActiveStart;
    ActiveEnd := (Source as TPlannerDisplay).ActiveEnd;
    CurrentPosFrom := (Source as TPlannerDisplay).CurrentPosFrom;
    CurrentPosTo := (Source as TPlannerDisplay).CurrentPosTo;
    DisplayStart := (Source as TPlannerDisplay).DisplayStart;
    DisplayEnd := (Source as TPlannerDisplay).DisplayEnd;
    DisplayOffset := (Source as TPlannerDisplay).DisplayOffset;
    DisplayScale := (Source as TPlannerDisplay).DisplayScale;
    DisplayUnit := (Source as TPlannerDisplay).DisplayUnit;
    DisplayText := (Source as TPlannerDisplay).DisplayText;
    ColorActive := (Source as TPlannerDisplay).ColorActive;
    ColorNonActive := (Source as TPlannerDisplay).ColorNonActive;
    ColorNonSelect := (Source as TPlannerDisplay).ColorNonSelect;
    ColorCurrent := (Source as TPlannerDisplay).ColorCurrent;
    ColorCurrentItem := (Source as TPlannerDisplay).ColorCurrentItem;
    ScaleToFit := (Source as TPlannerDisplay).ScaleToFit;
    ShowCurrent := (Source as TPlannerDisplay).ShowCurrent;
    ShowCurrentItem := (Source as TPlannerDisplay).ShowCurrentItem;
    BrushNonSelect := (Source as TPlannerDisplay).BrushNonSelect;
  end;
end;

procedure TPlannerDisplay.SetCurrentPosFrom(const value: Integer);
begin
  if (FCurrentPosFrom <> value) then
  begin
    FCurrentPosFrom := value;
    UpdatePlanner;
  end;
end;

procedure TPlannerDisplay.SetCurrentPosTo(const value: Integer);
begin
  if (FCurrentPosTo <> value) then
  begin
    FCurrentPosTo := value;
    UpdatePlanner;
  end;
end;

procedure TPlannerDisplay.SetHourLineColor(const value: TColor);
begin
  if (FHourLineColor <> value) then
  begin
    FHourLineColor := value;
    FOwner.Invalidate;
  end;
end;

{ TPlannerItem }

constructor TPlannerItem.Create(Collection: TCollection);
begin
  inherited Create(Collection);
  FPlanner := (Collection as TPlannerItems).FOwner;
  FItemBegin := FPlanner.Display.ActiveStart;
  FItemEnd := FItemBegin + 1;
  FItemPos := 0;
  FColor := clWhite;
  FColorTo := clBtnFace;
  FColorDirection := gdVertical;
  FBorderColor := clSilver;
  FTrackColor := clBlue;
  FTrackSelectColor := clBlue;
  FTrackLinkColor := clRed;
  FTrackVisible := True;
  FTrackBrushStyle := bsSolid;
  FText := TStringList.Create;
  FFixedPos := False;
  FFixedSize := False;
  FReadOnly := False;
  FCanSelect := true;
  FImageID := -1;
  FVisible := (csDesigning in FPlanner.ComponentState);
  FImageIndexList := TPlannerIntList.Create(Self);
  FImageIndexList.OnChange := ImageChange;
  FName := 'PlannerItem' + IntToStr(Index);
  FObject := nil;
  FPopupMenu := nil;
  FShape := psRect;
  FConflicts := 0;
  FConflictPos := 0;
  FShadow := True;
  FIsCurrent := False;
  FAllowOverlap := FPlanner.Sidebar.Orientation = soVertical;
  FFont := TFont.Create;
  FFont.Assign(FPlanner.Font);
  FFont.OnChange := FontChange;
  FText.OnChange := TextChange;
  FCaptionFont := TFont.Create;
  FCaptionFont.Assign(FPlanner.Font);
  FCaptionFont.OnChange := FontChange;
  FCaptionBkg := clWhite;
  FCaptionBkgTo := clNone;
  FCaptionAlign := taLeftJustify;
  FCaptionBkgDirection := gdHorizontal;
  FCaptionDivider := true;
  FBrushStyle := bsSolid;
  FSelected := False;
  FSelectColor := clInfoBk;
  FSelectColorTo := clNone;
  FSelectCaptionBkg := clNone;
  FSelectCaptionBkgTo := clNone;
  FSelectFontColor := clRed;
  FShowSelection := True;
  FWordWrap := True;
  FUniformBkg := True;
  FAlarm := TPlannerAlarm.Create;
  FParentIndex := -1;
  FLinkColor := clNavy;
  FLinkType := ltLinkNone;
  FRelationShip := irParent;
  FCursor := crNone;
  FBarItems := TPlannerBarItemList.Create(Self);
  FPopupEdit := False;
  FVisible := True;
  FPreview := False;
  FVMargin := 0;
  FHintIndicator := False;
  FHintIndicatorColor := clRed;
  FHTMLTemplate := TStringList.Create;
  DefOrganize;

  if Assigned(FPlanner.DefaultItem) then
    Self.Assign(FPlanner.DefaultItem);
end;

destructor TPlannerItem.Destroy;
var
  plItems: TPlannerItems;
  i: Integer;
begin
  plItems := (Collection as TPlannerItems);

  if (RelationShip = irParent) and (ParentIndex <> -1) then
  begin
    i := 0;
    while i < plItems.Count do
      if (plItems.Items[i].ParentIndex = ParentIndex) and
        (plItems.Items[i].RelationShip = irChild) then
        plItems.Items[i].Free
      else
        Inc(i);
  end;

  FImageIndexList.Free;
  FHTMLTemplate.Free;
  FAlarm.Free;

  if Assigned(FPlanner.FGrid) then
  begin
    if FPlanner.FGrid.FMemo.Visible then
      FPlanner.FGrid.FMemo.Visible := False;
    if FPlanner.FRichEdit.FPlannerItem = Self then
      FPlanner.FRichEdit.Visible := False;
  end;

  if FOwnsItemObject and Assigned(FObject) then
  begin
    FObject.Free;
    FObject := nil;
  end;

  if Self = plItems.Selected then
  begin
    plItems.SelectNext;

    if not Assigned(plItems.Selected) then
    begin
      plItems.Selected := Self;
      plItems.SelectPrev;
    end;
  end;
  FFont.Free;
  FCaptionFont.Free;
  //FVisible := False;
  FText.Free;
  for i := FBarItems.Count - 1 downto 0 do
    FBarItems[i].Free;
  FBarItems.Free;

  inherited;
  plItems.SetConflicts;
end;

{$IFNDEF VER90}
function TPlannerItem.GetDisplayName: string;
begin
  Result := FName;
end;
{$ENDIF}

procedure TPlannerItem.SetAlignment(const value: TAlignment);
begin
  FAlignment := value;
  Repaint;
end;

procedure TPlannerItem.SetAllowOverlap(const value: Boolean);
begin
  if FAllowOverlap <> value then
  begin
    FAllowOverlap := value;
    Repaint;
    Changed;
  end;
end;

procedure TPlannerItem.SetCaptionType(const value: TCaptionType);
begin
  if (FCaptionType <> value) then
  begin
    FCaptionType := value;
    Repaint;
    Changed;
  end;
end;

procedure TPlannerItem.SetCaptionText(const value: string);
begin
  FCaptionText := value;
  try
    Repaint;
  finally
    Changed;
  end;
end;

procedure TPlannerItem.ImageChange(Sender: TObject);
begin
  Repaint;
  Changed;
end;

procedure TPlannerItem.FontChange(Sender: TObject);
begin
  Repaint;
  Changed;
end;

procedure TPlannerItem.TextChange(Sender: TObject);
begin
  Repaint;
  Changed;
end;

procedure TPlannerItem.SetVisible(const value: Boolean);
begin
  if FVisible <> value then
  begin
    FVisible := value;
    Repaint;
  end;
end;

function TPlannerItem.GetVisible: Boolean;
begin
  Result := FVisible and not FInHeader;
end;

procedure TPlannerItem.ScrollInView;
begin
  with (Collection as TPlannerItems).FOwner do
  begin
    if Sidebar.Position <> spTop then
    begin
      if FGrid.VisibleRowCount < FGrid.RowCount then
        GridTopRow := FItemBegin;

      if (FGrid.VisibleColCount < FGrid.ColCount) and
        (PositionWidth > 0) then
      begin
        if Sidebar.Visible and (Sidebar.Position = spLeft) then
          GridLeftCol := FItemPos + 1
        else
          GridLeftCol := FItemPos
      end
    end
    else
    begin
      if FGrid.VisibleColCount < FGrid.ColCount then
        GridLeftCol := FItemBegin;

      if (FGrid.VisibleRowCount < FGrid.RowCount) and
        (PositionWidth > 0) then
        GridTopRow := Min(FGrid.RowCount - FGrid.VisibleRowCount,
          FItemPos + 1);
    end;
  end;
end;

procedure TPlannerItem.PopupEdit;
var
  PlannerInstance: TCustomPlanner;
begin
  if Assigned(Editor) then
  begin
    PlannerInstance := FPlanner;
    PlannerInstance.FEditMode := True;

    if Assigned(PlannerInstance.OnItemStartEdit) then
      PlannerInstance.OnItemStartEdit(PlannerInstance, Self);

    Editor.Edit(PlannerInstance, Self);

    if Assigned(PlannerInstance.OnItemEndEdit) then
      PlannerInstance.OnItemEndEdit(PlannerInstance, Self);

    PlannerInstance.FEditMode := False;
  end;
end;

procedure TPlannerItem.Edit;
var
  GridRect: TRect;
  ColOffset, RowOffset: Integer;
begin
  if (FPlanner.Sidebar.Orientation = soVertical) then
  begin
    ColOffset := FPlanner.FSidebar.FColOffset;
    GridRect := FPlanner.FGrid.CellRectEx(ItemPos + ColOffset,
      ItemBegin);
    FPlanner.FGrid.StartEditCol(GridRect, Self, -1, -1);
  end
  else
  begin
    RowOffset := FPlanner.FSidebar.FRowOffset;
    GridRect := FPlanner.FGrid.CellRectEx(ItemBegin,
      ItemPos + RowOffset);
    FPlanner.FGrid.StartEditRow(GridRect, Self, -1, -1);
  end;
end;

procedure TPlannerItem.SetFocus(const value: Boolean);
begin
  if (csDestroying in FPlanner.ComponentState) then
    Exit;

  if (FFocus <> value) then
  begin
    if value then
    begin
      if Assigned(FPlanner.FOnItemEnter) then
        FPlanner.FOnItemEnter(FPlanner, Self);
    end
    else
    begin
      if Assigned(FPlanner.FOnItemExit) then
        FPlanner.FOnItemExit(FPlanner, Self);
    end;

    FFocus := value;
    Self.Repaint;
  end;
end;

procedure TPlannerItem.SetFont(const value: TFont);
begin
  FFont.Assign(value);
  Repaint;
  Changed;
end;

procedure TPlannerItem.SetBackground(const value: Boolean);
begin
  if (FBackGround <> value) then
  begin
    FBackGround := value;
    FReadOnly := not FPlanner.AllowBackgroundItemSelection;
    FFixedPos := True;
    FFixedSize := True;
    FAllowOverlap := False;
    Self.Repaint;
    Changed;
  end;
end;

procedure TPlannerItem.SetImageID(const value: Integer);
begin
  if (FImageID <> value) then
  begin
    FImageID := value;
    Repaint;
    Changed;
  end;
end;

procedure TPlannerItem.SetImagePosition(const value: TItemImagePosition);
begin
  if (FImagePosition <> value) then
  begin
    FImagePosition := value;
    Repaint;
    Changed;
  end;
end;

procedure TPlannerItem.SetBorderColor(const Value: TColor);
begin
  if (FBorderColor <> Value) then
  begin
    FBorderColor := Value;
    Repaint;
    Changed;
  end;
end;

procedure TPlannerItem.SetColor(const Value: TColor);
begin
  if (FColor <> Value) then
  begin
    FColor := value;
    Repaint;
    Changed;
  end;
end;

procedure TPlannerItem.SetColorDirection(const Value: TPlannerGradientDirection);
begin
  if (FColorDirection <> Value) then
  begin
    FColorDirection := Value;
    Repaint;
    Changed;
  end;
end;

procedure TPlannerItem.SetColorTo(const value: TColor);
begin
  if (FColorTo <> value) then
  begin
    FColorTo := value;
    Repaint;
    Changed;
  end;
end;

procedure TPlannerItem.SetTrackBrushStyle(const Value: TBrushStyle);
begin
  if (FTrackBrushStyle <> Value) then
  begin
    FTrackBrushStyle := Value;
    Repaint;
  end;
end;

procedure TPlannerItem.SetTrackColor(const value: TColor);
begin
  if (FTrackColor <> value) then
  begin
    FTrackColor := value;
    Repaint;
    Changed;
  end;
end;

procedure TPlannerItem.SetTrackSelectColor(const value: TColor);
begin
  if (FTrackSelectColor <> value) then
  begin
    FTrackSelectColor := value;
    Repaint;
    Changed;
  end;
end;

procedure TPlannerItem.SetLayer(const value: Integer);
begin
  if (FLayer <> Value) then
  begin
    FLayer := value;
    Repaint;
    Changed;
  end;
end;

procedure TPlannerItem.SetItemEnd(const value: Integer);
var
  Difference: Integer;
  OldVisible: Boolean;

begin
  LinkUpdating := True;

  if Assigned(FLinkedItem)
    and not FPlanner.FLinkUpdate and not FLinkedItem.LinkUpdating
    then
  begin
    Difference := value + EndOffset - FItemEnd;

    //    FPlanner.FLinkUpdate := True;

    FPlanner.Items.ResetUpdate;

    case LinkType of
      ltLinkFull, ltLinkEndEnd:
        begin
          if (FLinkedItem.ItemEnd + Difference < 0) or
            (FLinkedItem.ItemEnd + Difference >
              FPlanner.FDisplay.FDisplayEnd -
              FPlanner.Display.FDisplayStart + 1)
            or FPlanner.FLinkCancel then
          begin
            FLinkedItem.FEndOffset :=
              FLinkedItem.ItemEnd + Difference -
              FPlanner.FDisplay.FDisplayEnd - 1;
            FLinkedItem.FItemEnd := FPlanner.FDisplay.FDisplayEnd -
              FPlanner.Display.FDisplayStart + 1;
            FPlanner.FLinkUpdate := False;

            FLinkedItem.FItemEndPrecis :=
              (FLinkedItem.FItemEnd + FLinkedItem.FEndOffset +
                FPlanner.Display.DisplayStart)
              * FPlanner.Display.DisplayUnit +
              FPlanner.Display.DisplayOffset;
          end
          else
          begin
            if (FLinkedItem.LinkedItem = Self) then
              FPlanner.FLinkUpdate := True;

            FLinkedItem.ItemEnd := FLinkedItem.ItemEnd + Difference;
            FLinkedItem.EndOffset := 0;
            FLinkedItem.FItemEndPrecis :=
              (FLinkedItem.FItemEnd + FLinkedItem.FEndOffset +
                FPlanner.Display.DisplayStart)
              * FPlanner.Display.DisplayUnit +
              FPlanner.Display.DisplayOffset;

            if (FLinkedItem.LinkedItem = Self) then
              FPlanner.FLinkUpdate := False;
          end;
        end;
      ltLinkEndBegin:
        begin
          if (FLinkedItem.ItemEnd + Difference < 0) or
            (FLinkedItem.ItemEnd + Difference >
              FPlanner.FDisplay.FDisplayEnd -
              FPlanner.Display.FDisplayStart) or
            (FLinkedItem.ItemBegin + Difference < 0) or
            (FLinkedItem.ItemBegin + Difference >
              FPlanner.FDisplay.FDisplayEnd -
              FPlanner.Display.FDisplayStart + 1)
            or FPlanner.FLinkCancel then
          begin
            FPlanner.FLinkUpdate := False;
            Exit;
          end;

          if FLinkedItem.LinkedItem = Self then
            FPlanner.FLinkUpdate := True;

          FLinkedItem.ItemEnd := FLinkedItem.ItemEnd + Difference;
          FLinkedItem.ItemBegin := FLinkedItem.ItemBegin + Difference;

          if FLinkedItem.LinkedItem = Self then
            FPlanner.FLinkUpdate := False;
        end;
    end;
    //    FPlanner.FLinkUpdate := False;
  end;

  LinkUpdating := False;

  OldVisible := Visible;
  Visible := False;

  FItemEnd := value;

  if not FPlanner.FLoading then
  begin
    FItemEndPrecis := (FItemEnd + FEndOffset + FPlanner.Display.DisplayStart)
      * FPlanner.Display.DisplayUnit + FPlanner.Display.DisplayOffset;
  end;

  Visible := OldVisible;
  (Collection as TPlannerItems).SetConflicts;
end;

procedure TPlannerItem.SetItemBegin(const value: Integer);
var
  Difference: Integer;
begin
  LinkUpdating := True;
  FPlanner.FLinkCancel := False;

  if Assigned(FLinkedItem) and not FPlanner.FLinkUpdate and not FLinkedItem.LinkUpdating then
  begin
    // FPlanner.FLinkUpdate := True;
    FPlanner.Items.ResetUpdate;

    Difference := value - FItemBegin - BeginOffset;

    case LinkType of
      ltLinkFull, ltLinkBeginBegin:
        begin
          if (FLinkedItem.ItemBegin + Difference < 0) or
            (FLinkedItem.ItemBegin + Difference >
              FPlanner.FDisplay.FDisplayEnd -
              FPlanner.FDisplay.FDisplayStart + 1) then
          begin
            FLinkedItem.FBeginOffset := -Difference;
            FLinkedItem.FItemBegin := 0;
            FLinkedItem.ItemBeginPrecis :=
              (FLinkedItem.FItemBegin + FPlanner.Display.DisplayStart)
              * FPlanner.Display.DisplayUnit +
              FPlanner.Display.DisplayOffset;

            FPlanner.FLinkUpdate := False;
            //FPlanner.FLinkCancel := True;
          end
          else
          begin
            if FLinkedItem.LinkedItem = Self then
              FPlanner.FLinkUpdate := True;

            FLinkedItem.ItemBegin := FLinkedItem.ItemBegin + Difference;
            FLinkedItem.FBeginOffset := 0;

            if FLinkedItem.LinkedItem = Self then
              FPlanner.FLinkUpdate := False;
          end;
        end;
      ltLinkBeginEnd:
        begin
          if (FLinkedItem.ItemEnd + Difference < 0) or
            (FLinkedItem.ItemEnd + Difference >
              FPlanner.FDisplay.FDisplayEnd -
              FPlanner.FDisplay.FDisplayStart) or
            (FLinkedItem.ItemBegin + Difference < 0) or
            (FLinkedItem.ItemBegin + Difference >
              FPlanner.FDisplay.FDisplayEnd -
              FPlanner.FDisplay.FDisplayStart + 1) then
          begin
            FPlanner.FLinkUpdate := False;
            FPlanner.FLinkCancel := True;
            Exit;
          end;

          if FLinkedItem.LinkedItem = Self then
            FPlanner.FLinkUpdate := True;

          FLinkedItem.ItemBegin := FLinkedItem.ItemBegin + Difference;
          FLinkedItem.ItemEnd := FLinkedItem.ItemEnd + Difference;

          if FLinkedItem.LinkedItem = Self then
            FPlanner.FLinkUpdate := False;
        end;
    end;
    // FPlanner.FLinkUpdate := False;
  end;

  LinkUpdating := False;

  Visible := False;
  FItemFullBegin := value;

  if (value >= 0) then
    FItemBegin := value
  else
    FItemBegin := 0;

  if not FPlanner.FLoading then
  begin
    FItemBeginPrecis := (FItemBegin + FPlanner.Display.DisplayStart)
      * FPlanner.Display.DisplayUnit + FPlanner.Display.DisplayOffset;
  end;

  Visible := True;
  (Collection as TPlannerItems).SetConflicts;
end;

function TPlannerItem.GetVisibleSpan: Integer;
var
  cb, ce: Integer;
begin
  cb := ItemBegin;
  ce := ItemEnd;
  if FPlanner.Sidebar.Position <> spTop then
  begin
    if cb < FPlanner.FGrid.TopRow then
      cb := FPlanner.FGrid.TopRow;
    if ce > FPlanner.FGrid.VisibleRowCount + FPlanner.FGrid.TopRow then
      ce := FPlanner.FGrid.VisibleRowCount + FPlanner.FGrid.TopRow + 1;
  end
  else
  begin
    if cb < FPlanner.FGrid.LeftCol then
      cb := FPlanner.FGrid.LeftCol;
    if ce >= FPlanner.FGrid.VisibleColCount + FPlanner.FGrid.LeftCol then
      ce := FPlanner.FGrid.VisibleColCount + FPlanner.FGrid.LeftCol;
  end;

  Result := ce - cb;
end;

function TPlannerItem.GetItemRect: TRect;
var
  gr1, gr2: TRect;
begin
  if (FPlanner.Sidebar.Orientation = soVertical) then
  begin
    gr1 := FPlanner.FGrid.CellRectEx(ItemPos + FPlanner.FSidebar.FColOffset, ItemBegin);
    gr2 := FPlanner.FGrid.CellRectEx(ItemPos + FPlanner.FSidebar.FColOffset, ItemEnd - 1);

    CalcConflictRect(gr1, FPlanner.FGrid.ColWidthEx(ItemPos),
      FPlanner.FGrid.RowHeightEx(FPlanner.FSidebar.FRowOffset), True);

    gr1.Bottom := gr2.Bottom;
  end
  else
  begin
    gr1 := FPlanner.FGrid.CellRectEx(ItemBegin, ItemPos + FPlanner.FSidebar.FRowOffset);
    gr2 := FPlanner.FGrid.CellRectEx(ItemEnd - 1, ItemPos + FPlanner.FSidebar.FRowOffset);

    CalcConflictRect(gr1, FPlanner.FGrid.RowHeightEx(ItemPos),
      FPlanner.FGrid.RowHeightEx(FPlanner.FSidebar.FRowOffset), False);

    gr1.Right := gr2.Right;
  end;
  Result := gr1;
end;

function TPlannerItem.GetItemPaintRect: TRect;
var
  R: TRect;
//  delta: integer;
begin
  R := GetItemRect;

  if (FPlanner.Sidebar.Orientation = soVertical) then
  begin
    if (ItemEnd <= FPlanner.GridControl.TopRow) then
      R.Bottom := 0;

    if ItemBegin > FPlanner.GridControl.TopRow + FPlanner.GridControl.VisibleRowCount then
    begin
      R.Bottom := FPlanner.GridControl.ClientRect.Bottom;
      R.Top := FPlanner.GridControl.ClientRect.Bottom;
    end;
  end;

  if (FPlanner.Sidebar.Orientation = soHorizontal) then
  begin
    if ItemEnd <= FPlanner.GridControl.LeftCol then
      R.Right := 0;

    if ItemPos + 1 >= FPlanner.GridControl.TopRow + FPlanner.GridControl.VisibleRowCount then
      R.Top := 0;

    if ItemPos + 1 < FPlanner.GridControl.TopRow then
      R.Top := 0;

    (*
    if FConflicts > 1 then
    begin
      delta := (R.Bottom - R.Top) div FConflicts;
      R.Top := R.Top + FConflictPos * delta;
      R.Bottom := R.Top + delta;
    end;

    if not Background then
    begin
      R.Bottom := R.Bottom - FPlanner.ItemGap;
    end;
    *)
  end;

  Result := R;
end;

function TPlannerItem.GetGridRect: TRect;
var
  nBegin, nEnd: Integer;
begin
  nBegin := Self.ItemBegin;
  nEnd := Self.ItemEnd;

  if FPlanner.Sidebar.Orientation = soVertical then
  begin
    Result := Rect(Self.ItemPos + FPlanner.FSidebar.FColOffset, nBegin,
      Self.ItemPos + FPlanner.FSidebar.FColOffset, nEnd - 1);

  end
  else
  begin
    Result := Rect(nBegin, Self.ItemPos + FPlanner.FSidebar.FRowOffset,
      nEnd - 1, Self.ItemPos + FPlanner.FSidebar.FRowOffset);
  end;
end;

procedure TPlannerItem.Repaint;
var
  ItemPositionIndex: Integer;
  nBegin, nEnd, nPos: Integer;
begin
  if FPlanner.Items.FUpdateCount > 0 then
    Exit;

  { Repaint the complete conflictzone }
  if InHeader then
  begin
    FPlanner.FHeader.Invalidate;
  end
  else
  begin
    FRepainted := False;
    nBegin := Self.ItemBegin;
    nEnd := Self.ItemEnd;
    nPos := Self.ItemPos;
    FPlanner.Items.NumConflicts(nBegin, nEnd, nPos);

    for ItemPositionIndex := nBegin to nEnd - 1 do
    begin
      if FPlanner.Sidebar.Orientation = soVertical then
         FPlanner.FGrid.InvalidateCell(
        Self.ItemPos + FPlanner.FSidebar.FColOffset, ItemPositionIndex)
      else
      FPlanner.FGrid.InvalidateCell(
       ItemPositionIndex, Self.ItemPos + FPlanner.FSidebar.FRowOffset)
    end;

    if (FPlanner.Sidebar.Orientation = soVertical) and FPlanner.Sidebar.Visible and
       FPlanner.Sidebar.ShowOccupied then
      for ItemPositionIndex := nBegin to nEnd do
      begin
        FPlanner.FGrid.InvalidateCell(0, ItemPositionIndex);
      end;

      if (FPlanner.Sidebar.Orientation = soHorizontal) and FPlanner.Sidebar.Visible and
        FPlanner.Sidebar.ShowOccupied then
      for ItemPositionIndex := nBegin to nEnd do
      begin
        FPlanner.FGrid.InvalidateCell(ItemPositionIndex, 0);
      end;
    end;
end;

procedure TPlannerItem.DefOrganize;
begin
  FItemBeginPrecis := (FItemBegin + FPlanner.Display.DisplayStart) * FPlanner.Display.DisplayUnit + FPlanner.Display.DisplayOffset;
  FItemEndPrecis := (FItemEnd + FPlanner.Display.DisplayStart) * FPlanner.Display.DisplayUnit + FPlanner.Display.DisplayOffset;
end;

procedure TPlannerItem.ReOrganize;
var
  d: double;
  delta: integer;
begin
  FItemBegin := ((FItemBeginPrecis - FPlanner.Display.DisplayOffset) div FPlanner.Display.DisplayUnit) - FPlanner.Display.DisplayStart;

  d := (FItemEndPrecis - FPlanner.Display.DisplayOffset) / FPlanner.Display.DisplayUnit;

  if Frac(d) > 0 then
    FItemEnd := 1 + ((FItemEndPrecis - FPlanner.Display.DisplayOffset) div FPlanner.Display.DisplayUnit)  - FPlanner.Display.DisplayStart - FEndOffset
  else
    FItemEnd := ((FItemEndPrecis - FPlanner.Display.DisplayOffset) div FPlanner.Display.DisplayUnit) - FPlanner.Display.DisplayStart - FEndOffset;

  delta := FItemEnd - (FPlanner.Display.DisplayEnd - FPlanner.Display.DisplayStart);

  if (delta > 0) then
  begin
    FItemEnd := FItemEnd - (delta - 1);
    FEndOffset := FEndOffset + (delta - 1);
  end
  else
  begin
    while (FEndOffset > 0) and (delta <= 0) do
    begin
      inc(FItemEnd);
      dec(FEndOffset);
      inc(delta);
    end;
  end;

  (*
  if FPlanner.IsDBAware then
  begin
    if FItemEnd > FPlanner.Display.DisplayEnd - FPlanner.Display.DisplayStart + 1  then
    begin
      FItemEnd := FPlanner.Display.DisplayEnd - FPlanner.Display.DisplayStart + 1;
    end;

    if FItemBegin < FPlanner.Display.DisplayStart then
    begin
      FItemBegin := FPlanner.Display.DisplayStart;
    end;
  end;
  *)

  UpdateWnd;
end;

procedure TPlannerItem.SetText(const value: TStringList);
begin
  if Assigned(value) then
    FText.Assign(value);
  Repaint;
end;

procedure TPlannerItem.UpdateWnd;
begin
  Self.Repaint;
end;

procedure TPlannerItem.CalcConflictRect(var Rect: TRect; Width, Height: Integer; Position: Boolean);
begin
  if FConflicts > 1 then
  begin
    if Position then
    begin
      Width :=  Width div FConflicts;
      Rect.Left := Rect.Left + Width * FConflictPos;
      Rect.Right := Rect.Left + Width - FPlanner.ItemGap;
    end
    else
    begin
      Height := Height div FConflicts;
      Rect.Top := Rect.Top + Height * FConflictPos + VMargin;
      Rect.Bottom := Rect.Top + Height - FPlanner.ItemGap - VMargin;
    end;
  end
  else
  begin
    if Position then
      Rect.Right := Rect.Right - FPlanner.ItemGap
    else
    begin
      Rect.Bottom := Rect.Bottom - FPlanner.ItemGap - VMargin;
      Rect.Top := Rect.Top + VMargin;
    end;
  end;

end;

procedure TPlannerItem.SetItemPos(const value: Integer);
var
  Difference: Integer;
begin
  LinkUpdating := True;

  if FItemPos <> value then
  begin
    if Assigned(FLinkedItem) and not FPlanner.FLinkUpdate and not FLinkedItem.LinkUpdating and (FLinkType <> ltLinkNone) then
    begin
      //FPlanner.FLinkUpdate := True;
      FPlanner.Items.ResetUpdate;
      Difference := value - FItemPos;
      FLinkedItem.ItemPos := FLinkedItem.ItemPos + Difference;
      //FPlanner.FLinkUpdate := False;
    end;

    Visible := False;
    Repaint;

    FItemPos := value;
    Visible := True;
    FPlanner.Items.SetConflicts;
    Repaint;
  end;
  LinkUpdating := False;
end;

procedure TPlannerItem.Assign(Source: TPersistent);
begin
  if Source is TPlannerItem then
  begin
    ItemPos := TPlannerItem(Source).ItemPos;
    ItemBegin := TPlannerItem(Source).ItemBegin;
    ItemEnd := TPlannerItem(Source).ItemEnd;
    Color := TPlannerItem(Source).Color;
    ColorTo := TPlannerItem(Source).ColorTo;
    ColorDirection := TPlannerItem(Source).ColorDirection;
    BorderColor := TPlannerItem(Source).BorderColor;
    CanSelect := TPlannerItem(Source).CanSelect;
    Completion := TPlannerItem(Source).Completion;
    CompletionDisplay := TPlannerItem(Source).CompletionDisplay;
    Cursor := TPlannerItem(Source).Cursor;
    Text.Text := TPlannerItem(Source).Text.Text;
    ReadOnly := TPlannerItem(Source).ReadOnly;
    FixedSize := TPlannerItem(Source).FixedSize;
    FixedPos := TPlannerItem(Source).FixedPos;
    FixedPosition := TPlannerItem(Source).FixedPosition;
    FixedTime := TPlannerItem(Source).FixedTime;
    CaptionType := TPlannerItem(Source).CaptionType;
    ImageID := TPlannerItem(Source).ImageID;
    ImagePosition := TPlannerItem(Source).ImagePosition;
    Alignment := TPlannerItem(Source).Alignment;
    Name := TPlannerItem(Source).Name;
    Visible := TPlannerItem(Source).Visible;
    Tag := TPlannerItem(Source).Tag;
    TrackColor := TPlannerItem(Source).TrackColor;
    TrackLinkColor := TPlannerItem(Source).TrackLinkColor;
    TrackSelectColor := TPlannerItem(Source).TrackSelectColor;
    TrackVisible := TPlannerItem(Source).TrackVisible;
    TrackBrushStyle := TPlannerItem(Source).TrackBrushStyle;
    CaptionText := TPlannerItem(Source).CaptionText;
    EditMask := TPlannerItem(Source).EditMask;
    InplaceEdit := TPlannerItem(Source).InplaceEdit;
    Layer := TPlannerItem(Source).Layer;
    Font.Assign(TPlannerItem(Source).Font);
    Background := TPlannerItem(Source).Background;
    AllowOverlap := TPlannerItem(Source).AllowOverlap;
    Selected := TPlannerItem(Source).Selected;
    SelectColor := TPlannerItem(Source).SelectColor;
    SelectColorTo := TPlannerItem(Source).SelectColorTo;
    SelectCaptionBkg := TPlannerItem(Source).SelectCaptionBkg;
    SelectCaptionBkgTo := TPlannerItem(Source).SelectCaptionBkgTo;
    FCaptionBkg := TPlannerItem(Source).CaptionBkg;
    FCaptionBkgTo := TPlannerItem(Source).CaptionBkgTo;
    FCaptionBkgDirection := TPlannerItem(Source).CaptionBkgDirection;
    FCaptionAlign := TPlannerItem(Source).CaptionAlign;
    FCaptionFont.Assign(TPlannerItem(Source).CaptionFont);
    FCaptionType := TPlannerItem(Source).CaptionType;
    FCaptionDivider := TPlannerItem(Source).CaptionDivider;
    BrushStyle := TPlannerItem(Source).BrushStyle;
    InHeader := TPlannerItem(Source).InHeader;
    OwnsItemObject := TPlannerItem(Source).OwnsItemObject;
    ItemObject := TPlannerItem(Source).ItemObject;
    ShowDeleteButton := TPlannerItem(Source).ShowDeleteButton;
    Selected := TPlannerItem(Source).Selected;
    SelectColor := TPlannerItem(Source).SelectColor;
    SelectFontColor := TPlannerItem(Source).SelectFontColor;
    Shape := TPlannerItem(Source).Shape;
    PopupMenu := TPlannerItem(Source).PopupMenu;
    ShowSelection := TPlannerItem(Source).ShowSelection;
    DBTag := TPlannerItem(Source).DBTag;
    WordWrap := TPlannerItem(Source).WordWrap;
    Attachement := TPlannerItem(Source).Attachement;
    URL := TPlannerItem(Source).URL;
    UniformBkg := TPlannerItem(Source).UniformBkg;
    Alarm.Assign(TPlannerItem(Source).Alarm);
    Shadow := TPlannerItem(Source).Shadow;
    Editor := TPlannerItem(Source).Editor;
    DrawTool := TPlannerItem(Source).DrawTool;
    DrawTag := TPlannerItem(Source).DrawTag;
    Hint := TPlannerItem(Source).Hint;
    HintIndicator := TPlannerItem(Source).HintIndicator;
    HintIndicatorColor := TPlannerItem(Source).HintIndicatorColor;
    LinkColor := TPlannerItem(Source).LinkColor;
    HTMLTemplate := TPlannerItem(Source).HTMLTemplate;
    ShowLinks := TPlannerItem(Source).ShowLinks;
    FLinkArrow := TPlannerItem(Source).LinkArrow;
    Recurrency := TPlannerItem(Source).Recurrency;
    Recurrent := TPlannerItem(Source).Recurrent;
    RecurrentOrigStart := TPlannerItem(Source).RecurrentOrigStart;
    RecurrentOrigEnd := TPlannerItem(Source).RecurrentOrigEnd;
    VMargin := TPlannerItem(Source).VMargin;
    WideCaption := TPlannerItem(Source).WideCaption;
    WideText := TPlannerItem(Source).WideText;
    Unicode := TPlannerItem(Source).Unicode;
  end;
end;

procedure TPlannerItem.AssignEx(Source: TPersistent);
begin
  if Source is TPlannerItem then
  begin
    CanSelect := TPlannerItem(Source).CanSelect;
    Color := TPlannerItem(Source).Color;
    ColorTo := TPlannerItem(Source).ColorTo;
    ColorDirection := TPlannerItem(Source).ColorDirection;
    BorderColor := TPlannerItem(Source).BorderColor;
    Cursor := TPlannerItem(Source).Cursor;
    Text.Text := TPlannerItem(Source).Text.Text;
    ReadOnly := TPlannerItem(Source).ReadOnly;
    FixedSize := TPlannerItem(Source).FixedSize;
    FixedPos := TPlannerItem(Source).FixedPos;
    FixedPosition := TPlannerItem(Source).FixedPosition;
    FixedTime := TPlannerItem(Source).FixedTime;
    CaptionType := TPlannerItem(Source).CaptionType;
    ImageID := TPlannerItem(Source).ImageID;
    Alignment := TPlannerItem(Source).Alignment;
    Name := TPlannerItem(Source).Name;
    Visible := TPlannerItem(Source).Visible;
    Tag := TPlannerItem(Source).Tag;
    TrackColor := TPlannerItem(Source).TrackColor;
    TrackLinkColor := TPlannerItem(Source).TrackLinkColor;
    TrackSelectColor := TPlannerItem(Source).TrackSelectColor;
    TrackVisible := TPlannerItem(Source).TrackVisible;
    TrackBrushStyle := TPlannerItem(Source).TrackBrushStyle;
    CaptionText := TPlannerItem(Source).CaptionText;
    EditMask := TPlannerItem(Source).EditMask;
    InplaceEdit := TPlannerItem(Source).InplaceEdit;
    Layer := TPlannerItem(Source).Layer;
    LinkColor := TPlannerItem(Source).LinkColor;
    Font.Assign(TPlannerItem(Source).Font);
    Background := TPlannerItem(Source).Background;
    AllowOverlap := TPlannerItem(Source).AllowOverlap;
    ShowDeleteButton := TPlannerItem(Source).ShowDeleteButton;
    Selected := TPlannerItem(Source).Selected;
    SelectColor := TPlannerItem(Source).SelectColor;
    SelectColorTo := TPlannerItem(Source).SelectColorTo;
    SelectCaptionBkg := TPlannerItem(Source).SelectCaptionBkg;
    SelectCaptionBkgTo := TPlannerItem(Source).SelectCaptionBkgTo;
    CaptionBkg := TPlannerItem(Source).CaptionBkg;
    CaptionBkgTo := TPlannerItem(Source).CaptionBkgTo;
    CaptionBkgDirection := TPlannerItem(Source).CaptionBkgDirection;
    CaptionAlign := TPlannerItem(Source).CaptionAlign;
    CaptionFont.Assign(TPlannerItem(Source).CaptionFont);
    CaptionType := TPlannerItem(Source).CaptionType;
    BrushStyle := TPlannerItem(Source).BrushStyle;
    InHeader := TPlannerItem(Source).InHeader;
    OwnsItemObject := TPlannerItem(Source).OwnsItemObject;
    ItemObject := TPlannerItem(Source).ItemObject;
    Selected := TPlannerItem(Source).Selected;
    SelectColor := TPlannerItem(Source).SelectColor;
    Shape := TPlannerItem(Source).Shape;
    PopupMenu := TPlannerItem(Source).PopupMenu;
    ShowSelection := TPlannerItem(Source).ShowSelection;
    DBTag := TPlannerItem(Source).DBTag;
    WordWrap := TPlannerItem(Source).WordWrap;
    Attachement := TPlannerItem(Source).Attachement;
    URL := TPlannerItem(Source).URL;
    UniformBkg := TPlannerItem(Source).UniformBkg;
    ShowLinks := TPlannerItem(Source).ShowLinks;
    Alarm.Assign(TPlannerItem(Source).Alarm);
    DrawTool := TPlannerItem(Source).DrawTool;
    DrawTag := TPlannerItem(Source).DrawTag;
    Editor := TPlannerItem(Source).Editor;
    Hint := TPlannerItem(Source).Hint;
    HintIndicator := TPlannerItem(Source).HintIndicator;
    HintIndicatorColor := TPlannerItem(Source).HintIndicatorColor;
    VMargin := TPlannerItem(Source).VMargin;
    WideCaption := TPlannerItem(Source).WideCaption;
    WideText := TPlannerItem(Source).WideText;
    Unicode := TPlannerItem(Source).Unicode;
  end;
end;

procedure TPlannerItem.SetItemEndTime(const Value: TDateTime);
var
  Hour, Minute, Second, Second100: Word;
  da, mo, ye: Word; dte, dts: TDateTime;
  nv, delta, res, MinutePrecis: Integer;
  usert: boolean;
  withinvu: boolean;
begin
  FItemEndTime := Value;

  with TPlannerItems(Collection).FOwner do
  begin
    case Mode.PlannerType of
    plDay:
      begin
        delta := 0;
        EndOffset := 0;

        usert := (Int(FPlanner.Mode.Date) <> 0) and (Int(Value) <> 0) and not IsDBAware;

        if usert then
        begin
          if Int(Value) > Int(FPlanner.Mode.Date) + FItemPos then
            delta := 24 * 60;
        end
        else
        // if FItemRealStartTime <> 0 then
        begin
          BeginOffset := 0;

          if int(Value) > int(FItemRealStartTime) then
            delta := 24 * 60;

          if int(value) < int(FItemRealStartTime) then
            delta := -24 * 60;
        end;

        DecodeTime(Value, Hour, Minute, Second, Second100);

        Minute := Minute + (Hour * 60) - FDisplay.DisplayOffset;

        // start 1.6.0.2 fix to display items on day crossing views
        //if (Minute div Display.DisplayUnit < Display.DisplayStart) and (Display.DisplayStart > 0) then
        //  Minute := Minute + 1440;
        // end 1.6.0.2 fix to display items on day crossing views

        Minute := Minute + delta;

        FItemEndPrecis := Minute; // moved after delta

        if FItemEndPrecis < FItemBeginPrecis then
        begin
          FItemEndPrecis := FItemEndPrecis + 60 * 24;
          Minute := Minute + 60 * 24;
        end;

        if Minute > Display.FDisplayEndPrecis then
        begin
          if FRoundTime then
            EndOffset := Round((Minute - Display.FDisplayEndPrecis) / Display.DisplayUnit)
          else
            EndOffset := (Minute - Display.FDisplayEndPrecis) div Display.DisplayUnit;

          ItemEnd := Display.DisplayEnd - Display.DisplayStart + 1;
        end
        else
          if FItemBeginPrecis < Display.FDisplayStartPrecis then
          begin
           // hide item if falling outside displayed timespan
           if (Minute < Display.FDisplayStartPrecis) then
           begin
             //ItemBegin := 0;
             //ItemEnd := 0;
             InHeader := True;
           end
           else
           begin
          {
           if FRoundTime then
           BeginOffset := Round((Display.FDisplayStartPrecis - (Minute - Display.DisplayStart * Display.DisplayUnit)) /
           Display.DisplayUnit)
           else
           BeginOffset := (Display.FDisplayStartPrecis - (Minute - Display.DisplayStart * Display.DisplayUnit)) div
           Display.DisplayUnit;
           }
            if FRoundTime then
              BeginOffset := Round((Display.FDisplayStartPrecis - FItemBeginPrecis) / Display.DisplayUnit)
            else
              BeginOffset := (Display.FDisplayStartPrecis - FItemBeginPrecis) div Display.DisplayUnit;

            ItemBegin := 0;

            if FRoundTime then
              ItemEnd := Round(Minute / Display.DisplayUnit) - Display.DisplayStart
            else
            begin
              //if (FItemEndPrecis mod Display.DisplayUnit = 0) then // avoid issue with item with timespan < 60sec
              //  ItemEnd := ((Minute) div Display.DisplayUnit) + 1 - Display.DisplayStart
              //else
              ItemEnd := ((Minute - 1) div Display.DisplayUnit) + 1 - Display.DisplayStart;
            end;
          end;
        end
        else
        begin
          if FRoundTime then
            ItemEnd := Round(Minute / Display.DisplayUnit) - Display.DisplayStart
          else
          begin
            //if (FItemEndPrecis mod Display.DisplayUnit = 0) then // avoid issue with item with timespan < 60sec
            //  ItemEnd := ((Minute) div Display.DisplayUnit) + 1 - Display.DisplayStart
            //else
            ItemEnd := ((Minute - 1) div Display.DisplayUnit) + 1 - Display.DisplayStart;
          end;
        end;

        if FRoundTime then
          if ItemEnd = ItemBegin then
            ItemEnd := ItemEnd + 1;

        // removed in 1.6.0.2
        FItemEndPrecis := Minute; // moved after delta
{$IFDEF TMSDEBUG}
        outputdebugstring(PChar(FormatDateTime('hh:nn dd/mm/yyyy', value)));
{$ENDIF}
        FItemRealEndTime := value;
      end;

    plTimeLine:
      begin
        DecodeTime(value, Hour, Minute, Second, Second100);
        Minute := Minute + Hour * 60;
        FItemEndPrecis := Minute;

        delta := Minute mod Display.DisplayUnit;

        // start 1.6.0.2 fix to display items on day crossing views
        // if ((Minute div Display.DisplayUnit) - Display.DisplayStart) < 0 then
        //  Minute := Minute + 1440;
        // end 1.6.0.2 fix to display items on day crossing views

        //DInc := Round(Int(Value) - Int(Mode.TimeLineStart)) * (MININDAY div Display.DisplayUnit);

        MinutePrecis := Minute;

        Minute := (Minute div Display.DisplayUnit) - Display.DisplayStart;

        res := AbsTimeToCell(value);

        if (res > Display.DisplayEnd + 1) then
        begin
          EndOffset := res - Display.DisplayEnd - 1;
          ItemEnd := Display.DisplayEnd + 1;
        end
        else
        begin
          ItemEnd := res;

          withinvu := true;

          if (Mode.TimeLineNVUEnd <> 0) or (Mode.TimeLineNVUBegin <> 0) then
          begin
            if MinutePrecis > 1440 - Mode.TimeLineNVUEnd * Display.DisplayUnit then
              withinvu := false;

            if MinutePrecis < Mode.TimeLineNVUBegin * Display.DisplayUnit then
              withinvu := false;
          end;

          if (delta > 0) and withinvu then
            ItemEnd := res + 1;

          EndOffset := 0;
        end;

        {
        if Minute + DInc > Display.FDisplayEnd then
        begin
          EndOffset := Minute + DInc - Display.DisplayEnd - 1;
          ItemEnd := Display.DisplayEnd - Display.DisplayStart + 1;
        end
        else
          ItemEnd := Minute + DInc;
        }
        FItemRealEndTime := value;
      end;

    plDayPeriod, plMonth, plWeek:
      begin
        dte := FPlanner.Mode.PeriodEndDate;
        dts := FPlanner.Mode.PeriodStartDate;
        FItemRealEndTime := value;
        EndOffset := 0;

        if Trunc(value) > dte then
          EndOffset := Trunc(value - dte);

        nv := Trunc(value - FPlanner.Mode.PeriodStartDate) + 1;

        // Clip(nv, FPlanner.Display.DisplayStart, FPlanner.Display.DisplayEnd - FPlanner.Display.DisplayStart);

        if (nv < 0) then // Because of the 0 we can't use the Clip function
          nv := FPlanner.Display.DisplayStart;

        if (nv > FPlanner.Display.DisplayEnd - FPlanner.Display.DisplayStart) then
          nv := FPlanner.Display.DisplayEnd - FPlanner.Display.DisplayStart + 1;

        if value < dts then
        begin
          Self.Visible := False;
        end
        else
          ItemEnd := nv;
        {$IFDEF TMSDEBUG}
        outputdebugstring(PChar(FormatDateTime('et : hh:nn dd/mm/yyyy', value)));
        {$ENDIF}
        FItemRealEndTime := value;
      end;

    plActiveDayPeriod:
      begin
        dte := FPlanner.Mode.PeriodEndDate;
        dts := FPlanner.Mode.PeriodStartDate;

        if Trunc(value) > dte then
          EndOffset := FPlanner.DiffActiveDays(value,dte);

        nv := FPlanner.DiffActiveDays(value, FPlanner.Mode.PeriodStartDate) + 1;

        if (nv < 0) then // Because of the 0 we can't use the Clip function
          nv := FPlanner.Display.DisplayStart;

        if (nv > FPlanner.Display.DisplayEnd - FPlanner.Display.DisplayStart) then
          nv := FPlanner.Display.DisplayEnd - FPlanner.Display.DisplayStart + 1;

        if value < dts then
        begin
          Self.Visible := False;
        end
        else
          ItemEnd := nv;

        FItemRealEndTime := value;
      end;

    plHalfDayPeriod:
      begin
        dte := FPlanner.Mode.PeriodEndDate + 1;
        EndOffset := 0;
        nv := Trunc(2 * (value - FPlanner.Mode.PeriodStartDate));

        //if (Frac(Value) >= 0) and (Frac(Value) <> 0.5) then
        //  inc(nv,2);

        if ((Frac(value) > 0) and (Frac(value) <> 0.5)) or (nv = ItemBegin) then
          Inc(nv, 1);

        if (nv < 0) then // Because of the 0 we can't use the Clip function
          nv := FPlanner.Display.DisplayStart;

        if nv > FPlanner.Display.DisplayEnd - FPlanner.Display.DisplayStart then
          nv := FPlanner.Display.DisplayEnd - FPlanner.Display.DisplayStart + 1;

        ItemEnd := nv;

        if value > int(dte) then
          EndOffset := Round(2 * (value - dte));

        FItemRealEndTime := value;
      end;

    plMultiMonth:
      begin
        DecoDedate(value, ye, mo, da);

        while (FPlanner.Mode.Year < ye) do
        begin
          mo := mo + 12;
          Dec(ye);
        end;

        ItemPos := Limit(mo - FPlanner.Mode.Month, 0, Positions - 1);

        if (mo > FPlanner.Mode.Month + Positions - 1) then
          ItemEnd := PlanUtil.DaysInMonth(ye, FPlanner.Mode.Month + Positions - 1)
        else
          ItemEnd := da;
      end;

    plCustom, plCustomList:
      begin
        ItemEnd := FPlanner.TimeToIndex(value);
        if ItemEnd = ItemBegin then
          ItemEnd := ItemEnd + 1;
      end;
    end;
  end;
end;

procedure TPlannerItem.SetItemStartTime(const value: TDateTime);
var
  Hour, Minute, Second, Second100: Word;
  da, mo, ye: Word;
  dts, dte: TDateTime;
  res, di, dn: Integer;
  usert: boolean;

begin
  FItemStartTime := value;
  with TPlannerItems(Collection).FOwner do
  begin
    case Mode.PlannerType of
    plDay:
      begin
        usert := (Int(FPlanner.Mode.Date) <> 0) and (Int(Value) <> 0) and not IsDBAware;

        DecodeTime(Value, Hour, Minute, Second, Second100);
        Minute := Minute + (Hour * 60) - FDisplay.DisplayOffset;

        // start 1.6.0.2 fix to display items on day crossing views
        if (((Minute div Display.DisplayUnit) - Display.DisplayStart) < 0) and (Display.DisplayStart > 0) and
          (Display.DisplayEnd * Display.DisplayUnit > 1440) and (Int(Value) = 0) then
          Minute := Minute + 1440;
        // end 1.6.0.2 fix to display items on day crossing views

        if usert and (Int(Value) <= Int(FPlanner.Mode.Date) - 1) then
        begin
          ItemBegin := 0;
          di := Minute - 1440;
          Minute := 0;
          BeginOffset := -Round(di / Display.DisplayUnit) - Display.DisplayStart;
        end
        else
        begin
          if FRoundTime then
            ItemBegin := Round(Minute / Display.DisplayUnit) - Display.DisplayStart
          else
            ItemBegin := (Minute div Display.DisplayUnit) - Display.DisplayStart;
        end;

        FItemBeginPrecis := Minute;
        FItemRealStartTime := Value;

        if not FPlanner.IsDBAware then
        begin
          di := Trunc(Int(EncodeDate(FPlanner.Mode.Year, FPlanner.Mode.Month, FPlanner.Mode.Day)));
          dn := Trunc(Int(value));
          if (dn > 0) then
            FItemPos := dn - di;
        end;
      end;

    plTimeLine:
      begin
        DecodeTime(value, Hour, Minute, Second, Second100);
        Minute := Minute + Hour * 60;

        FItemBeginPrecis := Minute;
        Minute := (Minute div Display.DisplayUnit) - Display.DisplayStart;

        res := AbsTimeToCell(value);

        if res < 0 then
        begin
          ItemBegin := 0; BeginOffset := -res;
        end
        else
        begin
          ItemBegin := res;
          BeginOffset := 0;
        end;

        FItemRealStartTime := value;
      end;

    plDayPeriod, plMonth, plWeek:
      begin
        dts := FPlanner.Mode.PeriodStartDate;
        dte := FPlanner.Mode.PeriodEndDate;

        BeginOffset := 0;

        if (Trunc(value) > dts) and (Trunc(value) <= dte) then
          ItemBegin := Trunc(value - dts)
        else
        begin
          BeginOffset := Trunc(dts - Trunc(value));
          ItemBegin := 0;
          if Trunc(value) > dte then
            Self.Visible := False;
        end;
        FItemRealStartTime := value;
      end;

    plActiveDayPeriod:
      begin
        dts := FPlanner.Mode.PeriodStartDate;
        dte := FPlanner.Mode.PeriodEndDate;

        BeginOffset := 0;

        if (Trunc(value) > dts) and (Trunc(value) <= dte) then
          ItemBegin := FPlanner.DiffActiveDays(dts, value)
        else
        begin
          BeginOffset :=  FPlanner.DiffActiveDays(dts, value);
          ItemBegin := 0;
          if Trunc(value) > dte then
            Self.Visible := False;
        end;

        FItemRealStartTime := value;
      end;

    plHalfDayPeriod:
      begin
        dts := FPlanner.Mode.PeriodStartDate;
        dte := FPlanner.Mode.PeriodEndDate;

        BeginOffset := 0;
        if (value >= dts) and (value < int(dte) + 1) then
        begin
          ItemBegin := Trunc(2 * (value - dts))
        end
        else
        begin
          BeginOffset := Round(2 * (dts - value));
          ItemBegin := 0;
        end;
        FItemRealStartTime := value;
      end;

    plMultiMonth:
      begin
        DecoDedate(value, ye, mo, da);
        while (FPlanner.Mode.Year < ye) do
        begin
          mo := mo + 12;
          Dec(ye);
        end;

        ItemPos := Limit(mo - FPlanner.Mode.Month, 0, Positions - 1);
        ItemBegin := da - 1;
      end;

    plCustom, plCustomList:
      begin
        ItemBegin := TimeToIndex(value);
      end;
    end;
  end;
end;

function TPlannerItem.GetItemEndTime: TDateTime;
var
  res, ID: Integer;
  //DInc: Integer;
  da, mo, ye: Word; DT: TDateTime;
begin
  with TPlannerItems(Collection).FOwner do
  begin
    Result := 0;
    case Mode.PlannerType of
    plDay:
      begin
        res := FItemEndPrecis;
        ID := 0;
        while (res >= MININDAY) do
        begin
          res := res - MININDAY;
          Inc(ID);
        end;
        Result := EncodeTime(res div 60, res mod 60, 0, 0);

        {
        if EndOffset > 0 then
        begin
          res := EndOffset * Display.DisplayUnit;
          Result := Result + EncodeTime(res div 60,res mod 60,0 ,0);
        end;
        }

        Result := Result + PosToDay(ItemPos) + ID;
      end;

    plTimeLine:
      begin
        CellToAbsTime(ItemEnd + EndOffset - 1, DT, Result);
        {
        // res := FItemEndPrecis + (EndOffset - 1) * Display.DisplayUnit
        res := FItemEndPrecis;

        while (res >= MININDAY) do
        begin
          res := res - MININDAY;
        end;

        Result := EncodeTime(res div 60, res mod 60, 0, 0);

        DInc := (ItemEnd + EndOffset) div ((MININDAY div Display.DisplayUnit));

        Result := Result + Int(FPlanner.Mode.TimeLineStart + DInc);
        }
      end;

    plMonth, plWeek:
      begin
        Result := Mode.StartOfMonth - 1 + EndOffset + ItemEnd + Frac(FItemRealEndTime);
      end;

    plActiveDayPeriod:
      begin
        Result := FPlanner.AddActiveDays(FPLanner.Mode.PeriodStartDate, ItemEnd - 1 + EndOffSet);
      end;

    plDayPeriod:
      begin
        Result := FPlanner.Mode.PeriodStartDate - 1 + EndOffset + ItemEnd + Frac(FItemRealEndTime);
      end;

    plHalfDayPeriod:
      begin
        Result := FPlanner.Mode.PeriodStartDate + (ItemEnd + EndOffset) / 2;
      end;

    plMultiMonth:
      begin
        ye := FPlanner.Mode.Year;
        mo := FPlanner.Mode.Month + ItemPos;
        da := ItemEnd;

        while (mo > 12) do
        begin
          mo := mo - 12;
          ye := ye + 1;
        end;

        if da > PlanUtil.DaysInMonth(mo, ye) then
        begin
          Inc(mo);
          if mo > 12 then
          begin
            mo := 1;
            Inc(ye);
          end;
          da := 1;
        end;

        Result := EncodeDate(ye, mo, da) + Frac(FItemRealEndTime);
      end;

    plCustom, plCustomList:
      begin
        Result := IndexToTime(ItemEnd);
      end;
    end;
  end;
end;

function TPlannerItem.GetItemStartTime: TDateTime;
var
  res, ID, Y: Integer;
  //DInc: Integer;
  DT: TDateTime;
begin
  with TPlannerItems(Collection).FOwner do
  begin
    Result := 0;
    case Mode.PlannerType of
    plDay:
      begin
        res := FItemBeginPrecis;
        ID := 0;

        while (res >= 24 * 60) do
        begin
          res := res - 60 * 24;
          Inc(ID);
        end;

        Result := EncodeTime(res div 60, res mod 60, 0, 0);

        if BeginOffset > 0 then
        begin
          res := BeginOffset * Display.DisplayUnit;
          Result := Result - EncodeTime(res div 60, res mod 60, 0, 0);
        end;

        Result := Result + PosToDay(ItemPos) + ID;
      end;

    plTimeLine:
      begin
        CellToAbsTime(ItemBegin - BeginOffset, Result, DT);
        {
        res := FItemBeginPrecis - BeginOffset * Display.DisplayUnit;

        while (res >= MININDAY) do
          res := res - MININDAY;

        while (res < 0) do
          res := res + MININDAY;

        Result := EncodeTime(res div 60, res mod 60, 0, 0);
        DInc := (ItemBegin) div ((MININDAY div Display.DisplayUnit));
        if BeginOffset > 0 then
          DInc := DInc - 1 - (BeginOffset div (MININDAY div Display.DisplayUnit));

        Result := Result + Int(FPlanner.Mode.TimeLineStart + DInc);
        }
      end;

    plMonth, plWeek:
      begin
        Result := Mode.StartOfMonth - BeginOffset + ItemBegin + Frac(FItemRealStartTime);
      end;

    plActiveDayPeriod:
      begin
        Result := FPlanner.AddActiveDays(FPlanner.Mode.PeriodStartDate, ItemBegin - BeginOffset);
      end;

    plDayPeriod:
      begin
        Result := FPlanner.Mode.PeriodStartDate - BeginOffset + ItemBegin + Frac(FItemRealStartTime);
      end;

    plHalfDayPeriod:
      begin
        Result := FPlanner.Mode.PeriodStartDate + (ItemBegin - BeginOffset) / 2;
      end;

    plMultiMonth:
      begin
        res := FPlanner.Mode.Month + ItemPos;
        Y := FPlanner.Mode.Year;
        while (res > 12) do
        begin
          res := res - 12;
          Inc(Y);
        end;
        Result := EncodeDate(Y, res, ItemBegin + 1) + Frac(FItemRealStartTime);
      end;

    plCustom, plCustomList:
      begin
        Result := FPlanner.IndexToTime(ItemBegin);
      end;
    end;

    FItemStartTime := Result;
  end;
end;

function TPlannerItem.IsSelectable: boolean;
begin
  Result := FCanSelect;

  if Assigned(FPlanner) then
  begin
    if Assigned(FPlanner.OnItemCanSelect) then
    begin
      FPlanner.OnItemCanSelect(FPlanner, Self, Result);
    end;
  end;
end;

function TPlannerItem.GetItemSpanTimeStr: string;
begin
  Result := GetCaptionTimeString;
end;

function TPlannerItem.GetItemEndTimeStr: string;
var
  dt1, dd: TDateTime;
begin
  with TPlannerItems(Collection).FOwner do
  begin
    Result := '';
    case Mode.PlannerType of
    plDay:
      begin
        Result := PlanTimeToStr(FItemEndPrecis);
      end;

    plTimeLine:
      begin
        FPlanner.CellToAbsTime(ItemEnd + EndOffset, dt1, dd);
        Result := TimeToStr(dt1) + ' ' + DateToStr(dt1)
      end;

    plMonth, plWeek:
      begin
        Result := DateToStr(Mode.StartOfMonth - 1 + ItemEnd + EndOffset);
      end;

    plActiveDayPeriod:
      begin
        Result := DateToStr(AddActiveDays(Mode.PeriodStartDate, ItemEnd - 1 + EndOffSet));
      end;

    plDayPeriod:
      begin
        Result := DateToStr(Mode.PeriodStartDate - 1 + ItemEnd + EndOffset);
      end;

    plHalfDayPeriod:
      begin
        Result := DateToStr(Mode.PeriodStartDate + (ItemEnd - 1 + EndOffset) / 2);
      end;

    plMultiMonth:
      begin
        if not RealTime then
          Result := DateToStr(GetItemEndTime)
        else
          Result := DateToStr(GetItemRealEndTime);
      end;

   plCustom, plCustomList:
      begin
        Result := FormatDateTime(Mode.DateTimeFormat, ItemEndTime);
      end;
    end;
  end;
end;

function TPlannerItem.GetItemStartTimeStr: string;
var
  dt1, dd: TDateTime;
begin
  with TPlannerItems(Collection).FOwner do
  begin
    Result := '';
    case Mode.PlannerType of
    plDay:
      begin
        Result := PlanTimeToStr(FItemBeginPrecis - BeginOffset * FPlanner.FDisplay.FDisplayUnit + MININDAY);
      end;

    plTimeLine:
      begin
        //Result := PlanTimeToStr(FItemBeginPrecis -
        //  BeginOffset * FPlanner.FDisplay.FDisplayUnit + MININDAY);

        FPlanner.CellToAbsTime(ItemBegin - BeginOffset, dt1, dd);
        Result := TimeToStr(dt1) + ' ' + DateToStr(dt1)
      end;

    plDayPeriod, plMonth, plWeek:
      begin
        Result := DateToStr(Mode.PeriodStartDate + ItemBegin - BeginOffset);
      end;

    plActiveDayPeriod:
      begin
        Result := DateToStr(AddActiveDays(Mode.PeriodStartDate, ItemBegin - BeginOffset));
      end;

    plHalfDayPeriod:
      begin
        Result := DateToStr(Mode.PeriodStartDate + (ItemBegin - BeginOffset) / 2);
      end;

    plMultiMonth:
      begin
        if not RealTime then
          Result := DateToStr(GetItemStartTime)
        else
          Result := DateToStr(GetItemRealStartTime);
      end;

    plCustom, plCustomList:
      begin
        Result := FormatDateTime(Mode.DateTimeFormat, ItemStartTime);
      end;
    end;
  end;
end;

procedure TPlannerItem.SetIsCurrent(const value: Boolean);
begin
  if FIsCurrent <> value then
  begin
    FIsCurrent := value;

    if FIsCurrent and Assigned(FPlanner.FOnItemActivate) then
      FPlanner.FOnItemActivate(FPlanner, Self);

    if not FIsCurrent and Assigned(FPlanner.FOnItemDeActivate) then
      FPlanner.FOnItemDeActivate(FPlanner, Self);

    Repaint;
  end;
end;

procedure TPlannerItem.SetItemRealEndTime(const value: TDateTime);
begin
  FItemRealEndTime := value;
end;

procedure TPlannerItem.SetItemRealStartTime(const value: TDateTime);
begin
  FItemRealStartTime := value;
end;

procedure TPlannerItem.SetBrusStyle(const value: TBrushStyle);
begin
  if (FBrushStyle <> value) then
  begin
    FBrushStyle := value;
    Repaint;
  end;
end;

procedure TPlannerItem.SetCaptionAlign(const value: TAlignment);
begin
  if (FCaptionAlign <> value) then
  begin
    FCaptionAlign := value;
    Repaint;
  end;
end;

procedure TPlannerItem.SetCaptionBkg(const value: TColor);
begin
  if (FCaptionBkg <> value) then
  begin
    FCaptionBkg := value;
    Repaint;
  end;
end;

procedure TPlannerItem.SetCaptionBkgDirection(const Value: TPlannerGradientDirection);
begin
  if (FCaptionBkgDirection <> Value) then
  begin
    FCaptionBkgDirection := Value;
    Repaint;
  end;
end;

procedure TPlannerItem.SetCaptionFont(const value: TFont);
begin
  FCaptionFont.Assign(value);
  Repaint;
end;

{$WARNINGS OFF}

function TPlannerItem.GetCaptionTimeString: string;
var
  s1, s2: string;
  DateTime: TDateTime;
  dt1, dt2, dd: TDateTime;
  //  DOffs1,DOffs2: Integer;
  ho, mi, se, se100: Word;
begin
  case FPlanner.FMode.FPlannerType of
  plDay:
    begin
      s1 := FPlanner.PlanTimeToStr(FItemBeginPrecis - BeginOffset * FPlanner.FDisplay.FDisplayUnit + 60 * 24);
      s2 := FPlanner.PlanTimeToStr(FItemEndPrecis {+ EndOffset * FPlanner.FDisplay.FDisplayUnit});

      if RealTime or InHeader then
      begin
        DecodeTime(ItemRealStartTime, ho, mi, se, se100);

        mi := mi + ho * 60;
        s1 := FPlanner.PlanTimeToStr(mi);

        // s1 := TimeToStr(ItemRealStartTime);

        DecodeTime(ItemRealEndTime, ho, mi, se, se100);
        mi := mi + ho * 60;
        s2 := FPlanner.PlanTimeToStr(mi);

        // s2 := TimeToStr(ItemRealEndTime);

        if (int(ItemRealStartTime) <> int(ItemRealEndTime))
          and (int(ItemRealStartTime) <> 0) and (int(ItemRealEndTime) <> 0) then
          Result := s1 + ' ' + DateToStr(ItemRealStartTime) + ' - ' + s2 + ' ' + DateToStr(ItemRealEndTime)
        else
          Result := s1 + ' - ' + s2;
        {$IFDEF TMSDEBUG}
        outputdebugstring(PChar(DateToStr(ItemRealEndTime)));
        {$ENDIF}
      end
      else
      begin
        if (int(ItemStartTime) <> int(ItemEndTime)) and (int(ItemStartTime) <> 0) and (int(ItemEndTime) <> 0) then
          Result := s1 + ' ' + DateToStr(ItemStartTime) + ' - ' + s2 + ' ' + DateToStr(ItemEndTime)
        else
          Result := s1 + ' - ' + s2;
      end;
    end;

  plTimeLine:
    begin
      s1 := FPlanner.PlanTimeToStr(FItemBeginPrecis - BeginOffset * FPlanner.FDisplay.FDisplayUnit + MININDAY);
      s2 := FPlanner.PlanTimeToStr(FItemEndPrecis);

      {
      s2 := FPlanner.PlanTimeToStr(FItemEndPrecis +
      EndOffset * FPlanner.FDisplay.FDisplayUnit);
      }
      (*
      if RealTime or InHeader then
      begin
        s1 := TimeToStr(ItemRealStartTime);
        s2 := TimeToStr(ItemRealEndTime);

        if (Int(ItemRealStartTime) <> Int(ItemRealEndTime)) and
           (Int(ItemRealStartTime) <> 0) and (Int(ItemRealEndTime) <> 0) then
          Result := s1 + ' ' + DateToStr(ItemRealStartTime) + ' - ' + s2 + ' ' + DateToStr(ItemRealEndTime)
        else
          Result := s1 + ' - ' + s2;

{$IFDEF TMSDEBUG}
        outputdebugstring(pchar(datetostr(itemrealendtime)));
{$ENDIF}
      end
      else
      *)
      begin
        FPlanner.CellToAbsTime(ItemBegin - BeginOffset, dt1, dd);
        FPlanner.CellToAbsTime(ItemEnd - 1 + EndOffset, dt2, dd);

        if int(dt1) <> int(dt2) then
          Result := TimeToStr(dt1) + ' ' + DateToStr(dt1) + ' - ' + TimeToStr(dd)  + ' ' + DateToStr(dd)
        else
          Result := TimeToStr(dt1) + ' - ' + TimeToStr(dd) + ' ' + DateToStr(dt2);

        {
        DOffs1 := (((ItemBegin) * FPlanner.Display.DisplayUnit) div MININDAY);
        DOffs2 := (((ItemEnd + EndOffset) * FPlanner.Display.DisplayUnit) div MININDAY);

        if BeginOffset > 0 then
          DOffs1 := DOffs1 - 1 - ((BeginOffset * FPlanner.Display.DisplayUnit) div MININDAY);

        if (Doffs1 <> Doffs2) then
          Result := s1 + ' ' + DateToStr(Planner.Mode.TimeLineStart + DOffs1) + ' - ' + s2 + ' ' + DateToStr(Planner.Mode.TimeLineStart + DOffs2)
        else
          Result := s1 + ' - ' + s2 + ' ' + DateToStr(Planner.Mode.TimeLineStart + DOffs1);
        }
      end;
    end;

   plWeek:
     begin
       s2 := '';
       s1 := FPlanner.GetDayName(ItemBegin - FPlanner.FMode.WeekStart);

       DateTime := FPlanner.Mode.PeriodStartDate + FItemBegin;
       DateTime := DateTime - BeginOffset;

       if FPlanner.Mode.FDateTimeFormat <> '' then
         s1 := s1 + ' ' + FormatDateTime(FPlanner.Mode.FDateTimeFormat, DateTime + Frac(ItemRealStartTime));

       DateTime := FPlanner.Mode.PeriodStartDate + FItemEnd;
       DateTime := DateTime + EndOffset - 1;

       if FItemEnd > FItemBegin + 1 then
       begin
         s2 := FPlanner.GetDayName(FItemEnd - 1 - FPlanner.FMode.WeekStart);
         if FPlanner.Mode.FDateTimeFormat <> '' then
           s2 :=  s2 + ' ' + FormatDateTime(FPlanner.Mode.FDateTimeFormat, DateTime + Frac(ItemRealEndTime));
       end;

       if s2 <> '' then
         s1 := s1 + ' - ' + s2;
       Result := s1;
     end;

   plDayPeriod, plMonth:
     begin
       with FPlanner.FMode do
       begin
         DateTime := FPlanner.Mode.PeriodStartDate + FItemBegin;
         DateTime := DateTime - BeginOffset;

         s1 := FormatDateTime(FDateTimeFormat, DateTime + Frac(ItemRealStartTime));

         DateTime := FPlanner.Mode.PeriodStartDate + FItemEnd;
         DateTime := DateTime + EndOffset - 1;

         if FItemEnd > FItemBegin + 1 then
           s2 := '';
         if FItemEnd > FItemBegin + 1 then
           s2 := FormatDateTime(FDateTimeFormat, DateTime + Frac(ItemRealEndTime));
         if (s2 <> '') then
           s1 := s1 + ' - ' + s2;
         Result := s1;
       end;
     end;

   plActiveDayPeriod:
     begin
       with FPlanner.FMode do
       begin
         DateTime := FPlanner.AddActiveDays(FPlanner.Mode.PeriodStartDate, FItemBegin - BeginOffset);
//         DateTime := DateTime - BeginOffset;

         s1 := FormatDateTime(FDateTimeFormat, DateTime + Frac(ItemRealStartTime));

         DateTime := FPlanner.AddActiveDays(FPlanner.Mode.PeriodStartDate, FItemEnd + EndOffSet - 1);
//         DateTime := DateTime + EndOffset - 1;

         if FItemEnd > FItemBegin + 1 then
           s2 := '';

         if FItemEnd > FItemBegin + 1 then
           s2 := FormatDateTime(FDateTimeFormat, DateTime + Frac(ItemRealEndTime));

         if (s2 <> '') then
           s1 := s1 + ' - ' + s2;

         Result := s1;
       end;
     end;

   plHalfDayPeriod:
     begin
       with FPlanner.FMode do
       begin
         DateTime := Trunc(FPlanner.Mode.PeriodStartDate + (FItemBegin - BeginOffset) / 2);

         s1 := FormatDateTime(FDateTimeFormat, DateTime);

         if Odd(FItemBegin - BeginOffset) then
           s1 := s1 + ' PM'
         else
           s1 := s1 + ' AM';

         DateTime := Trunc((FPlanner.Mode.PeriodStartDate + (FItemEnd - 1 + EndOffset) / 2));

         s2 := FormatDateTime(FDateTimeFormat, DateTime);
         if Odd(FItemEnd + EndOffset) then
           s2 := s2 + ' AM'
         else
           s2 := s2 + ' PM';

         Result := s1 + ' - ' + s2;
       end;
     end;

   plMultiMonth:
     begin
       Result := ItemStartTimeStr + ' - ' + ItemEndTimeStr;
     end;

  plCustom, plCustomList:
     begin
       Result := ItemStartTimeStr + ' - ' + ItemEndTimeStr;
     end;
  end;
end;

{$WARNINGS ON}

function TPlannerItem.GetWideCaptionString: widestring;
begin
  if RelationShip = irChild then
  begin
    Result := ParentItem.GetCaptionString;
    Exit;
  end;

  if CaptionType in [ctTime, ctTimeText] then
  begin
    Result := GetCaptionTimeString;
    if CaptionType = ctTimeText then
      Result := Result + ' ' + WideCaption;
  end
  else
    Result := WideCaption;
end;

function TPlannerItem.GetCaptionString: string;
begin
  if RelationShip = irChild then
  begin
    Result := ParentItem.GetCaptionString;
    Exit;
  end;

  if CaptionType in [ctTime, ctTimeText] then
  begin
    Result := GetCaptionTimeString;
    if CaptionType = ctTimeText then
      Result := Result + ' ' + CaptionText;
  end
  else
    Result := CaptionText;
end;

function TPlannerItem.GetCaptionHeight: Integer;
begin
  Result := FCaptionHeight;
end;

procedure TPlannerItem.SetSelectColor(const value: TColor);
begin
  if FSelectColor <> value then
  begin
    FSelectColor := value;
    Repaint;
  end;
end;

procedure TPlannerItem.SetLinkColor(const Value: TColor);
begin
  if (FLinkColor <> Value) then
  begin
    FLinkColor := Value;
    if Assigned(FPlanner) then
      if Assigned(FPlanner.GridControl) then
        if FPlanner.GridControl.HandleAllocated then
          FPlanner.GridControl.Repaint;
  end;
end;

procedure TPlannerItem.SetLinkSelect(const value: Boolean);
begin
  if FLinkSelect <> value then
  begin
    FLinkSelect := value;
    Repaint;
  end;
end;

procedure TPlannerItem.SetSelectColorTo(const value: TColor);
begin
  if FSelectColorTo <> value then
  begin
    FSelectColorTo := value;
    Repaint;
  end;
end;

procedure TPlannerItem.SetSelectFontColor(const value: TColor);
begin
  if FSelectFontColor <> value then
  begin
    FSelectFontColor := value;
    Repaint;
  end;
end;

procedure TPlannerItem.SetSelectCaptionBkg(const Value: TColor);
begin
  if (FSelectCaptionBkg <> Value) then
  begin
    FSelectCaptionBkg := Value;
    Repaint;
  end;
end;

procedure TPlannerItem.SetSelectCaptionBkgTo(const Value: TColor);
begin
  if (FSelectCaptionBkgTo <> Value) then
  begin
    FSelectCaptionBkgTo := Value;
    Repaint;
  end;
end;

procedure TPlannerItem.SetSelected(const value: Boolean);
begin
  if (FSelected <> value) then
  begin
    if not value and not (csDestroying in FPlanner.ComponentState) then
      FPlanner.ItemUnSelected(Self);

    FSelected := value;
    Self.Repaint;

    if ShowLinks and FSelected then
      (Collection as TPlannerItems).UpdateLinks(Self);

    if ShowLinks and not FSelected then
      (Collection as TPlannerItems).ClearLinks;

    if FPlanner.AutoSelectLinkedItems and FSelected then
    begin
      FPlanner.SelectLinkedItems(Self);
    end;
  end;
end;

procedure TPlannerItem.SetShadow(const value: Boolean);
begin
  if FShadow <> value then
  begin
    FShadow := value;
    Self.Repaint;
  end;
end;

procedure TPlannerItem.SetObject(const value: TObject);
begin
  if FObject = value then
    Exit;

  if FOwnsItemObject and Assigned(FObject) then
    FObject.Free;
  FObject := value;
end;

procedure TPlannerItem.SetInHeader(const value: Boolean);
begin
  if FInHeader <> value then
  begin
    FInHeader := value;
    FVisible := not FInHeader;

    Self.Repaint;
    FPlanner.FHeader.Invalidate;
    FPlanner.FGrid.Invalidate;

    if FPlanner.FPlannerHeader.AutoSize then
      FPlanner.AutoSizeHeader;

    FPlanner.Items.SetConflicts;
    FPlanner.FGrid.Invalidate;
  end;
end;

procedure TPlannerItem.SetItemBeginPrecis(const value: Integer);
begin
  FItemBeginPrecis := value;
  ItemBegin := (FItemBeginPrecis div FPlanner.Display.DisplayUnit) - FPlanner.Display.DisplayStart;
end;

procedure TPlannerItem.SetItemEndPrecis(const value: Integer);
begin
  FItemEndPrecis := value;
  ItemEnd := (FItemEndPrecis div FPlanner.Display.DisplayUnit) - FPlanner.Display.DisplayStart;
end;

procedure TPlannerItem.SetTrackVisible(const value: Boolean);
begin
  FTrackVisible := value;
  Repaint;
end;

procedure TPlannerItem.SetShape(const value: TPlannerShape);
begin
  FShape := value;
  Repaint;
end;

procedure TPlannerItem.SetPopupMenu(const value: TPopupMenu);
begin
  FPopupMenu := value;
end;

procedure TPlannerItem.SetShowSelection(const value: Boolean);
begin
  FShowSelection := value;
  Repaint;
end;

procedure TPlannerItem.SetShowDeleteButton(const value: Boolean);
begin
  FShowDeleteButton := value;
  Repaint;
end;

procedure TPlannerItem.GetTimeTag;
begin
  ItemBeginPrecis := Loword(DBTag);
  ItemEndPrecis := Hiword(DBTag);
  FRepainted := False;
end;

procedure TPlannerItem.SetTimeTag;
begin
  ItemBegin := ItemBegin;
  ItemEnd := ItemEnd;
  DBTag := MakeLong(ItemBeginPrecis, ItemEndPrecis);
end;

procedure TPlannerItem.Update;
begin
  FPlanner.UpdateItem(Self);
end;

function TPlannerItem.GetItemText: string;
var
  Index: Integer;
begin
  Result := '';
  for Index := 0 to Text.Count - 1 do
  begin
    if Result <> '' then
      Result := Result + #13;
    Result := Result + Text.Strings[Index];
  end;
end;

procedure TPlannerItem.SetWordWrap(const value: Boolean);
begin
  if FWordWrap <> value then
  begin
    FWordWrap := value;
    Self.Repaint;
  end;
end;

procedure TPlannerItem.SetAttachement(const value: string);
begin
  if FAttachement <> value then
  begin
    FAttachement := value;
    Self.Repaint;
  end;
end;

procedure TPlannerItem.MoveItem(NewBegin, NewEnd, NewPos: Integer; var NewOffset: Integer);
var
  delta, w: Integer;
begin
  if Assigned(FPlanner.OnItemPlaceUpdate) then
    FPlanner.OnItemPlaceUpdate(FPlanner, Self, NewBegin, NewEnd, NewPos);

  delta := NewBegin - ItemBegin;

  //  W := newend - newbegin + beginoffset + endoffset;

  w := ItemEnd - ItemBegin + BeginOffset + EndOffset;

  FInHeader := false;
  RealTime := False;

  if BeginOffset <> 0 then
  begin
    BeginOffset := BeginOffset - delta;

    If BeginOffset < 0 then
    begin
      NewBegin := ItemBegin - BeginOffset;
      NewEnd := NewBegin + w;
      BeginOffset := 0;
      NewOffset := NewOffset - delta;
    end
    else
    begin
      NewBegin := NewBegin - delta;
      NewOffset := NewOffset - delta;
      NewEnd := ItemEnd + delta;
    end;
  end;

  if EndOffset <> 0 then
  begin
    EndOffset := EndOffset + delta;

    if EndOffset < 0 then
    begin
      NewEnd := ItemEnd + EndOffset;
      EndOffset := 0;
    end
    else
    begin
      NewEnd := ItemEnd + EndOffset;
      NewOffset := NewOffset;
      NewBegin := ItemBegin + delta; // **
    end;
  end;

  if NewBegin < 0 then
  begin
    BeginOffset := -NewBegin;
    NewBegin := 0;
    NewOffset := NewOffset - delta;
  end;

  if NewEnd < 1 then
  begin
    NewBegin := 0;
    NewEnd := 1;
    BeginOffset := w - 1;
    EndOffset := 0;
    NewOffset := NewOffset - delta;
  end;

  if FPlanner.Sidebar.Position = spTop then
  begin
    if NewEnd > FPlanner.FGrid.ColCount then
    begin
      EndOffset := NewEnd - FPlanner.FGrid.ColCount;
      NewEnd := FPlanner.FGrid.ColCount;
    end;
  end
  else
  begin
    if NewEnd > FPlanner.FGrid.RowCount then
    begin
      EndOffset := NewEnd - FPlanner.FGrid.RowCount;
      NewEnd := FPlanner.FGrid.RowCount;
    end;
  end;

  ItemBegin := NewBegin;
  ItemEnd := NewEnd;
  ItemPos := NewPos;
end;

procedure TPlannerItem.SizeItem(NewBegin, NewEnd: Integer);
var
  NewPos: Integer;
begin
  RealTime := False;

  NewPos := ItemPos;

  if Assigned(FPlanner.OnItemPlaceUpdate) then
    FPlanner.OnItemPlaceUpdate(FPlanner, Self, NewBegin, NewEnd, NewPos);

  if ItemBegin <> NewBegin then
    ItemBegin := NewBegin;

  if ItemEnd <> NewEnd then
    ItemEnd := NewEnd;

  if ItemPos <> NewPos then
    ItemPos := NewPos;
end;

function TPlannerItem.GetItemRealEndTime: TDateTime;
begin
  if RealTime or InHeader then
    Result := FItemRealEndTime
  else
    Result := ItemEndTime;
end;

function TPlannerItem.GetItemRealStartTime: TDateTime;
begin
  if RealTime then
    Result := FItemRealStartTime
  else
    Result := ItemStartTime;
end;

procedure TPlannerItem.SetURL(const value: string);
begin
  if FURL <> value then
  begin
    FURL := value;
    Repaint;
  end;
end;

procedure TPlannerItem.SetAlarm(const value: TPlannerAlarm);
begin
  FAlarm.Assign(value);
end;

function TPlannerItem.GetStrippedItemText: string;
var
  txt: string;
begin
  txt := GetItemText;

  if IsRtf(txt) then
  begin
    if not FPlanner.RichEdit.Visible then
    begin
      FPlanner.TextToRich(txt);
      Result := FPlanner.FRichEdit.Text;
    end;
  end
  else
    Result := HTMLStrip(txt);
end;

procedure TPlannerItem.SetFlashing(const value: Boolean);
begin
  if FFlashing <> value then
  begin
    FFlashing := value;
    if not FFlashing then
      Repaint;
  end;
end;

procedure TPlannerItem.Changed;
begin
  FPlanner.Items.ItemChanged(Self);

  if Assigned(OnDesignChange) then
    OnDesignChange(Self);
end;

procedure TPlannerItem.ChangeCrossing;
var
  delta: Integer;
begin
  delta := ItemEnd + EndOffset - ItemBegin;

  BeginOffset := - (ItemBegin - MININDAY div Planner.Display.DisplayUnit);
  ItemBegin := 0;
  EndOffset := 0;
  ItemEnd := delta - BeginOffset;
end;

function TPlannerItem.Planner: TCustomPlanner;
begin
  Result := (Collection as TPlannerItems).FOwner;
end;

function TPlannerItem.GetParentItem: TPlannerItem;
var
  i: Integer;
begin
  Result := Self;
  if (ParentIndex = -1) or (RelationShip = irParent) then
    Result := Self
  else
    for i := 1 to (Collection as TPlannerItems).Count do
    begin
      if ((Collection as TPlannerItems).Items[i - 1].ParentIndex = ParentIndex)
         and ((Collection as TPlannerItems).Items[i - 1].RelationShip = irParent) then
      begin
        Result := (Collection as TPlannerItems).Items[i - 1];
        Break;
      end;
    end;
end;

procedure TPlannerItem.SetControlVal(ID, AValue: string);
begin
  SetValue(ID, AValue);
end;

function TPlannerItem.GetControlVal(ID: string): string;
var
  v: string;
begin
  Result := '';
  if GetValue(ID, v) then
    Result := v;
end;

function TPlannerItem.GetValue(ID: string; var value: string): Boolean;
begin
  Result := GetControlValue(Text.Text, ID, value);
end;

function TPlannerItem.SetValue(ID, value: string): Boolean;
var
  s: string;
begin
  s := Text.Text;
  Result := SetControlValue(s, ID, value);
  if Result then
    Text.Text := s;
end;

function TPlannerItem.GetNotes: string;
var
  i: Integer;
begin
  Result := '';
  for i := 1 to Text.Count do
  begin
    Result := Result + Text[i - 1];
    if i < Text.Count then
      Result := Result + #13;
  end;
end;

function TPlannerItem.GetCanEdit: Boolean;
begin
  Result := ReadOnly or (InplaceEdit = peForm) or (FPlanner.UserMode in [puReadOnly, puViewOnly]);
end;

procedure TPlannerItem.EnsureFullVisibility;
begin
  if FPlanner.Sidebar.Position = spTop then
  begin
    if ItemBegin < FPlanner.FGrid.LeftCol then
      FPlanner.FGrid.LeftCol := ItemBegin;

    if ItemEnd > FPlanner.FGrid.LeftCol + FPlanner.FGrid.VisibleColCount then
      FPlanner.FGrid.LeftCol := ItemEnd - FPlanner.FGrid.VisibleColCount;
  end
  else
  begin
    if ItemBegin < FPlanner.FGrid.TopRow then
      FPlanner.FGrid.TopRow := ItemBegin;

    if ItemEnd > FPlanner.FGrid.TopRow + FPlanner.FGrid.VisibleRowCount then
      FPlanner.FGrid.TopRow := ItemEnd - FPlanner.FGrid.VisibleRowCount;
  end;
end;

procedure TPlannerItem.SetCaptionBkgTo(const value: TColor);
begin
  if (FCaptionBkgTo <> value) then
  begin
    FCaptionBkgTo := value;
    Repaint;
  end;
end;

procedure TPlannerItem.SetCaptionDivider(const Value: boolean);
begin
  if (FCaptionDivider <> Value) then
  begin
    FCaptionDivider := Value;
    Changed;
  end;
end;

procedure TPlannerItem.SetDrawTool(const value: TCustomItemDrawTool);
begin
  if (FDrawTool <> value) then
  begin
    FDrawTool := value;
    Repaint;
  end;
end;

procedure TPlannerItem.SetCompletion(const value: Integer);
begin
  if value > 100 then
    raise Exception.Create('Completion cannot be larger than 100');

  if value < 0 then
    raise Exception.Create('Completion cannot be smaller than 0');

  if (FCompletion <> value) then
  begin
    FCompletion := value;
    Repaint;
  end;
end;

procedure TPlannerItem.ImageListAdapt(var R: TRect);
begin
  if ImageIndexList.Count > 0 then
  begin
    if ImagePosition = ipHorizontal then
      R.Top := R.Top + FPlanner.PlannerImages.Height
    else
      R.Left := R.Left + FPlanner.PlannerImages.Width + 4;
  end;
end;

procedure TPlannerItem.CompletionAdapt(var R: TRect);
begin
  if CompletionDisplay = cdVertical then
    R.Left := R.Left + 11;

  if CompletionDisplay = cdHorizontal then
    R.Top := R.Top + 11;
end;

procedure TPlannerItem.SetCompletionDisplay(const value: TCompletionDisplay);
begin
  if (FCompletionDisplay <> value) then
  begin
    FCompletionDisplay := value;
    Repaint;
  end;
end;

procedure TPlannerItem.SetWideText(const value: widestring);
begin
  FWideText := value;
  Repaint;
end;

procedure TPlannerItem.SetWideCaption(const value: widestring);
begin
  FWideCaption := value;
  Repaint;
end;

procedure TPlannerItem.SetUnicode(const value: Boolean);
begin
  if value <> FUnicode then
  begin
    FUnicode := value;
    Repaint;
  end;
end;

{NEW INTERFACES FOR DESCENDENT CLASSES}
procedure TPlannerItem.SetClipped(value: Boolean);
begin
  FClipped := value;
end;

procedure TPlannerItem.SetHintIndicator(const Value: boolean);
begin
  if (FHintIndicator <> Value) then
  begin
    FHintIndicator := Value;
    Repaint;
  end;
end;

procedure TPlannerItem.SetHintIndicatorColor(const Value: TColor);
begin
  if (FHintIndicatorColor <> Value) then
  begin
    FHintIndicatorColor := Value;
    Repaint;
  end;
end;

procedure TPlannerItem.SetHTMLTemplate(const value: TStrings);
begin
  FHTMLTemplate.Assign(value);
end;

procedure TPlannerItem.SetConflictPos(value: Integer);
begin
  FConflictPos := value;
end;

procedure TPlannerItem.SetConflicts(value: Integer);
begin
  FConflicts := value;
end;

{END OF NEW INTERFACES FOR DESCENDENT CLASSES}

{ TPlannerItems }

function TPlannerItems.Add: TPlannerItem;
begin
  Result := TPlannerItem(inherited Add);
  Result.Assign(FOwner.DefaultItem);
  SetConflicts;
end;

constructor TPlannerItems.Create(AOwner: TCustomPlanner);
begin
  inherited Create(GetItemClass);
  FOwner := AOwner;
  FSelected := nil;
  FUpdateCount := 0;
end;

function TPlannerItems.GetItem(Index: Integer): TPlannerItem;
begin
  Result := TPlannerItem(inherited GetItem(Index));
end;

{$IFNDEF VER90}
function TPlannerItems.GetOwner: TPersistent;
begin
  Result := FOwner;
end;
{$ENDIF}

function TPlannerItems.CheckItems: Boolean;
var
  i: Integer;
begin
  Result := True;

  if not Assigned(FOwner.ItemChecker) then
    Exit;

  FOwner.ItemChecker.StartCheck;

  for i := 1 to Count do
    if not CheckItem(Items[i - 1]) then
      Result := False;

  FOwner.ItemChecker.StopCheck;
end;

function TPlannerItems.CheckPosition(Position: Integer): Boolean;
var
  i: Integer;
begin
  Result := True;

  if not Assigned(FOwner.ItemChecker) then
    Exit;

  FOwner.ItemChecker.StartCheck;

  for i := 1 to Count do
    if Items[i - 1].ItemPos = Position then
      if not CheckItem(Items[i - 1]) then
        Result := False;

  FOwner.ItemChecker.StopCheck;
end;

function TPlannerItems.CheckLayer(Layer: Integer): Boolean;
var
  i: Integer;
begin
  Result := True;

  if not Assigned(FOwner.ItemChecker) then
    Exit;

  FOwner.ItemChecker.StartCheck;

  for i := 1 to Count do
    if Items[i - 1].Layer and Layer = Layer then
      if not CheckItem(Items[i - 1]) then
        Result := False;

  FOwner.ItemChecker.StopCheck;
end;

function TPlannerItems.CheckItem(Item: TPlannerItem): Boolean;
var
  Corr: string;
begin
  Result := True;

  if Assigned(FOwner.ItemChecker) then
  begin
    Item.Selected := True;

    if FOwner.ItemChecker.UseCorrect then
    begin
      Corr := FOwner.ItemChecker.Correct(HTMLStrip(Item.Text.Text));
      if Corr <> Item.Text.Text then
        Result := False;
      Item.Text.Text := Corr;
    end;

    if FOwner.ItemChecker.UseMarkError then
    begin
      Corr := FOwner.ItemChecker.MarkError(Item.Text.Text);
      if Corr <> Item.Text.Text then
        Result := False;
      Item.Text.Text := Corr;
    end;

    Item.Selected := False;
  end;
end;

function TPlannerItems.Insert(Index: Integer): TPlannerItem;
begin
  Result := TPlannerItem(inherited Insert(Index));
  Result.Assign(FOwner.DefaultItem);
end;

function TPlannerItems.HasItem(ItemBegin, ItemEnd, ItemPos: Integer): Boolean;
var
  ItemIndex: Integer;
  APlannerItem: TPlannerItem;
begin
  Result := False;

  for ItemIndex := 0 to Count - 1 do
  begin
    APlannerItem := Items[ItemIndex];

    if (((APlannerItem.ItemBegin <= ItemBegin) and (APlannerItem.ItemEnd > ItemBegin)) or
       ((APlannerItem.ItemBegin < ItemEnd) and (APlannerItem.ItemEnd >= ItemEnd)) or
       ((ItemBegin < APlannerItem.ItemEnd) and (ItemEnd >= APlannerItem.ItemEnd)) or
       ((ItemBegin <= APlannerItem.ItemBegin) and (ItemEnd > APlannerItem.ItemBegin))) and
       (APlannerItem.ItemPos = ItemPos) and (APlannerItem.Visible) and
       (InVisibleLayer(APlannerItem.Layer)) and (APlannerItem.ItemBegin <> APlannerItem.ItemEnd) then
    begin
      Result := (not APlannerItem.AllowOverlap) or (not FOwner.FOverlap);
      if Result then
        Break;
    end;
  end;
end;

function TPlannerItems.HasHeaderItem(ItemPos: Integer): Boolean;
var
  ItemIndex: Integer;
  APlannerItem: TPlannerItem;
begin
  Result := False;

  for ItemIndex := 0 to Count - 1 do
  begin
    APlannerItem := Items[ItemIndex];
    if APlannerItem.InHeader and (APlannerItem.ItemPos = ItemPos) and (APlannerItem.Visible) and
       (InVisibleLayer(APlannerItem.Layer)) then
    begin
      Result := true;
      Break;
    end;
  end;
end;

function TPlannerItems.HasItemInt(ItemBegin, ItemEnd, ItemPos: Integer): Boolean;
var
  ItemIndex: Integer;
  APlannerItem: TPlannerItem;
begin
  Result := False;

  for ItemIndex := 0 to Count - 1 do
  begin
    APlannerItem := Items[ItemIndex];

    if (((APlannerItem.ItemBegin <= ItemBegin) and (APlannerItem.ItemEnd > ItemBegin)) or
       ((APlannerItem.ItemBegin < ItemEnd) and (APlannerItem.ItemEnd >= ItemEnd)) or
       ((ItemBegin < APlannerItem.ItemEnd) and (ItemEnd >= APlannerItem.ItemEnd)) or
       ((ItemBegin <= APlannerItem.ItemBegin) and (ItemEnd > APlannerItem.ItemBegin))) and
       (APlannerItem.ItemPos = ItemPos) and (APlannerItem.Visible) and (APlannerItem <> Selected) and
       (InVisibleLayer(APlannerItem.Layer)) and (APlannerItem.ItemBegin <> APlannerItem.ItemEnd) then
    begin
      Result := (not APlannerItem.AllowOverlap) or (not FOwner.FOverlap);
      if Result then
        Break;
    end;
  end;
end;

function TPlannerItems.FindFirst(ItemBegin, ItemEnd, ItemPos: Integer): TPlannerItem;
var
  ItemIndex: Integer;
  APlannerItem: TPlannerItem;

begin
  Result := nil;

  FFindIndex := 1;

  for ItemIndex := 1 to Self.Count do
  begin
    APlannerItem := Self.Items[ItemIndex - 1];

    if (((APlannerItem.ItemBegin <= ItemBegin) and (APlannerItem.ItemEnd > ItemBegin)) or
       ((APlannerItem.ItemBegin < ItemEnd) and (APlannerItem.ItemEnd >= ItemEnd)) or
       ((ItemBegin < APlannerItem.ItemEnd) and (ItemEnd >= APlannerItem.ItemEnd)) or
       ((ItemBegin <= APlannerItem.ItemBegin) and (ItemEnd > APlannerItem.ItemBegin))) and
       (APlannerItem.ItemPos = ItemPos) then
    begin
      Result := APlannerItem;
      FFindIndex := ItemIndex + 1;
      Break;
    end;
  end;
end;

function TPlannerItems.FindNext(ItemBegin, ItemEnd, ItemPos: Integer): TPlannerItem;
var
  ItemIndex: Integer;
  APlannerItem: TPlannerItem;

begin
  Result := nil;

  for ItemIndex := FFindIndex to Self.Count do
  begin
    APlannerItem := Self.Items[ItemIndex - 1];
    if (((APlannerItem.ItemBegin <= ItemBegin) and (APlannerItem.ItemEnd > ItemBegin)) or
       ((APlannerItem.ItemBegin < ItemEnd) and (APlannerItem.ItemEnd >= ItemEnd)) or
       ((ItemBegin < APlannerItem.ItemEnd) and (ItemEnd >= APlannerItem.ItemEnd)) or
       ((ItemBegin <= APlannerItem.ItemBegin) and (ItemEnd > APlannerItem.ItemBegin))) and
       (APlannerItem.ItemPos = ItemPos) then
    begin
      FFindIndex := ItemIndex + 1;
      Result := APlannerItem;
      Break;
    end;
  end;
end;

procedure TPlannerItems.ClearSelectedRepaints(ItemBegin, ItemPos: Integer);
var
  ItemIndex, ItemEnd: Integer;
  APlannerItem: TPlannerItem;
begin
  ItemEnd := ItemBegin + 1;
  for ItemIndex := 0 to Self.Count - 1 do
  begin
    APlannerItem := Self.Items[ItemIndex];
    if (((ItemBegin >= APlannerItem.ItemBegin) and (ItemBegin < APlannerItem.ItemEnd)) or
       ((ItemEnd > APlannerItem.ItemBegin) and (ItemEnd < APlannerItem.ItemEnd)) or
       ((APlannerItem.ItemBegin >= ItemBegin) and (APlannerItem.ItemBegin < ItemEnd)) or
       ((APlannerItem.ItemEnd > ItemBegin) and (APlannerItem.ItemEnd <= ItemEnd))
       ) and (APlannerItem.ItemPos = ItemPos) and (APlannerItem.Visible) and (InVisibleLayer(APlannerItem.Layer)) then
    begin
      APlannerItem.Repainted := False;
    end;
  end;
end;

function TPlannerItems.NumItem(ItemBegin, ItemEnd, ItemPos: Integer): TPoint;
var
  ItemIndex: Integer;
  APlannerItem: TPlannerItem;
begin
  Result.X := 0;
  Result.Y := 0;
  for ItemIndex := 0 to Count - 1 do
  begin
    APlannerItem := Items[ItemIndex];
    if (((ItemBegin >= APlannerItem.ItemBegin) and (ItemBegin < APlannerItem.ItemEnd)) or
       ((ItemEnd > APlannerItem.ItemBegin) and (ItemEnd < APlannerItem.ItemEnd)) or
       ((APlannerItem.ItemBegin >= ItemBegin) and (APlannerItem.ItemBegin < ItemEnd)) or
       ((APlannerItem.ItemEnd > ItemBegin) and (APlannerItem.ItemEnd <= ItemEnd))
       ) and (APlannerItem.ItemPos = ItemPos) and (APlannerItem.Visible) and (InVisibleLayer(APlannerItem.Layer)) and
      (APlannerItem.ItemEnd > APlannerItem.ItemBegin) then
    begin
      Inc(Result.X);

      if APlannerItem.FConflicts > Result.Y then
        Result.Y := APlannerItem.FConflicts;

      if not (APlannerItem.Background and APlannerItem.AllowOverlap) then
      begin
        if ItemBegin > APlannerItem.ItemBegin then
          ItemBegin := APlannerItem.ItemBegin;
        if ItemEnd < APlannerItem.ItemEnd then
          ItemEnd := APlannerItem.ItemEnd;
      end;
    end;
  end;
end;

function TPlannerItems.NumItemPos(ItemBegin, ItemEnd, ItemPos: Integer): TPoint;
var
  ItemIndex: Integer;
  APlannerItem: TPlannerItem;
begin
  Result.X := 0;
  Result.Y := 0;
  for ItemIndex := 0 to Self.Count - 1 do
  begin
    APlannerItem := Self.Items[ItemIndex];
    if (((APlannerItem.ItemBegin <= ItemBegin) and (APlannerItem.ItemEnd > ItemBegin)) or
       ((APlannerItem.ItemBegin < ItemEnd) and (APlannerItem.ItemEnd >= ItemEnd)) or
       ((ItemBegin < APlannerItem.ItemEnd) and (ItemEnd >= APlannerItem.ItemEnd)) or
       ((ItemBegin <= APlannerItem.ItemBegin) and (ItemEnd > APlannerItem.ItemBegin))) and
       (APlannerItem.ItemPos = ItemPos) and (APlannerItem.Visible) and (InVisibleLayer(APlannerItem.Layer)) then
    begin
      Inc(Result.X);
      if APlannerItem.FConflictPos > Result.Y then
        Result.Y := APlannerItem.FConflictPos;
    end;
  end;
end;

function TPlannerItems.NumItemPosStart(ItemBegin, ItemPos: Integer): Integer;
var
  ItemIndex: Integer;
  APlannerItem: TPlannerItem;
begin
  Result := 0;
  for ItemIndex := 0 to Self.Count - 1 do
  begin
    APlannerItem := Self.Items[ItemIndex];
    if (APlannerItem.ItemBegin = ItemBegin) and (APlannerItem.ItemPos = ItemPos) and
       (APlannerItem.Visible) and (InVisibleLayer(APlannerItem.Layer)) then
    begin
      Inc(Result);
    end;
  end;
end;

function TPlannerItems.FindItem(ItemBegin, ItemPos: Integer): TPlannerItem;
var
  ItemIndex: Integer;
  APlannerItem: TPlannerItem;
begin
  Result := nil;
  for ItemIndex := 0 to Self.Count - 1 do
  begin
    APlannerItem := Self.Items[ItemIndex];
    if (APlannerItem.ItemBegin <= ItemBegin) and (APlannerItem.ItemEnd > ItemBegin) and
       (APlannerItem.ItemPos = ItemPos) and (APlannerItem.Visible) and (InVisibleLayer(APlannerItem.Layer)) then
    begin
      Result := APlannerItem;
      Break;
    end;
  end;
end;

function TPlannerItems.FindItemIdx(ItemBegin: Integer): TPlannerItem;
var
  ItemIndex: Integer;
  APlannerItem: TPlannerItem;
begin
  Result := nil;
  for ItemIndex := 0 to Self.Count - 1 do
  begin
    APlannerItem := Self.Items[ItemIndex];
    if (APlannerItem.ItemBegin <= ItemBegin) and (APlannerItem.ItemEnd > ItemBegin) and
       (APlannerItem.Visible) and (InVisibleLayer(APlannerItem.Layer)) then
    begin
      Result := APlannerItem;
      Break;
    end;
  end;
end;

function TPlannerItems.FindItemPos(ItemBegin, ItemPos, ItemSubPos: Integer): TPlannerItem;
var
  ItemIndex, wo: Integer;
  APlannerItem: TPlannerItem;
  w: integer;
begin
  Result := nil;

  if FOwner.Sidebar.Orientation = soVertical then
    wo := FOwner.FGrid.ColWidthEx(ItemPos)
  else
    wo := FOwner.FGrid.RowHeightEx(ItemPos);

  for ItemIndex := 0 to Count - 1 do
  begin
    APlannerItem := Items[ItemIndex];

    if (APlannerItem.Visible) and (APlannerItem.ItemPos = ItemPos) and
       (APlannerItem.ItemBegin <= ItemBegin) and  (APlannerItem.ItemEnd > ItemBegin) and not
       (APlannerItem.Background and APlannerItem.AllowOverlap) and (InVisibleLayer(APlannerItem.Layer)) then
    begin
      if (APlannerItem.FConflicts > 1) then
        w := wo div APlannerItem.FConflicts
      else
        w := wo;

      if (ItemSubPos > APlannerItem.FConflictPos * w + APlannerItem.VMargin) and (ItemSubPos < (APlannerItem.FConflictPos + 1) * w - APlannerItem.VMargin - FOwner.FItemGap) then
      begin
        if FOwner.TrackOnly then
        begin
          if ItemSubPos < APlannerItem.FConflictPos * w + FOwner.TrackWidth then
          begin
            Result := APlannerItem;
            Break;
          end;
        end
        else
        begin
          Result := APlannerItem;
          Break;
        end;
      end;
    end;
  end;
end;

function TPlannerItems.FindBkgItem(ItemBegin, ItemEnd,
  ItemPos: integer): TPlannerItem;
begin
  Result := FindBkgPos(ItemBegin, ItemEnd, ItemPos);
end;

function TPlannerItems.FindBkgPos(ItemBegin, ItemPos, ItemSubPos: Integer): TPlannerItem;
var
  ItemIndex, w, wo, ig: Integer;
  APlannerItem: TPlannerItem;
begin
  Result := nil;

  if FOwner.Sidebar.Orientation = soVertical then
    wo := FOwner.FGrid.ColWidthEx(ItemPos)
  else
    wo := FOwner.FGrid.RowHeightEx(ItemPos);

  if FOwner.AllowBackgroundItemSelection then
    ig := 0
  else
    ig := FOwner.ItemGap;

  for ItemIndex := 0 to Self.Count - 1 do
  begin
    APlannerItem := Self.Items[ItemIndex];

    if (APlannerItem.ItemBegin <= ItemBegin) and (APlannerItem.ItemEnd > ItemBegin) and
       (APlannerItem.ItemPos = ItemPos) and (APlannerItem.Visible) and
       (APlannerItem.Background and APlannerItem.AllowOverlap) and (InVisibleLayer(APlannerItem.Layer)) then
    begin
      if APlannerItem.FConflicts > 1 then
        w := wo div APlannerItem.FConflicts
      else
        w := wo;

      if (ItemSubPos > APlannerItem.FConflictPos * w) and (ItemSubPos < (APlannerItem.FConflictPos + 1) * w - ig) then
      begin
        Result := APlannerItem;
        Break;
      end;
    end;
  end;
end;

function TPlannerItems.FindItemPosIdx(ItemBegin, ItemPos, ItemSubPos: Integer): TPlannerItem;
var
  ItemIndex: Integer;
  APlannerItem: TPlannerItem;
begin
  Result := nil;
  for ItemIndex := 0 to Self.Count - 1 do
  begin
    APlannerItem := Self.Items[ItemIndex];
    if (APlannerItem.ItemBegin <= ItemBegin) and (APlannerItem.ItemEnd > ItemBegin) and
       (APlannerItem.ItemPos = ItemPos) and (APlannerItem.Visible) and not
       (APlannerItem.Background and APlannerItem.AllowOverlap) and
       (APlannerItem.FConflictPos = ItemSubPos) and (InVisibleLayer(APlannerItem.Layer)) then
    begin
      Result := APlannerItem;
      Break;
    end;
  end;
end;

function TPlannerItems.FindItemIndex(ItemBegin, ItemPos, ItemSubIdx: Integer): TPlannerItem;
var
  ItemIndex: Integer;
  APlannerItem: TPlannerItem;
begin
  Result := nil;

  for ItemIndex := 0 to Count - 1 do
  begin
    APlannerItem := Items[ItemIndex];

    if (APlannerItem.ItemBegin <= ItemBegin) and (APlannerItem.ItemEnd > ItemBegin) and
       (APlannerItem.ItemPos = ItemPos) and (APlannerItem.FConflictPos = ItemSubIdx) and
       (APlannerItem.Visible) and not (APlannerItem.Background and APlannerItem.AllowOverlap) and
       (InVisibleLayer(APlannerItem.Layer)) then
    begin
      Result := APlannerItem;
      Break;
    end;
  end;
end;

function TPlannerItems.FindBackground(ItemBegin, ItemPos: Integer): TPlannerItem;
var
  ItemIndex: Integer;
  APlannerItem: TPlannerItem;
begin
  Result := nil;
  for ItemIndex := 0 to Self.Count - 1 do
  begin
    APlannerItem := Self.Items[ItemIndex];

    if (APlannerItem.ItemBegin <= ItemBegin) and (APlannerItem.ItemEnd > ItemBegin) and
       (APlannerItem.ItemPos = ItemPos) and (APlannerItem.AllowOverlap) and (APlannerItem.Visible) and
       (APlannerItem.Background) and (InVisibleLayer(APlannerItem.Layer)) then
    begin
      Result := APlannerItem;
      Break;
    end;
  end;
end;

function TPlannerItems.QueryItem(Item: TPlannerItem; ItemBegin, ItemPos: Integer): TPlannerItem;
var
  ItemIndex, StartIndex: Integer;
  APlannerItem: TPlannerItem;
begin
  Result := nil;
  if Assigned(Item) then
    StartIndex := Item.Index + 2
  else
    StartIndex := 1;

  for ItemIndex := StartIndex to Self.Count do
  begin
    APlannerItem := Self.Items[ItemIndex - 1];
    if (APlannerItem.ItemBegin <= ItemBegin) and (APlannerItem.ItemEnd > ItemBegin) and
       (APlannerItem.ItemPos = ItemPos) and (APlannerItem.Visible) and
       (InVisibleLayer(APlannerItem.Layer)) then
    begin
      Result := APlannerItem;
      Break;
    end;
  end;
end;

procedure TPlannerItems.SetCurrent(ItemCurrent: Integer);
var
  ItemIndex: Integer;
  APlannerItem: TPlannerItem;
begin
  for ItemIndex := 0 to Self.Count - 1 do
  begin
    APlannerItem := Self.Items[ItemIndex];
    APlannerItem.IsCurrent := (APlannerItem.ItemBegin <= ItemCurrent) and (APlannerItem.ItemEnd > ItemCurrent)
     and not APlannerItem.InHeader and APlannerItem.Planner.IsCurPos(APlannerItem.ItemPos);
  end;
end;

function TPlannerItems.FocusItem(ItemBegin, ItemPos, ItemSubPos: Integer; Control: Boolean): TPlannerItem;
var
  ItemIndex, w: Integer;
  APlannerItem: TPlannerItem;

begin
  Result := nil;
  FSelected := nil;

  for ItemIndex := 0 to Count - 1 do
  begin
    if FOwner.Sidebar.Orientation = soVertical then
      w := FOwner.FGrid.ColWidthEx(ItemPos)
    else
      w := FOwner.FGrid.RowHeightEx(ItemPos);

    APlannerItem := Self.Items[ItemIndex];

    if (APlannerItem.ItemBegin <= ItemBegin) and (APlannerItem.ItemEnd > ItemBegin) and
       (APlannerItem.ItemPos = ItemPos) and (APlannerItem.Visible) and not {APlannerItem.GetBkgSelect and not}
       (APlannerItem.Background and APlannerItem.AllowOverlap) and (InVisibleLayer(APlannerItem.Layer)) then
    begin
      if APlannerItem.FConflicts > 1 then
        w := w div APlannerItem.FConflicts;

      if (ItemSubPos > APlannerItem.FConflictPos * w) and (ItemSubPos < (APlannerItem.FConflictPos + 1) * w - FOwner.ItemGap) and (APlannerItem.IsSelectable) then
      begin
        Result := APlannerItem;
        {
        APlannerItem.Focus := True;

        if Control and APlannerItem.Selected then
          APlannerItem.Selected := False
        else
          APlannerItem.Selected := True;

        FSelected := APlannerItem;
        }
      end
      else
      begin
        APlannerItem.Focus := False;
        if not Control or not FOwner.MultiSelect then
          APlannerItem.Selected := False;
      end;
    end
    else
    begin
      APlannerItem.Focus := False;
      if not Control or not FOwner.MultiSelect then
        APlannerItem.Selected := False;
    end;
  end;

  if Assigned(Result) then
  begin
    APlannerItem := Result;
    APlannerItem.Focus := True;
    if Control and APlannerItem.Selected then
      APlannerItem.Selected := False
    else
    begin
      APlannerItem.Selected := True;
      if FOwner.AutoSelectLinkedItems and FOwner.MultiSelect then
        FOwner.SelectLinkedItems(APlannerItem);
    end;

    FSelected := APlannerItem;
  end;
end;

function TPlannerItems.FocusBkg(ItemBegin, ItemPos, ItemSubPos: Integer; Control: Boolean): TPlannerItem;
var
  ItemIndex, w: Integer;
  APlannerItem: TPlannerItem;

begin
  Result := nil;
  FSelected := nil;

  for ItemIndex := 0 to Count - 1 do
  begin
    if FOwner.Sidebar.Orientation = soVertical then
      w := FOwner.FGrid.ColWidthEx(ItemPos)
    else
      w := FOwner.FGrid.RowHeightEx(ItemPos);

    APlannerItem := Self.Items[ItemIndex];

    if (APlannerItem.ItemBegin <= ItemBegin) and (APlannerItem.ItemEnd > ItemBegin) and
       (APlannerItem.ItemPos = ItemPos) and (APlannerItem.Visible) and
       (APlannerItem.Background and APlannerItem.AllowOverlap) and (InVisibleLayer(APlannerItem.Layer)) then
    begin
      if APlannerItem.FConflicts > 1 then
        w := w div APlannerItem.FConflicts;

      if (ItemSubPos > APlannerItem.FConflictPos * w) and (ItemSubPos < (APlannerItem.FConflictPos + 1) * w) and (APlannerItem.IsSelectable) then
      begin
        Result := APlannerItem;
        {
         APlannerItem.Focus := True;

         if Control and APlannerItem.Selected then
         APlannerItem.Selected := False
         else
         APlannerItem.Selected := True;

         FSelected := APlannerItem;
         }
       end
       else
       begin
         APlannerItem.Focus := False;
         if not Control or not FOwner.MultiSelect then
           APlannerItem.Selected := False;
       end;
     end
     else
     begin
       APlannerItem.Focus := False;
       if not Control or not FOwner.MultiSelect then
         APlannerItem.Selected := False;
     end;
   end;

   if Assigned(Result) then
   begin
     APlannerItem := Result;
     APlannerItem.Focus := True;
     if Control and APlannerItem.Selected then
       APlannerItem.Selected := False
     else
     begin
       APlannerItem.Selected := True;
       if FOwner.AutoSelectLinkedItems and FOwner.MultiSelect then
         FOwner.SelectLinkedItems(APlannerItem);
     end;

     FSelected := APlannerItem;
  end;
end;


procedure TPlannerItems.UnSelect;
begin
  if Assigned(FSelected) then
  begin
    FSelected.Focus := False;
    FSelected.Selected := False;
    FSelected := nil;
  end;
  ClearLinks;
end;

procedure TPlannerItems.UnSelectAll;
var
  i: Integer;
begin
  for i := 0 to Count - 1 do
    with Items[i] do
    begin
      LinkSelect := False;
      Focus := False;
      Selected := False;
    end;
  FSelected := nil;
end;

function TPlannerItems.SelectNext: TPlannerItem;
var
  Idx: Integer;
begin
  if FSelected <> nil then
  begin
    FSelected.Focus := False;
    FSelected.Selected := False;
    Idx := FSelected.Index;
    while Idx + 1 < Self.Count do
    begin
      if not (Self.Items[Idx + 1].Background) then
      begin
        FSelected := Self.Items[Idx + 1];
        FSelected.Selected := True;
        Break;
      end
      else
        Inc(Idx);
    end;
    if (Idx + 1 = Self.Count) then
      FSelected := nil;
  end
  else
  begin
    if (Self.Count > 0) then
    begin
      FSelected := Self.Items[0];
      FSelected.Focus := True;
      FSelected.Selected := True;
    end;
  end;

  if Assigned(FSelected) then
    FSelected.Focus := True;
  Result := FSelected;
end;

function TPlannerItems.SelectPrev: TPlannerItem;
var
  Idx: Integer;
begin
  if FSelected <> nil then
  begin
    FSelected.Focus := False;
    FSelected.Selected := False;
    Idx := FSelected.Index;
    while Idx > 0 do
    begin
      if not Self.Items[Idx - 1].Background then
      begin
        FSelected := Self.Items[Idx - 1];
        FSelected.Selected := True;
        Break;
      end
      else
        Dec(Idx);
    end;

    if (Idx <= 0) then
      FSelected := nil;
  end
  else
  begin
    if Self.Count > 0 then
    begin
      FSelected := Self.Items[Self.Count - 1];
      FSelected.Selected := True;
    end;
  end;
  if Assigned(FSelected) then
    FSelected.Focus := True;
  Result := FSelected;
end;

function TPlannerItems.InVisibleLayer(Layer: Integer): Boolean;
begin
  Result := (FOwner.Layer = 0) or ((FOwner.Layer > 0) and (Layer and FOwner.Layer > 0));
end;

procedure TPlannerItems.SetItem(Index: Integer; value: TPlannerItem);
begin
  inherited SetItem(Index, value);
end;

procedure TPlannerItems.ClearPosition(Position: Integer);
var
  ItemIndex: Integer;
begin
  BeginUpdate;
  for ItemIndex := Count downto 1 do
  begin
    if Items[ItemIndex - 1].ItemPos = Position then
      Items[ItemIndex - 1].Free
  end;
  EndUpdate;
end;

procedure TPlannerItems.ClearLayer(Layer: Integer);
var
  ItemIndex: Integer;
begin
  BeginUpdate;
  for ItemIndex := Count downto 1 do
  begin
    if Items[ItemIndex - 1].Layer = Layer then
      Items[ItemIndex - 1].Free
  end;
  EndUpdate;
end;

procedure TPlannerItems.BeginUpdate;
begin
  inherited;
  Inc(FUpdateCount);
end;

procedure TPlannerItems.EndUpdate;
begin
  if FUpdateCount > 0 then
    Dec(FUpdateCount);
  if FUpdateCount = 0 then
  begin
    SetConflicts;
    FOwner.FGrid.UpdateNVI;
    FOwner.FGrid.Invalidate;
  end;
  inherited;
end;

procedure TPlannerItems.ResetUpdate;
var
  i: Integer;
begin
  if FUpdateCount > 0 then
    Dec(FUpdateCount);
  if FUpdateCount = 0 then
  begin
    SetConflicts;
    ClearRepaints;
    for i := 1 to Count do
      if Items[i - 1].FChanged then
        Items[i - 1].Repaint;
  end;
end;

procedure TPlannerItems.SetConflicts;
type
  tbp = record
    X, Y, Z: Byte;
  end;
  confarray = array of array of tbp;

var
  conf: confarray;
  i, j, k, M, n, mm, NumRows: Integer; flg: Boolean;

  function IsOverlapping(APlannerItem: TPlannerItem; ItemBegin: Integer): Boolean;
  begin
    Result := False;

    if (APlannerItem.ItemBegin <= ItemBegin) and (APlannerItem.ItemEnd > ItemBegin) and
       (APlannerItem.Visible) and not (APlannerItem.Background and APlannerItem.AllowOverlap) and
       (InVisibleLayer(APlannerItem.Layer)) then
    begin
      Result := True;
    end;
  end;

begin
  if FUpdateCount > 0 then
    Exit;

  if (csDestroying in FOwner.ComponentState) then
    Exit;

  if FOwner.FLinkUpdate then
    Exit;

  if Count = 0 then
  begin
    if FOwner.Footer.ShowCompletion and FOwner.Footer.Visible then
      FOwner.UpdateCompletion;

    if Assigned(FOwner.FOnConflictUpdate) then
      FOwner.FOnConflictUpdate(Self);
    Exit;
  end;

  if FOwner.CheckConflicts then
  begin

    for i := 1 to Count do
    begin
      with Items[i - 1] do
      begin
        FBeginExt := ItemBegin;
        FEndExt := ItemEnd;
        FChanged := False;
      end;
    end;

    //Clear counters of overlapping Items

    if FOwner.Sidebar.Orientation = soVertical then
    begin
      SetLength(conf, FOwner.FGrid.ColCount + 1, FOwner.FGrid.RowCount + 1);
      NumRows := FOwner.FGrid.RowCount + 1;
    end
    else
    begin
      SetLength(conf, FOwner.FGrid.RowCount + 1, FOwner.FGrid.ColCount + 1);
      NumRows := FOwner.FGrid.ColCount + 1;
    end;

    //Calculate worst-case item overlap count

    for i := 0 to Count - 1 do
    begin
      M := 0;
      if InVisibleLayer(Items[i].Layer) and Items[i].Visible and not
        (Items[i].Background and Items[i].AllowOverlap) then
      begin
        for j := 0 to Count - 1 do
        begin
          if (i <> j) and (Items[j].ItemPos = Items[i].ItemPos) then
          begin
            if FOwner.DrawPrecise then
            begin

            end
            else
            begin
              for k := Items[i].ItemBegin to Items[i].ItemEnd - 1 do
              begin
                if IsOverlapping(Items[j], k) then
                begin
                  if Items[j].FBeginExt < Items[i].FBeginExt then
                    Items[i].FBeginExt := Items[j].FBeginExt
                  else
                    Items[j].FBeginExt := Items[i].FBeginExt;

                  if Items[j].FEndExt > Items[i].FEndExt then
                    Items[i].FEndExt := Items[j].FEndExt
                  else
                    Items[j].FEndExt := Items[i].FEndExt;

                  Inc(M);
                  Break;
                end;
              end;
            end;
          end;
        end;
      end;

      Items[i].FChanged := Items[i].FConflicts <> M + 1;
      Items[i].FConflicts := M + 1;
    end;

    //Count. nr of overlapping Items per cell
    for i := 0 to Count - 1 do
    begin
      with Items[i] do
      begin
        if (FBeginExt >= 0) and (FEndExt >= 0) then
          if Visible and InVisibleLayer(Layer) and not (Background and AllowOverlap) then
            for j := FBeginExt to FEndExt - 1 do
            begin

              if (ItemPos < High(conf)) and (ItemPos >= 0) and (j < High(conf[ItemPos])) then
                if (Items[i].FConflicts > conf[ItemPos, j].X) then
                  conf[ItemPos, j].X := Items[i].FConflicts;
            end;
      end;
    end;

    //Assign Items conflicts & conflict positions
    for i := 0 to Count - 1 do begin with Items[i] do
      if Visible and InVisibleLayer(Layer) and not (Background and AllowOverlap) then
      begin
        M := 0; mm := 0;

        //get last assigned conflict position
        for j := ItemBegin to ItemEnd - 1 do
        begin
          if (ItemPos < High(conf)) and (ItemPos >= 0) and (j < High(conf[ItemPos])) then
          begin
            if (conf[ItemPos, j].Y > M) then
              M := conf[ItemPos, j].Y;

            if (conf[ItemPos, j].Z > mm) then
              mm := conf[ItemPos, j].Z;
          end;
        end;

        if mm = M then
          mm := 0;

        //get nr. of conflicts from extended zone
        n := 0;
        for j := FBeginExt to FEndExt - 1 do
          if (ItemPos < High(conf)) and (ItemPos >= 0) and (j < High(conf[ItemPos])) then
            if conf[ItemPos, j].X > n then
              n := conf[ItemPos, j].X;

       //scan ... if Assigned Position 0,1,2
       flg := (FConflicts <> n) or (FConflictPos <> M);

       FConflicts := n;

       if M < FConflicts then
       begin
         FChanged := FChanged or (FConflictPos <> M);
         FConflictPos := M
       end
       else
       begin
         FChanged := FChanged or (FConflictPos <> mm);
         FConflictPos := mm;
       end;

       if (M >= FConflicts) then
       begin
         mm := mm + 1;
         for j := Max(0, ItemBegin) to Max(0, ItemEnd - 1) do
         begin
           if (ItemPos < High(conf)) and (ItemPos >= 0) and (j < High(conf[ItemPos])) then
           begin
             conf[ItemPos, j].Z := mm;
           end;
         end;
       end;

       if M < FConflicts then
         M := M + 1;

       for j := Max(0, ItemBegin) to Max(0, ItemEnd - 1) do
       begin
         if (ItemPos < High(conf)) and (ItemPos >= 0) and (j < High(conf[ItemPos])) then
           conf[ItemPos, j].Y := M;
       end;

       if flg then
         Repaint;

      end;
    end;

    //If better than worst case position found, optimize
    for i := 1 to Count do
    begin
      with Items[i - 1] do
      begin
        M := 0;
        for j := 0 to NumRows - 1 do
          if (ItemPos < High(conf)) and (ItemPos >= 0) and (j < High(conf[ItemPos])) then
            if conf[ItemPos, j].Y > M then
              M := conf[ItemPos, j].Y;

        if FConflicts > M then
        begin
          FChanged := FChanged or (FConflicts <> M);
          FConflicts := M;
          Repaint;
        end;
      end;
    end;
  end
  else
  begin
    for i := 1 to Count do
    begin
      with Items[i - 1] do
      begin
        FConflicts := 1;
        FConflictPos := 0;
      end;
    end;

  end;

  if FOwner.Footer.ShowCompletion and FOwner.Footer.Visible then
  begin
    FOwner.UpdateCompletion;
  end;

  if Assigned(FOwner.FOnConflictUpdate) then
    FOwner.FOnConflictUpdate(Self);
end;

procedure TPlannerItems.ClearConflicts;
var
  ItemIndex: Integer;
begin
  for ItemIndex := 0 to Count - 1 do
  begin
    Items[ItemIndex].FConflictPos := 0;
    Items[ItemIndex].FConflicts := 0;
  end;
end;

function TPlannerItems.NumConflicts(var ItemBegin, ItemEnd: Integer; ItemPos: Integer): Integer;
var
  ItemIndex: Integer;
  APlannerItem: TPlannerItem;
begin
  Result := 0;
  for ItemIndex := 0 to Self.Count - 1 do
  begin
    APlannerItem := Self.Items[ItemIndex];
    if (((APlannerItem.ItemBegin <= ItemBegin) and (APlannerItem.ItemEnd > ItemBegin)) or
       ((APlannerItem.ItemBegin < ItemEnd) and (APlannerItem.ItemEnd >= ItemEnd)) or
       ((ItemBegin < APlannerItem.ItemEnd) and (ItemEnd >= APlannerItem.ItemEnd)) or
       ((ItemBegin <= APlannerItem.ItemBegin) and (ItemEnd > APlannerItem.ItemBegin))) and
       (APlannerItem.ItemPos = ItemPos) and (APlannerItem.Visible) and (InVisibleLayer(APlannerItem.Layer)) then
    begin
      Inc(Result);
      if APlannerItem.ItemBegin < ItemBegin then
        ItemBegin := APlannerItem.ItemBegin;
      if APlannerItem.ItemEnd > ItemEnd then
        ItemEnd := APlannerItem.ItemEnd;
    end;
  end;

  FOwner.DoPositionAutoSize;
end;

procedure TPlannerItems.ResolveLinks;
var
  i, j: Integer;
begin
  for i := 1 to Count do
  begin
    if (Items[i - 1].LinkedDBKey <> '') then
    begin
      Items[i - 1].LinkedItem := nil;

      for j := 1 to Count do
      begin
        if (Items[i - 1].LinkedDBKey = Items[j - 1].DBKey) then
          Items[i - 1].LinkedItem := Items[j - 1];
      end;
    end;
  end;
end;

procedure TPlannerItems.CopyToClipboard;
var
  Clipboard: TClipboard;
  PlannerItemIO: TPlannerItemIO;
  MemStream: TMemoryStream;
  Data: THandle;
  DataPtr: Pointer;
begin
  Clipboard := TClipboard.Create;
  if Assigned(Selected) then
  begin
    Selected.ItemBegin := Selected.ItemBegin;
    Selected.ItemEnd := Selected.ItemEnd;
    Selected.DBTag := MakeLong(Selected.ItemBeginPrecis, Selected.ItemEndPrecis);

    PlannerItemIO := TPlannerItemIO.CreateItem(Self);
    PlannerItemIO.Item.Assign(Selected);

    MemStream := TMemoryStream.Create;
    try
      MemStream.WriteComponent(PlannerItemIO);

      Clipboard.Open;
      try
        Data := GlobalAlloc(GMEM_MOVEABLE + GMEM_DDESHARE, MemStream.Size);
        try
          DataPtr := GlobalLock(Data);
          try
            Move(MemStream.Memory^, DataPtr^, MemStream.Size);
            Clipboard.Clear;
            SetClipboardData(CF_PLANNERITEM, Data);
          finally
            GlobalUnlock(Data);
          end;
        except
          GlobalFree(Data);
          raise;
       end;
      finally
        Clipboard.Close;
      end;
    finally
      MemStream.Free;
    end;
    PlannerItemIO.Free;
  end;
  Clipboard.Free;
end;

procedure TPlannerItems.CutToClipboard;
begin
  CopyToClipboard;
  if Assigned(Selected) then
    FOwner.FreeItem(Selected);
end;

function TPlannerItems.PasteItem(Position: Boolean; Size: Boolean): TPlannerItem;
var
  Clipboard: TClipboard;
  PlannerItemIO: TPlannerItemIO;
  MemStream: TMemoryStream;
  Data: THandle;
  DataPtr: Pointer;
  plIt: TPlannerItem;
  delta, EP: Integer;

begin
  Result := nil;
  Clipboard := TClipboard.Create;
  Clipboard.Open;

  Data := 0;

  try
    Data := GetClipboardData(CF_PLANNERITEM);
    if Data = 0 then
      Exit;

    DataPtr := GlobalLock(Data);
    if DataPtr = nil then
      Exit;

    try
      MemStream := TMemoryStream.Create;
      MemStream.WriteBuffer(DataPtr^, GlobalSize(Data));
      MemStream.Position := 0;
      PlannerItemIO := TPlannerItemIO.CreateItem(Self);
      try
        MemStream.ReadComponent(PlannerItemIO);
        with PlannerItemIO.Item do
        begin
          EP := 0;
          if Position then
          begin
            delta := Hiword(DBTag) - Loword(DBTag);

            ItemBegin := FOwner.SelItemBegin;
            if Size then
            begin
              ItemEndPrecis := ItemBeginPrecis + delta;
              if ItemEnd > FPlanner.Display.DisplayEnd then
              begin
                EP := ItemEnd - FPlanner.Display.DisplayEnd - 1;
                ItemEnd := FPlanner.Display.DisplayEnd + 1;
              end;
            end
            else
              ItemEnd := FOwner.SelItemEnd;

            ItemPos := FOwner.SelPosition;
          end
          else
          begin
            ItemBeginPrecis := Loword(DBTag);
            ItemEndPrecis := Hiword(DBTag);
          end;
        end;

        plIt := FOwner.CreateItem;
        plIt.Assign(PlannerItemIO.Item);
        plIt.EndOffset := EP;
        plIt.Update;
        Result := plIt;

      finally
        PlannerItemIO.Free;
        MemStream.Free;
      end;
    finally
    end;
  finally
    GlobalUnlock(Data);
  end;

  Clipboard.Close;
  Clipboard.Free;
end;

procedure TPlannerItems.PasteFromClipboard;
begin
  PasteItem(False, True);
end;

procedure TPlannerItems.PasteFromClipboardAtPos;
begin
  PasteItem(True, False);
end;

function TPlannerItems.PasteFromClipboardAtXY: TPlannerItem;
begin
  Result := PasteItem(True, True);
end;

procedure TPlannerItems.OffsetItems(Offset: Integer);
var
  ItemIndex: Integer;
begin
  BeginUpdate;
  try
    for ItemIndex := 0 to Count - 1 do
    begin
      Items[ItemIndex].ItemBegin := Items[ItemIndex].ItemBegin + Offset;
      Items[ItemIndex].ItemEnd := Items[ItemIndex].ItemEnd + Offset;
    end;
  finally
    EndUpdate;
  end;
end;

procedure TPlannerItems.MoveAll(DeltaPos, DeltaBegin: Integer);
var
  ItemIndex: Integer;
begin
  for ItemIndex := 0 to Count - 1 do
  begin
    Items[ItemIndex].ItemBegin := Clip(Items[ItemIndex].ItemBegin + DeltaBegin, FOwner.Display.DisplayStart, FOwner.Display.DisplayEnd);
    Items[ItemIndex].ItemEnd := Clip(Items[ItemIndex].ItemEnd + DeltaBegin, FOwner.Display.DisplayStart, FOwner.Display.DisplayEnd);
    Items[ItemIndex].ItemPos := Clip(Items[ItemIndex].ItemPos + DeltaPos, FOwner.Display.DisplayStart, FOwner.Display.DisplayEnd);
  end;
end;

procedure TPlannerItems.MoveSelected(DeltaPos, DeltaBegin: Integer);
var
  ItemIndex: Integer;
begin
  for ItemIndex := 0 to Count - 1 do
  begin
    if Items[ItemIndex].Selected and not Items[ItemIndex].Focus then
    begin
      Items[ItemIndex].ItemBegin := Clip(Items[ItemIndex].ItemBegin + DeltaBegin, FOwner.Display.DisplayStart, FOwner.Display.DisplayEnd);
      Items[ItemIndex].ItemEnd := Clip(Items[ItemIndex].ItemEnd + DeltaBegin, FOwner.Display.DisplayStart, FOwner.Display.DisplayEnd);
      Items[ItemIndex].ItemPos := Clip(Items[ItemIndex].ItemPos + DeltaPos, FOwner.Display.DisplayStart, FOwner.Display.DisplayEnd);
    end;
  end;
end;

procedure TPlannerItems.SizeAll(DeltaStart, DeltaEnd: Integer);
var
  ItemIndex: Integer;
begin
  for ItemIndex := 0 to Count - 1 do
  begin
    Items[ItemIndex].ItemBegin := Clip(Items[ItemIndex].ItemBegin + DeltaStart, FOwner.Display.DisplayStart, FOwner.Display.DisplayEnd);
    Items[ItemIndex].ItemEnd := Clip(Items[ItemIndex].ItemEnd + DeltaEnd, FOwner.Display.DisplayStart, FOwner.Display.DisplayEnd);
  end;
end;

procedure TPlannerItems.SizeSelected(DeltaStart, DeltaEnd: Integer);
var
  ItemIndex: Integer;
begin
  for ItemIndex := 0 to Count - 1 do
  begin
    if Items[ItemIndex].Selected and not Items[ItemIndex].Focus then
    begin
      Items[ItemIndex].ItemBegin := Clip(Items[ItemIndex].ItemBegin + DeltaStart, FOwner.Display.DisplayStart, FOwner.Display.DisplayEnd);
      Items[ItemIndex].ItemEnd := Clip(Items[ItemIndex].ItemEnd + DeltaEnd, FOwner.Display.DisplayStart, FOwner.Display.DisplayEnd);
    end;
  end;
end;

procedure TPlannerItems.ClearRepaints;
var
  ItemIndex: Integer;
begin
  for ItemIndex := 0 to Count - 1 do
    Items[ItemIndex].Repainted := False;
end;

function TPlannerItems.HeaderFirst(ItemPos: Integer): TPlannerItem;
var
  ItemIndex: Integer;
  APlannerItem: TPlannerItem;
begin
  Result := nil;
  FFindIndex := 1;

  for ItemIndex := 1 to Count do
  begin
    APlannerItem := Items[ItemIndex - 1];
    if (APlannerItem.ItemPos = ItemPos) and (APlannerItem.InHeader) and InVisibleLayer(APlannerItem.Layer) then
    begin
      Result := APlannerItem;
      FFindIndex := ItemIndex + 1;
      Break;
    end;
  end;
end;

function TPlannerItems.HeaderNext(ItemPos: Integer): TPlannerItem;
var
  ItemIndex: Integer;
  APlannerItem: TPlannerItem;
begin
  Result := nil;
  for ItemIndex := FFindIndex to Count do
  begin
    APlannerItem := Items[ItemIndex - 1];
    if (APlannerItem.ItemPos = ItemPos) and (APlannerItem.FInHeader)
       and InVisibleLayer(APlannerItem.Layer) then
    begin
      Result := APlannerItem;
      FFindIndex := ItemIndex + 1;
      Break;
    end;
  end;
end;

procedure TPlannerItems.ClearAll;
begin
  Clear;
  Selected := nil;
  FOwner.Invalidate;
end;

procedure TPlannerItems.ClearDB;
var
  i: Integer;
begin
  i := 0;
  while i < Count do
  begin
    if not Items[i].NonDBItem then
      Items[i].Free
    else
      Inc(i);
  end;
end;

procedure TPlannerItems.GetTimeTags;
var
  i: Integer;
begin
  if not FOwner.FStreamPersistentTime then
    Exit;

  for i := 1 to Count do
    Items[i - 1].GetTimeTag;
end;

procedure TPlannerItems.SetTimeTags;
var
  i: Integer;
begin
  for i := 1 to Count do
    Items[i - 1].SetTimeTag;
end;

function TPlannerItems.FindKey(DBKey: string): TPlannerItem;
var
  i: Integer;
begin
  Result := Nil;

  for i := 1 to Count do
  begin
    if Items[i - 1].DBKey = DBKey then
    begin
      Result := Items[i - 1];
      Break;
    end;
  end;
end;

procedure TPlannerItems.UpdateLinks(APlannerItem: TPlannerItem);
begin
  if APlannerItem.LinkUpdating then
    Exit;

  APlannerItem.LinkUpdating := True;

  if Assigned(APlannerItem.LinkedItem) then
  begin
    APlannerItem.LinkedItem.LinkSelect := True;
    UpdateLinks(APlannerItem.LinkedItem);
  end;

  APlannerItem.LinkUpdating := False;
end;

procedure TPlannerItems.ClearLinks;
var
  i: Integer;
begin
  for i := 1 to Count do
    Items[i - 1].LinkSelect := False;
end;

procedure TPlannerItems.Select(Item: TPlannerItem);
begin
  UnSelect;
  Item.Focus := True;
  Item.Selected := True;
  FSelected := Item;
  FOwner.ItemSelected(Item);
end;

function TPlannerItems.MatchItem(Item: TPlannerItem; s: string; Param: TFindTextParams): Boolean;
var
  SrchText: string;

begin
  Result := False;

  if fnCaptionText in Param then
  begin
    SrchText := Item.CaptionText;

    if fnIgnoreHTMLTags in Param then
      SrchText := HTMLStrip(SrchText);

    if not (fnMatchCase in Param) then
    begin
      SrchText := AnsiUpperCase(SrchText);
      s := AnsiUpperCase(s);
    end;

    if fnMatchFull in Param then
      Result := (s = SrchText)
    else
      if fnMatchStart in Param then
        Result := Pos(s, SrchText) = 1
      else
        if fnMatchRegular in Param then
          Result := MatchStr(s, SrchText, fnMatchCase in Param)
        else
          Result := Pos(s, SrchText) > 0;
  end;

  if Result then
    Exit;

  if fnText in Param then
  begin
    SrchText := Item.Text.Text;

    if fnIgnoreHTMLTags in Param then
      SrchText := HTMLStrip(SrchText);

    if not(fnMatchCase in Param) then
    begin
      SrchText := AnsiUpperCase(SrchText);
      s := AnsiUpperCase(s);
    end;

    if fnMatchFull in Param then
      Result := (s = SrchText)
    else
      if fnMatchStart in Param then
        Result := Pos(s, SrchText) = 1
      else
        if fnMatchRegular in Param then
          Result := MatchStr(s, SrchText, fnMatchCase in Param)
        else
          Result := Pos(s, SrchText) > 0;
  end;
end;

function TPlannerItems.FindText(StartItem: TPlannerItem; s: string; Param: TFindTextParams): TPlannerItem;
var
  i: Integer;

begin
  Result := nil;
  if Count = 0 then
    Exit;

  if not (fnBackward in Param) then
  begin
    i := 0;

    if Assigned(StartItem) then
    begin
      while i < Count do
      begin
        if Items[i] = StartItem then
          Break
        else
          Inc(i);
      end;

      if i < Count then
        Inc(i)
      else
        i := 0;
    end;

    while i < Count do
    begin
      if MatchItem(Items[i], s, Param) then
      begin
        Result := Items[i];
        if fnAutoGoto in Param then
        begin
          Items[i].ScrollInView;
          Items[i].SetFocus(True);
          Items[i].Selected := True;
        end;
        Break;
      end
      else
        Inc(i);
    end;
  end
  else
  begin
    i := Count - 1;

    if Assigned(StartItem) then
    begin
      while i > 0 do
      begin
        if Items[i] = StartItem then
          Break
        else
          Dec(i);
      end;

      if i > 0 then
        Dec(i)
      else
        i := Count - 1;
    end;

    while i > 0 do
    begin
      if MatchItem(Items[i], s, Param) then
      begin
        Result := Items[i];
        if fnAutoGoto in Param then
        begin
          Items[i].ScrollInView;
          Items[i].SetFocus(True);
          Items[i].Selected := True;
        end;
        Break;
      end
      else
        Dec(i);
    end;
  end;
end;

procedure TPlannerItems.MoveLinks(APlannerItem: TPlannerItem);
begin
  if not Assigned(APlannerItem) then
    Exit;

  APlannerItem.LinkUpdating := True;
  if Assigned(APlannerItem.LinkedItem) and (APlannerItem.LinkedItem.FLinkType <> ltLinkNone) then
  begin
    if not APlannerItem.LinkedItem.LinkUpdating then
    begin
      APlannerItem.LinkUpdating := True;
      APlannerItem.LinkedItem.LinkUpdating := True;
      FOwner.ItemMoved(APlannerItem.LinkedItem, 0, 0, 0, APlannerItem.LinkedItem.ItemBegin, APlannerItem.LinkedItem.ItemEnd, APlannerItem.LinkedItem.ItemPos);
      MoveLinks(APlannerItem.LinkedItem);
    end;
  end;
  APlannerItem.LinkUpdating := False;
end;

procedure TPlannerItems.SizeLinks(APlannerItem: TPlannerItem);
begin
  if not Assigned(APlannerItem) then
    Exit;

  APlannerItem.LinkUpdating := True;
  if Assigned(APlannerItem.LinkedItem) and (APlannerItem.LinkedItem.FLinkType <> ltLinkNone) then
  begin
    if not APlannerItem.LinkedItem.LinkUpdating then
    begin
      APlannerItem.LinkUpdating := True;
      APlannerItem.LinkedItem.LinkUpdating := True;
      FOwner.ItemSized(APlannerItem.LinkedItem, 0, 0, APlannerItem.LinkedItem.ItemBegin, APlannerItem.LinkedItem.ItemEnd);
      SizeLinks(APlannerItem.LinkedItem);
    end;
  end;
  APlannerItem.LinkUpdating := False;
end;

function TPlannerItems.MaxItemsInPos(Position: Integer): Integer;
var
  i, M: Integer;
  APlannerItem: TPlannerItem;
begin
  M := 1;
  for i := 1 to Count do
  begin
    APlannerItem := Items[i - 1];

    if (APlannerItem.ItemPos = Position) and (APlannerItem.Visible) and
       (InVisibleLayer(APlannerItem.Layer)) then
    begin
      if (APlannerItem.Conflicts > M) then
        M := APlannerItem.Conflicts;
    end;
  end;
  Result := M;
end;

function TPlannerItems.ItemsAtCell(ItemBegin, ItemEnd, ItemPos: Integer): Integer;
begin
  Result := NumItemPos(ItemBegin, ItemEnd, ItemPos).X;
end;

function TPlannerItems.ItemsAtIndex(Idx: Integer): Integer;
var
  APlannerItem: TPlannerItem;
  i: Integer;
begin
  Result := 0;

  for i := 1 to Count do
  begin
    APlannerItem := Items[i - 1];
    if (APlannerItem.ItemBegin <= Idx) and (APlannerItem.ItemEnd > Idx) and APlannerItem.Visible
      and InVisibleLayer(APlannerItem.Layer) then
      Result := Result + 1;
  end;
end;

function TPlannerItems.ItemsAtPosition(Pos: Integer): Integer;
var
  APlannerItem: TPlannerItem;
  i: Integer;
begin
  Result := 0;

  for i := 1 to Count do
  begin
    APlannerItem := Items[i - 1];
    if (APlannerItem.ItemPos = Pos) and APlannerItem.Visible
      and InVisibleLayer(APlannerItem.Layer) then
      Result := Result + 1;
  end;
end;

function TPlannerItems.GetItemClass: TCollectionItemClass;
begin
  Result := TPlannerItem;
end;

procedure TPlannerItems.ItemChanged(Item: TPlannerItem);
var
  i: Integer;

begin
  if Assigned(FOwner.OnItemUpdate) then
    FOwner.OnItemUpdate(Self);

  if FChanging then
    Exit;

  if Item.ParentIndex = -1 then
    Exit;

  FChanging := True;

  for i := 1 to Count do
  begin
    if (Items[i - 1] <> Item) and (Item.ParentIndex = Items[i - 1].ParentIndex) then
    begin
      Items[i - 1].AssignEx(Item);
    end;
  end;

  FChanging := False;
end;

function TPlannerItems.GetSelCount: Integer;
var
  i: Integer;
begin
  Result := 0;
  for i := 1 to Count do
  begin
    if Items[i - 1].Selected then
      Inc(Result);
  end;
end;

{ TPlannerMemo }

procedure TPlannerMemo.DoEnter;
begin
  inherited;
end;

procedure TPlannerMemo.DoExit;
var
  s: string;
begin
  inherited;

  if Assigned(Lines) and Assigned(PlannerItem) then
  begin
    s := Lines.Text;
    PlannerItem.Text.Text := s;
    if FPlanner.EditMode then
      PlannerItem.FPlanner.ItemEdited(PlannerItem);
  end;

  Visible := False;
  Parent.SetFocus;
end;

procedure TPlannerMemo.WMPaste(var Msg: TMessage);
var
  s: string;
begin
  inherited;
  if Assigned(FPlannerItem.FPlanner.OnItemClipboardAction) then
  begin
    s := Lines.Text;
    FPlannerItem.FPlanner.OnItemClipboardAction(FPlannerItem.FPlanner, FPlannerItem, itPaste, s);
    if s <> Lines.Text then
      Lines.Text := s;
  end;
end;

procedure TPlannerMemo.WMCopy(var Msg: TMessage);
var
  s: string;
begin
  inherited;
  if Assigned(FPlannerItem.FPlanner.OnItemClipboardAction) then
  begin
    s := Lines.Text;
    FPlannerItem.FPlanner.OnItemClipboardAction(FPlannerItem.FPlanner, FPlannerItem, itCopy, s);
    if s <> Lines.Text then
      Lines.Text := s;
  end;
end;

procedure TPlannerMemo.WMCut(var Msg: TMessage);
var
  s: string;
begin
  inherited;
  if Assigned(FPlannerItem.FPlanner.OnItemClipboardAction) then
  begin
    s := Lines.Text;
    FPlannerItem.FPlanner.OnItemClipboardAction(FPlannerItem.FPlanner, FPlannerItem, itCut, s);
    if s <> Lines.Text then
      Lines.Text := s;
  end;
end;

procedure TPlannerMemo.KeyDown(var Key: Word; Shift: TShiftState);
begin
  inherited;
  if Key = VK_ESCAPE then
  begin
    Self.Lines.Assign(PlannerItem.Text);
    PlannerItem.FPlanner.SetFocus;
  end;
end;

procedure TPlannerMemo.StopEdit;
var
  s: string;
begin
  inherited;
  if Assigned(Lines) and Assigned(PlannerItem) then
  begin
    s := Lines.Text;
    PlannerItem.Text.Text := s;
    PlannerItem.FPlanner.ItemEdited(PlannerItem);
  end;
  Visible := False;
end;

procedure TPlannerMemo.DblClick;
begin
  inherited;
  if Assigned(FPlanner.OnItemDblClick) then
    FPlanner.OnItemDblClick(FPlanner, FPlannerItem);
end;

{$IFNDEF DELPHI_UNICODE}
{ TPlannerUniMemo }

procedure TPlannerUniMemo.DoEnter;
begin
  inherited;
end;

procedure TPlannerUniMemo.DoExit;
begin
  inherited;
  if Assigned(PlannerItem) then
  begin
    PlannerItem.WideText := Text;
    PlannerItem.FPlanner.ItemEdited(PlannerItem);
  end;
  Visible := False;
  Parent.SetFocus;
end;

procedure TPlannerUniMemo.WMPaste(var Msg: TMessage);
{
var
  s: string;
}
begin
  inherited;
  {
  if Assigned(FPlannerItem.FPlanner.OnItemClipboardAction) then
  begin
    s := Lines.Text;
    FPlannerItem.FPlanner.OnItemClipboardAction(FPlannerItem.FPlanner,FPlannerItem,itPaste,s);
    if s <> Lines.Text then
      Lines.Text := s;
  end;
  }
end;

procedure TPlannerUniMemo.WMCopy(var Msg: TMessage);
{
var
  s:string;
}
begin
  inherited;
  {
  if Assigned(FPlannerItem.FPlanner.OnItemClipboardAction) then
  begin
    s := Lines.Text;
    FPlannerItem.FPlanner.OnItemClipboardAction(FPlannerItem.FPlanner,FPlannerItem,itCopy,s);
    if s <> Lines.Text then
      Lines.Text := s;
  end;
  }
end;

procedure TPlannerUniMemo.WMCut(var Msg: TMessage);
{
var
  s:string;
}
begin
  inherited;
  {
  if Assigned(FPlannerItem.FPlanner.OnItemClipboardAction) then
  begin
    s := Lines.Text;
    FPlannerItem.FPlanner.OnItemClipboardAction(FPlannerItem.FPlanner,FPlannerItem,itCut,s);
    if s <> Lines.Text then
      Lines.Text := s;
  end;
  }
end;

procedure TPlannerUniMemo.KeyDown(var Key: Word; Shift: TShiftState);
begin
  inherited;
  if Key = VK_ESCAPE then
  begin
    Text := PlannerItem.WideText;
    PlannerItem.FPlanner.SetFocus;
  end;
end;

procedure TPlannerUniMemo.DblClick;
begin
  inherited;
  if Assigned(FPlanner.OnItemDblClick) then
    FPlanner.OnItemDblClick(FPlanner, FPlannerItem);
end;
{$ENDIF}
{ TPlannerMaskEdit }

procedure TPlannerMaskEdit.DoExit;
begin
  inherited;
  if Assigned(PlannerItem) then
  begin
    PlannerItem.Text.Text := Self.Text;
    PlannerItem.FPlanner.ItemEdited(PlannerItem);
  end;
  Self.Visible := False;
  Self.Parent.SetFocus;
end;

procedure TPlannerMaskEdit.KeyDown(var Key: Word; Shift: TShiftState);
begin
  inherited;
  if Key = VK_ESCAPE then
  begin
    Self.Text := PlannerItem.Text[0];
    PlannerItem.FPlanner.SetFocus;
  end;
end;

procedure TPlannerMaskEdit.StopEdit;
begin
  inherited;
  if Assigned(PlannerItem) then
  begin
    PlannerItem.Text.Text := Text;
    PlannerItem.FPlanner.ItemEdited(PlannerItem);
  end;
  Visible := False;
end;

procedure TPlannerMaskEdit.WMPaste(var Msg: TMessage);
var
  s: string;
begin
  inherited;
  if Assigned(FPlannerItem.FPlanner.OnItemClipboardAction) then
  begin
    s := Text;
    FPlannerItem.FPlanner.OnItemClipboardAction(FPlannerItem.FPlanner, FPlannerItem, itPaste, s);
    if s <> Text then
      Text := s;
  end;
end;

procedure TPlannerMaskEdit.WMCopy(var Msg: TMessage);
var
  s: string;
begin
  inherited;
  if Assigned(FPlannerItem.FPlanner.OnItemClipboardAction) then
  begin
    s := Text;
    FPlannerItem.FPlanner.OnItemClipboardAction(FPlannerItem.FPlanner, FPlannerItem, itCopy, s);
    if s <> Text then
      Text := s;
  end;
end;

procedure TPlannerMaskEdit.WMCut(var Msg: TMessage);
var
  s: string;
begin
  inherited;
  if Assigned(FPlannerItem.FPlanner.OnItemClipboardAction) then
  begin
    s := Text;
   FPlannerItem.FPlanner.OnItemClipboardAction(FPlannerItem.FPlanner, FPlannerItem, itCut, s);
   if s <> Text then
     Text := s;
  end;
end;

{ TPlannerHeader }

constructor TPlannerHeader.Create(AOwner: TCustomPlanner);
begin
  inherited Create;
  FOwner := AOwner;
  FCaptions := TPlannerStringList.Create;
  FGroupCaptions := TPlannerStringList.Create;
  FHeight := 32;
  FFont := TFont.Create;
  FGroupFont := TFont.Create;
  FFont.OnChange := FontChanged;
  FGroupFont.OnChange := GroupFontChanged;
  FCaptions.OnChange := ItemsChanged;
  FGroupCaptions.OnChange := ItemsChanged;
  FColor := clBtnFace;
  FColorTo := clWhite;
  FItemColor := clGray;
  FReadOnly := True;
  FFlat := False;
  FTextHeight := 32;
  FItemHeight := 32;
  FLineColor := clGray;
  FVisible := True;
  FResizeAll := True;
  FActiveColor := clNone;
  FActiveColorTo := clNone;
  //FWideCaptions := TWideStrings.Create;
  //FWideGroupCaptions := TWideStrings.Create;
  FGroupSpan := TPlannerIntList.Create(nil);
  FCustomGroups := TGroupCollection.Create(Self, TGroupCollectionItem);
  FCustomGroups.OnChange := CustomGroupChange;
  FHeaderCustomColor := ccAll;
end;

destructor TPlannerHeader.Destroy;
begin
  //FWideCaptions.Free;
  //FWideGroupCaptions.Free;
  FGroupSpan.Free;
  FCustomGroups.Free;
  FCaptions.Free;
  FGroupCaptions.Free;
  FGroupFont.Free;
  FFont.Free;
  inherited Destroy;
end;

(*
procedure TPlannerHeader.SetWideCaptions(const Value: TWideStrings);
begin
  FWideCaptions.Assign(Value);
end;

procedure TPlannerHeader.SetWideGroupCaptions(const Value: TWideStrings);
begin
  FWideGroupCaptions.Assign(Value);
end;
*)

procedure TPlannerHeader.SetAlignment(const value: TAlignment);
begin
  FAlignment := value;
  FOwner.FHeader.Alignment := value;
end;

procedure TPlannerHeader.SetCaptions(const value: TPlannerStringList);
begin
  if Assigned(value) then
    FCaptions.Assign(value);
  ItemsChanged(Self);
end;

procedure TPlannerHeader.SetImages(const value: TImageList);
begin
  FImages := value;
  FOwner.FHeader.Images := value;
end;

procedure TPlannerHeader.SetImagePosition(const value: TImagePosition);
begin
  FImagePosition := value;
  FOwner.FHeader.ImagePosition := value;
end;

procedure TPlannerHeader.ItemsChanged(Sender: TObject);
var
  SectionIndex, SectionWidth: Integer;
begin
  if (FOwner.FHeader.Sections.Count = 0) then
    Exit;
  SectionIndex := 0;
  while
//(SectionIndex < FCaptions.Count) and
  (SectionIndex < FOwner.FHeader.Sections.Count) do
  begin
    SectionWidth := FOwner.FHeader.SectionWidth[SectionIndex];
    if (SectionIndex < FCaptions.Count) then
      FOwner.FHeader.Sections[SectionIndex] := FCaptions.Strings[SectionIndex]
    else
      FOwner.FHeader.Sections[SectionIndex] := '';

    FOwner.FHeader.SectionWidth[SectionIndex] := SectionWidth;
    Inc(SectionIndex);
  end;
end;

procedure TPlannerHeader.FontChanged(Sender: TObject);
begin
  FOwner.FHeader.Font.Assign(FFont);
end;

procedure TPlannerHeader.GroupFontChanged(Sender: TObject);
begin
  FOwner.FHeader.Invalidate;
end;

procedure TPlannerHeader.SetFont(const value: TFont);
begin
  FFont.Assign(value);
  FOwner.FHeader.Font.Assign(value);
end;

procedure TPlannerHeader.SetGroupHeight(const value: Integer);
begin
  if (FGroupHeight <> value) then
  begin
    FGroupHeight := value;
    FOwner.FHeader.Invalidate;
  end;
end;

procedure TPlannerHeader.SetGroupFont(const value: TFont);
begin
  FGroupFont.Assign(value);
  FOwner.FHeader.Invalidate;
end;

procedure TPlannerHeader.SetColor(const value: TColor);
begin
  if (FColor <> value) then
  begin
    FColor := value;
    FOwner.FHeader.Color := value;
  end;
end;

procedure TPlannerHeader.SetHeight(const value: Integer);
begin
  FHeight := value;
  UpdateHeights;
  FOwner.UpdateSizes;

  if (FOwner.PositionWidth = 0) then
  begin
    FOwner.FNoPositionSize := False;
    FOwner.FGrid.UpdatePositions;
  end;
end;

procedure TPlannerHeader.SetVisible(const value: Boolean);
begin
  if (FVisible <> value) then
  begin
    FVisible := value;
    if FVisible then
    begin
      FOwner.Header.Color := Color;
      FOwner.Header.Flat := Flat;
    end;
    FOwner.UpdateSizes;
  end;
end;

procedure TPlannerHeader.SetFlat(const value: Boolean);
begin
  FFlat := value;
  FOwner.FHeader.Flat := value;
  FOwner.FGrid.UpdatePositions;
end;

procedure TPlannerHeader.SetVAlignment(const value: TVAlignment);
begin
  FVAlignment := value;
  FOwner.FHeader.VAlignment := value;
end;

function TPlannerHeader.GetDragDrop: Boolean;
begin
  Result := FOwner.FHeader.SectionDragDrop;
end;

procedure TPlannerHeader.SetDragDrop(const value: Boolean);
begin
  FOwner.FHeader.SectionDragDrop := value;
end;

procedure TPlannerHeader.SetReadOnly(const value: Boolean);
begin
  FReadOnly := value;
  FOwner.FHeader.SectionEdit := not value;
end;

procedure TPlannerHeader.UpdateHeights;
begin
  if FOwner.FHeader.Orientation = hoHorizontal then
  begin
    FOwner.FHeader.Height := FHeight;
    FOwner.FHeader.FItemHeight := FItemHeight;
    FOwner.FHeader.FFixedHeight := FHeight - FTextHeight;
    FOwner.FHeader.FTextHeight := FTextHeight;
  end
  else
  begin
    FOwner.FHeader.Width := FHeight;
    FOwner.FHeader.FItemHeight := FItemHeight;
    FOwner.FHeader.FFixedHeight := FHeight - FTextHeight;
    FOwner.FHeader.FTextHeight := FTextHeight;
  end;
end;

procedure TPlannerHeader.SetItemHeight(const value: Integer);
begin
  FItemHeight := value;
  UpdateHeights;
  FOwner.FHeader.ShowFixed := Height - TextHeight > 0;
  FOwner.UpdateSizes;
end;

procedure TPlannerHeader.SetTextHeight(const value: Integer);
begin
  FTextHeight := value;
  UpdateHeights;
  FOwner.FHeader.ShowFixed := Height - TextHeight > 0;
  FOwner.UpdateSizes;
end;

procedure TPlannerHeader.SetAllowResize(const value: Boolean);
begin
  FAllowResize := value;
  FOwner.FHeader.AllowSizing := value;
  FOwner.FHeader.AllowResize := value;
end;

procedure TPlannerHeader.SetAllowPositionResize(const value: Boolean);
begin
  FAllowPositionResize := value;
  FOwner.FHeader.AllowResize := value;
end;

function TPlannerHeader.GroupSplit(Pos: Integer): Integer;
var
  i, gs: Integer;
begin
  i := 0;
  gs := 0;
  Result := -1;

  while (gs <= Pos) and (i < CustomGroups.Count) do
  begin
    if (gs = Pos) then
    begin
      Result := CustomGroups[i].Span;
      Exit;
    end;
    gs := gs + CustomGroups[i].Span;
    Inc(i);
  end;
end;

function TPlannerHeader.GetGroupCaption(Pos: Integer): string;
var
  i, gs: Integer;

begin
  i := 0;
  gs := 0;
  Result := '';

  while (gs <= Pos) and (i < CustomGroups.Count) do
  begin
    if (gs = Pos) then
    begin
      Result := CustomGroups[i].Caption;
      Exit;
    end;

    gs := gs + CustomGroups[i].Span;
    Inc(i);
  end;
end;

procedure TPlannerHeader.MergeHeader(FromSection, ToSection: Integer);
var
  i, w: Integer;
  s: String;
begin
  for i := FromSection to ToSection do
  begin
    if i < FOwner.FHeader.Sections.Count then
    begin
      w := FOwner.FHeader.SectionWidth[i];

      if i = FromSection then
      begin
        if Pos('#',FOwner.FHeader.Sections[i]) = 1 then
        begin
          s := FOwner.FHeader.Sections[i];
          Delete(s, 1, 1);
          FOwner.FHeader.Sections[i] := s;
          FOwner.FHeader.SectionWidth[i] := w;
        end;
      end
      else
      begin
        if Pos('#', FOwner.FHeader.Sections[i]) <> 1 then
        begin
          FOwner.FHeader.Sections[i] := '#' + FOwner.FHeader.Sections[i];
          FOwner.FHeader.SectionWidth[i] := w;
        end;
      end;
    end;
  end;
end;

procedure TPlannerHeader.UnMergeHeader(FromSection, ToSection: Integer);
var
  i: Integer;
  s: String;
  w: Integer;
begin
  for i := FromSection to ToSection do
  begin
    if i < FOwner.FHeader.Sections.Count then
    begin
      if Pos('#', FOwner.FHeader.Sections[i]) = 1 then
      begin
        s := FOwner.FHeader.Sections[i];
        w := FOwner.FHeader.SectionWidth[i];
        Delete(s, 1, 1);
        FOwner.FHeader.Sections[i] := s;
        FOwner.FHeader.SectionWidth[i] := w;
      end;
    end;
  end;
end;

procedure TPlannerHeader.SetAutoSize(const value: Boolean);
begin
  if FAutoSize <> value then
  begin
    FAutoSize := value;
    if FAutoSize then
      FOwner.AutoSizeHeader;
  end;
end;

procedure TPlannerHeader.SetAutoSizeGroupCaption(const value: Boolean);
begin
  if (FAutoSizeGroupCaption <> value) then
  begin
    FAutoSizeGroupCaption := value;
    FOwner.FHeader.Invalidate;
  end;
end;

procedure TPlannerHeader.SetItemColor(const value: TColor);
begin
  FItemColor := value;
  FOwner.FHeader.FixedColor := value;
end;

procedure TPlannerHeader.SetGroupCaptions(const value: TPlannerStringList);
begin
  FGroupCaptions.Assign(value);
  FOwner.FHeader.Invalidate;
end;

procedure TPlannerHeader.Assign(Source: TPersistent);
begin
  if Assigned(Source) then
  begin
    Alignment := (Source as TPlannerHeader).Alignment;
    AllowResize := (Source as TPlannerHeader).AllowResize;
    AllowPositionResize := (Source as TPlannerHeader).AllowPositionResize;
    AutoSize := (Source as TPlannerHeader).AutoSize;
    Captions.Assign((Source as TPlannerHeader).Captions);
    Color := (Source as TPlannerHeader).Color;
    ColorTo := (Source as TPlannerHeader).ColorTo;
    DragDrop := (Source as TPlannerHeader).DragDrop;
    ReadOnly := (Source as TPlannerHeader).ReadOnly;
    ResizeAll := (Source as TPlannerHeader).ResizeAll;
    Height := (Source as TPlannerHeader).Height;
    Flat := (Source as TPlannerHeader).Flat;
    Font.Assign((Source as TPlannerHeader).Font);
    GroupCaptions.Assign((Source as TPlannerHeader).GroupCaptions);
    Images := (Source as TPlannerHeader).Images;
    ImagePosition := (Source as TPlannerHeader).ImagePosition;
    ItemColor := (Source as TPlannerHeader).ItemColor;
    ItemHeight := (Source as TPlannerHeader).ItemHeight;
    PopupMenu := (Source as TPlannerHeader).PopupMenu;
    TextHeight := (Source as TPlannerHeader).TextHeight;
    VAlignment := (Source as TPlannerHeader).VAlignment;
    Visible := (Source as TPlannerHeader).Visible;
    CustomGroups.Assign((Source as TPlannerHeader).CustomGroups);
    RotateOnLeft := (Source as TPlannerHeader).RotateOnLeft;
    RotateGroupOnLeft := (Source as TPlannerHeader).RotateGroupOnLeft;
    AutoSizeGroupCaption := (Source as TPlannerHeader).AutoSizeGroupCaption;
    HeaderCustomColor := (Source as TPlannerHeader).HeaderCustomColor;
  end;
end;

procedure TPlannerHeader.SetLineColor(const value: TColor);
begin
  FLineColor := value;
  FOwner.FHeader.LineColor := value;
end;

procedure TPlannerHeader.SetColorTo(const value: TColor);
begin
   FColorTo := value;
   FOwner.FHeader.ColorTo := value;
end;

{
procedure TPlannerHeader.SetCursor(const Value: TCursor);
begin
  FCursor := Value;
  FOwner.FHeader.Cursor := Value;
end;
}

procedure TPlannerHeader.SetWordWrap(const value: Boolean);
begin
  FWordWrap := value;
  FOwner.FHeader.Invalidate;
end;

procedure TPlannerHeader.SetRotateOnLeft(const value: Boolean);
begin
  FRotateOnLeft := value;
  FOwner.FHeader.Rotate := value and (FOwner.Sidebar.Orientation = soHorizontal);
end;

procedure TPlannerHeader.SetRotateGroupOnLeft(const value: Boolean);
begin
  FRotateGroupOnLeft := value;
  FOwner.FHeader.Invalidate;
end;

procedure TPlannerHeader.SetRotateOnTop(const value: Boolean);
begin
  FRotateOnTop := value;
  FOwner.FHeader.Rotate := value and (FOwner.Sidebar.Orientation = soVertical);
end;

procedure TPlannerHeader.SetActiveColor(const value: TColor);
begin
  FActiveColor := value;
  FOwner.FHeader.Invalidate;
end;

procedure TPlannerHeader.SetActiveColorTo(const value: TColor);
begin
  FActiveColorTo := value;
  FOwner.FHeader.Invalidate;
end;

procedure TPlannerHeader.SetCustomGroups(const value: TGroupCollection);
begin
  FCustomGroups := value;
end;

function TPlannerHeader.GetOwner: TPersistent;
begin
  Result := FOwner;
end;

procedure TPlannerHeader.CustomGroupChange(Sender: TObject);
begin
  FOwner.FHeader.Invalidate;
end;

{ TPlannerMode }

constructor TPlannerMode.Create(AOwner: TCustomPlanner);
var
  Day, Month, Year: Word;
begin
  inherited Create;
  FOwner := AOwner;
  FPlannerType := plDay;
  FWeekStart := 0;
  FUpdateCount := 0;

  DecodeDate(Now, Year, Month, Day);
  FDay := Day;
  FYear := Year;
  FMonth := Month;

  // default start time in DayPeriod mode
  FPeriodStartYear := Year;
  FPeriodStartMonth := Month;
  FPeriodStartDay := Day;

  // default end time in DayPeriod mode
  DecodeDate(Now + 48, Year, Month, Day);
  FPeriodEndYear := Year;
  FPeriodEndMonth := Month;
  FPeriodEndDay := Day;

  FMultiResource := false;

  FTimeLineStart := int(Now);
end;

destructor TPlannerMode.Destroy;
begin
  inherited Destroy;
end;

procedure TPlannerMode.SetMonth(const value: Integer);
var
  dim: integer;
begin
  if (value > 0) and (value < 13) and (Value <> FMonth) then
  begin
    FMonth := value;
    dim := PlanUtil.DaysInMonth(FMonth, FYear);
    if (FDay > dim) then
      FDay := dim;
    if FUpdateCount = 0 then
      FOwner.Repaint;
  end;
end;

procedure TPlannerMode.SetPlannerType(const value: TPlannerType);
begin
  if (FPlannerType <> value) then
  begin
    FPlannerType := value;
    AutoCorrectPeriod;
    FOwner.InactiveChanged(Self);
    if FUpdateCount = 0 then
      FOwner.FGrid.Repaint;
  end;
end;

procedure TPlannerMode.SetWeekStart(const value: Integer);
begin
  if (FWeekStart <> value) then
  begin
    FWeekStart := value;
    if FUpdateCount = 0 then
      FOwner.FGrid.Repaint;
  end;
end;

procedure TPlannerMode.SetYear(const value: Integer);
begin
  if (FYear <> Value) then
  begin
    FYear := Value;
    if FUpdateCount = 0 then
      FOwner.Repaint;
  end;
end;

procedure TPlannerMode.SetDate(const Value: TDate);
var
  da,mo,ye:word;
begin
  DecodeDate(Value,ye,mo,da);
  FDay := da;
  FMonth := mo;
  FYear := ye;
end;

procedure TPlannerMode.SetDateTimeFormat(const value: string);
begin
  if (FDateTimeFormat <> value) then
  begin
    FDateTimeFormat := value;
    if FUpdateCount = 0 then
      FOwner.Repaint;
  end;
end;

procedure TPlannerMode.SetDay(const Value: integer);
begin
  if (value > 0) and (value <= PlanUtil.DaysInMonth(FMonth, FYear)) then
  begin
    FDay := Value;
    if FUpdateCount = 0 then
      FOwner.Repaint;
  end;
end;

procedure TPlannerMode.SetPeriodStartDay(const value: Integer);
begin
  if (value > 0) and (value < 32) and (FPeriodStartDay <> value) then
  begin
    FPeriodStartDay := value;
    UpdatePeriod;
  end;
end;

procedure TPlannerMode.SetPeriodStartMonth(const value: Integer);
begin
  if (value > 0) and (value < 13) and (FPeriodStartMonth <> value) then
  begin
    FPeriodStartMonth := value;
    UpdatePeriod;
  end;
end;

procedure TPlannerMode.SetPeriodStartYear(const value: Integer);
begin
  if (FPeriodStartYear <> value) then
  begin
    FPeriodStartYear := value;
    UpdatePeriod;
  end;
end;

procedure TPlannerMode.SetPeriodEndDay(const value: Integer);
begin
  if (value > 0) and (value < 32) and (FPeriodEndDay <> value) then
  begin
    FPeriodEndDay := value;
    UpdatePeriod;
  end;
end;

procedure TPlannerMode.SetPeriodEndMonth(const value: Integer);
begin
  if (value > 0) and (value < 13) and (FPeriodEndMonth <> value) then
  begin
    FPeriodEndMonth := value;
    UpdatePeriod;
  end;
end;

procedure TPlannerMode.SetPeriodEndYear(const value: Integer);
begin
  if (FPeriodEndYear <> value) then
  begin
    FPeriodEndYear := value;
    UpdatePeriod;
  end;
end;

function LimitMonth(Month: Word): Word;
begin
  Result := Month;
  if Result > 12 then
    Result := 12;
  if Result < 1 then
    Result := 1;
end;

function LimitDay(Year, Month, Day: Word): Word;
const
  NumDays: array [1 .. 12] of Word = (31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
begin
  if Day > NumDays[Month] then
    Result := NumDays[Month]
  else
    Result := Day;

  if (Month = 2) and (Result = 29) then if (Year mod 4 <> 0) then
    Result := 28;
end;

function EncodePlannerDate(Year, Month, Day: Word): TDateTime;
begin
  if (Year = 0) or (Month = 0) or (Day = 0) then
    Result := 0
  else
    try
      Month := LimitMonth(Month);
      Day := LimitDay(Year, Month, Day);

      Result := EncodeDate(Year, Month, Day);
    except
      Result := 0;
    end;
end;

function TPlannerMode.GetDate: TDate;
begin
  Result := EncodeDate(FYear, FMonth, FDay);
end;

function TPlannerMode.GetPeriodEndDate: TDateTime;
begin
  case PlannerType of
  plDay: Result := EncodePlannerDate(Year,Month,Day)+ FOwner.Positions;
  plHalfDayPeriod, plActiveDayPeriod: Result := EncodePlannerDate(PeriodEndYear, PeriodEndMonth, PeriodEndDay);
  plMonth, plWeek: Result := GetStartOfMonth + (FOwner.Display.FDisplayEnd - FOwner.Display.FDisplayStart)
  else
    Result := EncodePlannerDate(PeriodEndYear, PeriodEndMonth, PeriodEndDay);
  end;
end;

function TPlannerMode.GetPeriodStartDate: TDateTime;
begin
  case PlannerType of
  plDay: Result := EncodePlannerDate(Year, Month, Day);
  plHalfDayPeriod, plActiveDayPeriod: Result := EncodePlannerDate(PeriodStartYear, PeriodStartMonth, PeriodStartDay);
  plWeek, plMonth: Result := GetStartOfMonth
  else
    Result := EncodePlannerDate(PeriodStartYear, PeriodStartMonth, PeriodStartDay);
  end;
end;

function TPlannerMode.GetStartOfMonth: TDateTime;
var
  Diff: Integer;
begin
  Result := EncodePlannerDate(Year, Month, 1);

  if PlannerType = plWeek then
  begin
    Diff := (7 - WeekStart) - DayOfWeek(Result);
    if Diff > 0 then
      Diff := Diff - 7;
    Result := Result + Diff;
  end;
end;

procedure TPlannerMode.UpdatePeriod;
var
  DS, DE: TDateTime;
begin
  if FUpdateCount > 0 then
    Exit;

  AutoCorrectPeriod;

  DS := EncodePlannerDate(FPeriodStartYear, FPeriodStartMonth, FPeriodStartDay);
  DE := EncodePlannerDate(FPeriodEndYear, FPeriodEndMonth, FPeriodEndDay);

  if (DS <= DE) and (DS > 0) and (DE > 0) and not (csLoading in FOwner.ComponentState) and
  (PlannerType = plDayPeriod) then
  begin
    FOwner.Display.BeginUpdate;
    FOwner.Display.DisplayStart := 0;
    FOwner.Display.DisplayEnd := Trunc(DE - DS);
    FOwner.Display.EndUpdate;
  end;

  if (DS <= DE) and (DS > 0) and (DE > 0) and not (csLoading in FOwner.ComponentState) and
  (PlannerType = plHalfDayPeriod) then
  begin
    FOwner.Display.BeginUpdate;
    FOwner.Display.DisplayStart := 0;
    FOwner.Display.DisplayEnd := 2 * Trunc(DE - DS) + 1;
    FOwner.Display.EndUpdate;
  end;

  if (DS <= DE) and (DS > 0) and (DE > 0) and not (csLoading in FOwner.ComponentState) and
  (PlannerType = plActiveDayPeriod) then
  begin
    FOwner.Display.BeginUpdate;
    FOwner.Display.DisplayStart := 0;
    FOwner.Display.DisplayEnd := FOwner.DiffActiveDays(DE,DS);
    FOwner.Display.EndUpdate;
  end;

  FOwner.Invalidate;
end;

procedure TPlannerMode.SetPeriodEndDate(const value: TDateTime);
var
  da, mo, ye: Word;
begin
  DecoDedate(value, ye, mo, da);
  FPeriodEndYear := ye;
  FPeriodEndMonth := mo;
  FPeriodEndDay := da;
  UpdatePeriod;
end;

procedure TPlannerMode.SetPeriodStartDate(const value: TDateTime);
var
  da, mo, ye: Word;
begin
  DecoDedate(value, ye, mo, da);
  FPeriodStartYear := ye;
  FPeriodStartMonth := mo;
  FPeriodStartDay := da;
  UpdatePeriod;
end;

procedure TPlannerMode.AutoCorrectPeriod;
begin
  if PlannerType <> plActiveDayPeriod then
    Exit;

  if not FOwner.HasActiveDays then
    Exit;

  if (FPlannerType = plActiveDayPeriod) then
  begin
    if (DayOfWeek(PeriodStartDate) in FOwner.FInactive) then
    begin
      PeriodStartDate := FOwner.AddActiveDays(PeriodStartDate,1);
    end;

    if (DayOfWeek(PeriodEndDate) in FOwner.FInactive) then
    begin
      PeriodEndDate := FOwner.AddActiveDays(PeriodEndDate,1);
    end;
  end;
end;

procedure TPlannerMode.BeginUpdate;
begin
  Inc(FUpdateCount);
end;

procedure TPlannerMode.EndUpdate;
begin
  if FUpdateCount > 0 then
  begin
    Dec(FUpdateCount);
    if FUpdateCount = 0 then
      UpdatePeriod;
    FOwner.Repaint;
  end;
end;

procedure TPlannerMode.SetTimeLineStart(const value: TDateTime);
begin
  FTimeLineStart := value;
  FOwner.FGrid.Invalidate;
end;

procedure TPlannerMode.Assign(Source: TPersistent);
begin
  if (Source is TPlannerMode) then
  begin
    FClip := (Source as TPlannerMode).Clip;
    FDateTimeFormat := (Source as TPlannerMode).DateTimeFormat;
    FMonth := (Source as TPlannerMode).Month;
    PeriodStartDay := (Source as TPlannerMode).PeriodStartDay;
    PeriodStartMonth := (Source as TPlannerMode).PeriodStartMonth;
    PeriodStartYear := (Source as TPlannerMode).PeriodStartYear;
    PeriodEndDay := (Source as TPlannerMode).PeriodEndDay;
    PeriodEndMonth := (Source as TPlannerMode).PeriodEndMonth;
    PeriodEndYear := (Source as TPlannerMode).PeriodEndYear;
    PlannerType := (Source as TPlannerMode).PlannerType;
    TimeLineStart := (Source as TPlannerMode).TimeLineStart;
    WeekStart := (Source as TPlannerMode).WeekStart;
    Year := (Source as TPlannerMode).Year;
  end;
end;

procedure TPlannerMode.SetTimeLineNVUBegin(const value: Integer);
begin
  FTimeLineNVUBegin := value;
  FOwner.FGrid.Invalidate;
end;

procedure TPlannerMode.SetTimeLineNVUEnd(const value: Integer);
begin
  FTimeLineNVUEnd := value;
  FOwner.FGrid.Invalidate;
end;

{ TPlannerIO }

constructor TPlannerIO.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  FItems := (AOwner as TCustomPlanner).CreateItems;
end;

destructor TPlannerIO.Destroy;
begin
  FItems.Free;
  inherited Destroy;
end;

{ TNavigatorButtons }

constructor TNavigatorButtons.Create(AOwner: TCustomPlanner);
begin
  FOwner := AOwner;
  inherited Create;
  FVisible := True;
  FFlat := True;
end;

procedure TNavigatorButtons.SetFlat(const value: Boolean);
begin
  FFlat := value;
  FOwner.FNext.Flat := value;
  FOwner.FPrev.Flat := value;
end;

procedure TNavigatorButtons.SetNextHint(const value: string);
begin
  FNextHint := value;
  FOwner.FNext.Hint := value;
end;

procedure TNavigatorButtons.SetPrevHint(const value: string);
begin
  FPrevHint := value;
  FOwner.FPrev.Hint := value;
end;

procedure TNavigatorButtons.SetShowHint(const value: Boolean);
begin
  FShowHint := value;
  FOwner.FNext.ShowHint := value;
  FOwner.FPrev.ShowHint := value;
end;

procedure TNavigatorButtons.SetVisible(value: Boolean);
begin
  FVisible := value;
  FOwner.FCaption.UpdatePanel;
  FOwner.FGrid.UpdatePositions;
end;

{TPlannerRichEdit}

procedure TPlannerRichEdit.DoEnter;
begin
  inherited;
  SelStart := 0;
  SelLength := $FFFF;
end;

procedure TPlannerRichEdit.DoExit;
begin
  inherited;
  if Assigned(PlannerItem) then
  begin
    PlannerItem.Text.Text := PlannerItem.FPlanner.RichToText;
    PlannerItem.FPlanner.ItemEdited(PlannerItem);
  end;
  Self.Visible := False;
  Self.Parent.SetFocus;
end;

procedure TPlannerRichEdit.KeyDown(var Key: Word; Shift: TShiftState);
begin
  inherited;
  if Key = VK_ESCAPE then
  begin
    PlannerItem.FPlanner.TextToRich(PlannerItem.Text.Text);
    PlannerItem.FPlanner.SetFocus;
  end;
end;

constructor TPlannerIntList.Create(value: TPlannerItem);
begin
  inherited Create;
  FPlannerItem := value;
end;

procedure TPlannerIntList.SetInteger(Index: Integer; value: Integer);
begin
  inherited Items[Index] := TObject(value);

  if Assigned(OnChange) then
    OnChange(Self);
end;

function TPlannerIntList.GetInteger(Index: Integer): Integer;
begin
  Result := Integer(inherited Items[Index]);
end;

procedure TPlannerIntList.Clear;
begin
  inherited;
  if Assigned(OnChange) then
    OnChange(Self);
end;

function TPlannerIntList.Add(value: Integer): integer;
begin
  Result := inherited Add(TObject(value));
  if Assigned(OnChange) then
    OnChange(Self);
end;

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

{ TAdvHeader }

constructor TAdvHeader.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  FColor := clBtnFace;
  FColorTo := clWhite;
  FFixedColor := clGray;
  FLineColor := clGray;
  FLeftPos := 0;
  FSectionDragDrop := False;
  FTextHeight := 32;
  FItemHeight := 16;
  FShowFixed := True;

  if not (csDesigning in ComponentState) then
  begin
    FInplaceEdit := TMemo.Create(Self);
    FInplaceEdit.Parent := Self;
    FInplaceEdit.Visible := False;
    FInplaceEdit.OnExit := InplaceExit;
  end;

  Zoom := False;
  ZoomCol := -1;
  ShowHint := True;
  Hint := '';
  FLastHintPos := Point(-1, -1);
end;

destructor TAdvHeader.Destroy;
begin
  if not (csDesigning in ComponentState) then
    FInplaceEdit.Free;
  inherited;
end;

procedure TAdvHeader.InplaceExit(Sender: TObject);
var
  EditIdx: Integer;
  s: string;
begin
  //  EditIdx := GetSectionIdx(FEditSection);
  EditIdx := FEditSection;

  s := LFToCLF(FInplaceEdit.Text);

  if Assigned((Owner as TCustomPlanner).OnHeaderEndEdit) then
    (Owner as TCustomPlanner).OnHeaderEndEdit(Owner, EditIdx, s);

  (Owner as TCustomPlanner).FEditMode := False;

  Sections[EditIdx] := s;
  SectionWidth[EditIdx] := FEditWidth;
  FInplaceEdit.Visible := False;
end;

procedure TAdvHeader.CreateToolTip;
begin
  FHToolTip := CreateWindowEx(0, 'Tooltips_Class32', nil, TTS_ALWAYSTIP or TTS_BALLOON or TTS_NOPREFIX,
    Integer(CW_USEDEFAULT), Integer(CW_USEDEFAULT), Integer(CW_USEDEFAULT), Integer(CW_USEDEFAULT), Handle,
    0, HInstance, nil);

  if FHToolTip <> 0 then SetWindowPos(FHToolTip, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE or SWP_NOSIZE or SWP_NOACTIVATE);
end;

procedure TAdvHeader.DestroyToolTip;
begin
  DestroyWindow(FHToolTip);
end;

procedure TAdvHeader.AddToolTip(IconType: Integer; Text, Title: string);

var
  Item: THandle;
  Rect: TRect;
  ti: TToolInfo;
  buffer: array [0 .. 255] of Char;
begin
  Item := Self.Handle;

  if (Item <> 0) AND (Windows.GetClientRect(Item, Rect)) then
  begin
    ti.cbSize := SizeOf(TToolInfo);
    ti.uFlags := TTF_SUBCLASS or TTF_IDISHWND;
    ti.hInst := HInstance;
    ti.hwnd := Item; ti.Rect := Rect; ti.uId := Handle;
    ti.lpszText := LPSTR_TEXTCALLBACK;
    SendMessage(FHToolTip, TTM_ADDTOOL, 0, LParam(@ti));
    FillChar(buffer, SizeOf(buffer), #0);
    lstrcpy(buffer, PChar(Title));
    if (IconType > 3) or (IconType < 0) then
      IconType := 0;
    SendMessage(FHToolTip, TTM_SETTITLE, IconType, LParam(@buffer));
  end;
end;

procedure TAdvHeader.SetAlignment(const value: TAlignment);
begin
  FAlignment := value;
  Invalidate;
end;

procedure TAdvHeader.SetVAlignment(const value: TVAlignment);
begin
  FVAlignment := value;
  Invalidate;
end;

procedure TAdvHeader.SetColor(const value: TColor);
begin
  FColor := value;
  Invalidate;
end;

procedure TAdvHeader.SetLineColor(const value: TColor);
begin
  FLineColor := value;
  Invalidate;
end;

procedure TAdvHeader.SetImageList(const value: TImageList);
begin
  FImageList := value;
  Invalidate;
end;

procedure TAdvHeader.SetOrientation(const value: THeaderOrientation);
begin
  FOrientation := value;
  Invalidate;
end;

procedure TAdvHeader.SetFlat(const value: Boolean);
begin
  FFlat := value;
  Invalidate;
end;

procedure TAdvHeader.SetImagePosition(const value: TImagePosition);
begin
  FImagePosition := value;
  Invalidate;
end;

function TAdvHeader.GetSectionRect(X: Integer): TRect;
var
  Offset, SectionIndex: Integer;
begin
  Offset := 0;

  for SectionIndex := FLeftPos to X - 1 do
  begin
    if SectionIndex = FLeftPos then
      Offset := Offset + SectionWidth[0]
    else
      Offset := Offset + SectionWidth[SectionIndex];
  end;

  if FOrientation = hoHorizontal then
  begin
    Result.Left := Offset;
    Result.Right := Offset + SectionWidth[X];
    Result.Top := 0;
    Result.Bottom := Self.Height;
  end
  else
  begin
    Result.Left := 0;
    Result.Right := Self.Width;
    Result.Top := Offset;
    Result.Bottom := Offset + SectionWidth[X];
  end;
end;

function TAdvHeader.XYToSection(X, Y: Integer): Integer;
var
  Ofs, SectionIndex: Integer;
begin
  Ofs := 0;
  SectionIndex := FLeftPos;

  if FOrientation = hoHorizontal then
  begin
    while (Ofs < X) and (SectionIndex < Sections.Count) do
    begin
      if SectionIndex = FLeftPos then
        Ofs := Ofs + SectionWidth[0]
      else
        Ofs := Ofs + SectionWidth[SectionIndex];
      Inc(SectionIndex);
    end;
    Dec(SectionIndex);
  end
  else
  begin
    while (Ofs < Y) and (SectionIndex < Sections.Count) do
    begin
      if SectionIndex = FLeftPos then
        Ofs := Ofs + SectionWidth[0]
      else
        Ofs := Ofs + SectionWidth[SectionIndex];
      Inc(SectionIndex);
    end;
    Dec(SectionIndex);
  end;

  Result := SectionIndex;
end;

procedure TAdvHeader.Paint;
var
  SectionIndex, w, AIdx, BIdx, MergeNum: Integer; s: string;
  CT, CID, CV: string;
  CR, rct: TRect;
  DrawFlags: dword;
  DrawGroupFlags: dword;
  R, GR: TRect;
  pr,tr,mr: TRect;
  HorizontalAlign: Word;
  VerticalAlign: Word;
  AllPainted: Boolean;
  APlannerItem: TPlannerItem;
  DoDraw: Boolean;
  Anchor, Strip, FocusAnchor: string;
  ml, hl, XSize, YSize: Integer;
  hr: TRect;
  Planner: TCustomPlanner;
  Orgx, Oldx, GroupIdx: Integer;
  LastRow: Boolean;
  lf: TLogFont;
  tf: TFont;
  vimg: Integer;
  SideOffset: Integer;
  spanidx: Integer;
  IsGroup: Boolean;
  GroupCaption: string;
  GroupWideCaption: widestring;
  GroupImage: Integer;
  GroupFontHeight: Integer;
  prhbottom,h,btm: Integer;
  sectionclr, sectionclrto: TColor;
  grpclr,grpclrto: TColor;
  custcolor: THeaderCustomColor;

  function IsSideSection(APlanner: TCustomPlanner; Idx: Integer): Boolean;
  begin
    case APlanner.Sidebar.Position of
    spLeft, spTop: Result := Idx = 1;
    spRight: Result := Idx >= APlanner.Positions + 1;
    spLeftRight: Result := (Idx = 1) or (Idx > APlanner.Positions + 1);
    else
      Result := False;
    end;
  end;

begin
  Planner := Owner as TCustomPlanner;

  Planner.Header.GroupSpan.Clear;

  spanidx := 0;

  if Planner.Header.AutoSizeGroupCaption then
  begin
    tf := TFont.Create;
    tf.Assign(Canvas.Font);
    try
      Canvas.Font.Assign(Planner.Header.GroupFont);
      GroupFontHeight := Canvas.TextHeight('gh') + 4;
      Canvas.Font.Assign(tf);
    finally
      tf.Free;
    end;
  end
  else
  begin
    if Planner.Header.GroupHeight = 0 then
      GroupFontHeight := (FTextHeight shr 1)
    else
      GroupFontHeight := Planner.Header.GroupHeight;
  end;

  if Planner.Header.CustomGroups.Count > 0 then
  begin
    for w := 1 to Planner.Header.CustomGroups.Count do
    begin
      spanidx := spanidx + Planner.Header.CustomGroups[w - 1].Span;
      Planner.Header.GroupSpan.Add(spanidx);
    end;

    while Planner.Header.GroupSpan.Count <= Planner.Positions do
    begin
      Planner.Header.GroupSpan.Add(spanidx);
      Inc(spanidx);
    end;
  end;

  spanidx := 0;

  // adapt for scroll position
  if FLeftPos > 0 then
  begin
    while (spanidx < Planner.Header.GroupSpan.Count) and (FLeftPos >= Planner.Header.GroupSpan[spanidx]) do
      Inc(spanidx);
  end;

  SideOffset := 2;

  if Planner.Sidebar.Position = spRight then
    SideOffset := 1;

  with Canvas do
  begin
    Font := Self.Font;
    Brush.Color := FColor;

    if FLineColor = clNone then
      Pen.Color := FColor
    else
      Pen.Color := FLineColor;

    Pen.Width := 1;
    SectionIndex := 0;
    Orgx := 0;

    if (Orientation = hoHorizontal) then
      R := Rect(0, 0, 0, ClientHeight)
    else
      R := Rect(0, 0, ClientWidth, 0);

    AIdx := 0;
    w := 0;
    s := '';

    HorizontalAlign := AlignToFlag(FAlignment);
    VerticalAlign := 0;

    AllPainted := False;

    repeat
      MergeNum := 1;

      if SectionIndex + FLeftPos < Sections.Count then
      begin
        if SectionIndex > 0 then
          w := SectionWidth[SectionIndex + FLeftPos]
        else
          w := SectionWidth[SectionIndex];

        if (w < 0) and (Orientation = hoVertical) then
        begin
          w := Planner.FGrid.RowHeights[SectionIndex];
        end;

        if Flat and (SectionIndex = 0) and (Orientation = hoHorizontal) then
          Dec(w);

        if not Flat and (SectionIndex = 0) and (Orientation = hoVertical) then
          Inc(w);

        VerticalAlign := VAlignToFlag(FVAlignment);

        // get the caption text

        s := '';

        if FOffset = 1 then
        begin
          if (SectionIndex <= Sections.Count - 1 - FLeftPos) and (SectionIndex > 0) then
          begin
            AIdx := SectionIndex + FLeftPos;
            s := Sections[AIdx];
          end
          else
          begin
            AIdx := -1;
            if SectionIndex = 0 then
              s := Sections[0];
          end;
        end
        else
        begin
          if (SectionIndex < Sections.Count - FLeftPos) then
            AIdx := SectionIndex + FLeftPos
          else
            AIdx := 0;

          s := Sections[AIdx];
        end;

        // merged cells
        if (Pos('#', s) = 1) and (AIdx > 0) then
        begin
          BIdx := AIdx - 1;
          while (BIdx >= 0) and (Pos('#', Sections[BIdx]) = 1) do
          begin
            Dec(BIdx);
          end;
          s := Sections[BIdx];
        end;

        if AIdx <> -1 then
        begin
          BIdx := AIdx + 1;
          while (BIdx < Sections.Count) do
          begin
            if Pos('#', Sections[BIdx]) = 1 then
            begin
              w := w + SectionWidth[SectionIndex];
              Inc(MergeNum);
            end
            else
              Break;
            Inc(BIdx);
          end;
        end;

        Inc(SectionIndex, MergeNum);
      end;

      if (Orientation = hoHorizontal) then
      begin
        R.Left := R.Right;
        Inc(R.Right, w);

        R.Bottom := ClientHeight;

        if (ClientWidth - R.Right < 2) or (SectionIndex + FLeftPos = Sections.Count) then
        begin
          R.Right := ClientWidth;
          AllPainted := True;
        end;
      end
      else
      begin
        R.Top := R.Bottom;
        Inc(R.Bottom, w);

        if (ClientHeight - R.Bottom < 2) or (SectionIndex + FLeftPos = Sections.Count) then
        begin
          R.Bottom := ClientHeight;
          AllPainted := True;
        end;
      end;

      pr := R;

      if FShowFixed and not IsSideSection(Planner, SectionIndex) then
      begin
        Canvas.Brush.Color := FFixedColor;

        if Orientation = hoHorizontal then
          R.Top := R.Bottom - FFixedHeight
        else
          R.Left := R.Right - FFixedHeight;

        FillRect(R);
        R := pr;

        if Orientation = hoHorizontal then
          R.Bottom := R.Bottom - FFixedHeight
        else
          R.Right := R.Right - FFixedHeight;
      end;

      Canvas.Brush.Color := FColor;

      if (Planner.Header.ActiveColor <> clNone) and (SectionIndex + FLeftPos - SideOffset =  Planner.SelPosition) then
      begin
        sectionclr := Planner.Header.ActiveColor;
        sectionclrto := Planner.Header.ActiveColorTo;
      end
      else
      begin
        sectionclr := FColor;
        sectionclrto := FColorTo;
      end;

      Planner.HeaderDrawProp(Planner, SectionIndex + FLeftPos - SideOffset, sectionclr, sectionclrto, Canvas.Font);

      if FFlat and not (Planner.FUseVCLStyles and (Orientation = hoVertical)) then
      begin
        r.Top := r.Top + 1;
        r.Bottom := r.Bottom + 2;
      end;

      custcolor := Planner.Header.HeaderCustomColor;

      grpclr := Planner.Header.Color;
      grpclrto := Planner.Header.ColorTo;

      if Assigned(Planner.OnHeaderGroupDrawProp) then
      begin
        custcolor := ccItem;
        Planner.HeaderGroupDrawProp(Planner, SectionIndex + FLeftPos - SideOffset, grpclr, grpclrto, Canvas.Font);
      end;

      case custcolor of
      ccNone: R.Right := R.Left;
      ccGroup:
        begin
          GR := R;
          GR.Left := GR.Right -  Planner.Header.Height div 2;
          DrawGradient(Canvas, Planner.Header.Color, PLanner.Header.ColorTo, Planner.GradientSteps, R, Orientation = hoVertical);

          R.Right := R.Left + Planner.Header.Height div 2;
        end;
      ccItem:
        begin
          GR := R;
          GR.Right := GR.Left +  Planner.Header.Height div 2;
          DrawGradient(Canvas, grpclr, grpclrto, Planner.GradientSteps, R, Orientation = hoVertical);

          R.Left := R.Right -  Planner.Header.Height div 2;
        end;
      end;

      if FFlat and (Orientation = hoHorizontal) then
        r.Bottom := r.Bottom - 3;

      DrawGradient(Canvas, sectionclr, sectionclrto, Planner.GradientSteps, R, Orientation = hoVertical);

      if FFlat and (Orientation = hoHorizontal) then
        r.Bottom := r.Bottom + 3;

      R := pr;

      if FLineColor = clNone then
        Pen.Color := FColor
      else
        Pen.Color := FLineColor;

      DoDraw := True;

      if Assigned(Planner.FOnPlannerHeaderDraw) then
      begin
        Font := Self.Font;
        Brush.Color := FColor;
        Pen.Color := FLineColor;
        Pen.Width := 1;
        Planner.FOnPlannerHeaderDraw(TCustomPlanner(Owner), Canvas, R, AIdx, DoDraw);
      end;

      LastRow := False;

      if (Orientation = hoVertical) and (SectionIndex > Planner.GridControl.VisibleRowCount + 2) then
        LastRow := True;

      if DoDraw then
      begin
        InflateRect(pr, -4, 0);

        if Assigned(FImageList) and (FImageList.Count + 1 + FOffset - FLeftPos > SectionIndex) and
          (SectionIndex > FOffset) and (SectionIndex <= Sections.Count - 1 - FLeftPos) then
        begin
          vimg := pr.Top;
          if Planner.PositionGroup > 0 then
            vimg := pr.Top + FTextHeight div 2;

          prhbottom := pr.Top + Planner.Header.TextHeight;

          case FVAlignment of
          vtaCenter: vimg := vimg + ((prhbottom - vimg - FImageList.Height) div 2);
          vtaBottom: vimg := prhbottom - FImageList.Height;
          end;

          if FImagePosition = ipLeft then
          begin
            FImageList.Draw(Canvas, pr.Left, vimg, SectionIndex - 1 - FOffset + FLeftPos);
            pr.Left := pr.Left + FImageList.Width;
          end
          else
          begin
            pr.Right := pr.Right - FImageList.Width;
            FImageList.Draw(Canvas, pr.Right, vimg, SectionIndex - 1 - FOffset + FLeftPos);
          end;
        end;

        s := CLFToLF(s);
        if Pos(#13, s) = 0 then
          VerticalAlign := VerticalAlign or DT_SINGLELINE
        else
          VerticalAlign := 0;

        if (Orientation = hoHorizontal) then
          pr.Bottom := pr.Top + FTextHeight;

        // adapt header height / width when position groups are used
        if (Planner.PositionGroup > 0) and (Orientation = hoHorizontal) then
        begin
          pr.Top := pr.Top + GroupFontHeight;
        end;

        if (Planner.PositionGroup > 0) and (Orientation = hoVertical) then
        begin
          pr.Left := pr.Left + GroupFontHeight;
        end;

        if (Orientation = hoVertical) then
        begin
          pr.Right := FTextHeight;
          pr.Bottom := pr.Top + w - 2;
        end;

        DrawFlags := DT_NOPREFIX or DT_END_ELLIPSIS or HorizontalAlign or VerticalAlign;

        if Planner.Header.WordWrap then
        begin
          DrawFlags := DrawFlags and not DT_SINGLELINE and not DT_END_ELLIPSIS or DT_WORDBREAK;
          btm := pr.Bottom;
          inflaterect(pr,-2,-4);
        end;

        DrawFlags := Planner.DrawTextBiDiModeFlags(DrawFlags);

        if not LastRow then
        begin
          if Pos('</', s) > 0 then
          begin
            HTMLDrawEx(Canvas, s, pr, Planner.PlannerImages, 0, 0, -1, -1, 1, False, False,
              False, False, False, False, True
             , False
             , 1, clBlue, clNone, clNone, clGray, Anchor, Strip,
             FocusAnchor, XSize, YSize, ml, hl, hr
             , CR, CID, CV, CT, Planner.FImageCache, Planner.FContainer, Handle
             );
          end
          else
          begin
            Canvas.Brush.Style := bsClear;
            if Rotate or (Planner.Header.RotateOnLeft and (Planner.Sidebar.Position = spTop)) then
            begin
              tf := TFont.Create;
              try
                tf.Assign(Font);
                GetObject(tf.Handle, SizeOf(lf), @lf);
                lf.lfEscapement := 900;
                lf.lfOrientation := 900;
                tf.Handle := CreateFontIndirect(lf);
                Canvas.Font.Assign(tf);

                while Pos(#13, s) > 0 do
                begin
                  case Planner.Header.Alignment of
                  taLeftJustify: TextRect(pr, pr.Left, R.Bottom - 4, Copy(s, 1, Pos(#13, s) - 1));
                  taCenter: TextRect(pr, pr.Left, R.Bottom - ((R.Bottom - R.Top - TextWidth(Copy(s, 1, Pos(#13, s)))) div 2),
                                       Copy(s, 1, Pos(#13, s) - 1));
                  taRightJustify: TextRect(pr, pr.Left, R.Top + TextWidth(Copy(s, 1, Pos(#13, s))), Copy(s, 1, Pos(#13, s)));
                  end;

                  Delete(s, 1, Pos(#13, s) + 1);
                  pr.Left := pr.Left + TextHeight('gh');
                end;

                case Planner.Header.Alignment of
                taLeftJustify: TextRect(pr, pr.Left, R.Bottom - 4, s);
                taCenter: TextRect(pr, pr.Left, R.Bottom - ((R.Bottom - R.Top - TextWidth(s)) div 2), s);
                taRightJustify: TextRect(pr, pr.Left, R.Top + TextWidth(s) + 4, s);
                end;

              finally
                tf.Free;
              end;
            end
            else
            begin
              if Planner.Header.WordWrap and (Planner.Header.VAlignment <> vtaTop) then
              begin
                mr := pr;
                h := DrawText(Canvas.Handle, PChar(s), Length(s), mr, DrawFlags or DT_CALCRECT);
                case Planner.Header.VAlignment of
                vtaBottom: pr.Top := pr.Bottom - h;
                vtaCenter: pr.Top := pr.Top + (pr.Bottom - pr.Top - h) div 2;
                end;
                pr.Bottom := pr.Top + h;
              end;

              if (w > 4) then
                DrawText(Canvas.Handle, PChar(s), Length(s), pr, DrawFlags);

              pr.Bottom := btm;
            end;
          end;
        end;

        if FShowFixed and (Orientation = hoHorizontal) and (SectionIndex > 1) then
          R.Bottom := R.Bottom - FFixedHeight;

        if (Orientation = hoVertical) and (SectionIndex + FLeftPos = Sections.Count - 1) then
          R.Bottom := R.Bottom - 1;

        if FShowFixed and (Orientation = hoVertical) and (SectionIndex > 1) then
          R.Right := R.Right - FFixedHeight;

        // adapt header width / height when positiongroups are used
        if (Planner.PositionGroup > 0) and (Orientation = hoHorizontal) and (SectionIndex > 1) then
        begin
          if (Planner.Header.GroupHeight = 0) then
            R.Top := R.Top + FTextHeight div 2
          else
            R.Top := R.Top + Planner.Header.GroupHeight;
        end;

        if (Planner.PositionGroup > 0) and (Orientation = hoVertical) and (SectionIndex > 1) then
           R.Left := R.Left + FTextHeight div 2;

        //          r.Left := r.Left + GroupFontHeight;

        rct := R;

        if (SectionIndex > 1) and (Orientation = hoVertical) and (Planner.PositionGroup > 0) then
          rct.Left := GroupFontHeight;

        if (SectionIndex > 1) and (Orientation = hoHorizontal) and (Planner.PositionGroup > 0) then
          rct.Top := GroupFontHeight;

        if not FFlat then
        begin
          DrawEdge(Canvas.Handle, rct, BDR_RAISEDINNER, BF_TOPLEFT);
          DrawEdge(Canvas.Handle, rct, BDR_RAISEDINNER, BF_BOTTOMRIGHT);
        end
        else
        begin
          if (SectionIndex > 0) and (Orientation = hoHorizontal) and (FLineColor <> clNone) then
          begin
            Canvas.MoveTo(rct.Left + 2, rct.Top);
            Canvas.LineTo(rct.Left + 2, rct.Bottom);

            Canvas.MoveTo(rct.Left + 0, rct.Top + 0);
            Canvas.LineTo(rct.Right + 2, rct.Top + 0);
            Canvas.MoveTo(rct.Left + 0, rct.Bottom - 1);
            Canvas.LineTo(rct.Right + 2, rct.Bottom - 1);
          end;

          if (SectionIndex > 1) and (Orientation = hoVertical) and (FLineColor <> clNone) then
          begin
            Canvas.MoveTo(rct.Left + 2, rct.Top + 2);
            Canvas.LineTo(rct.Right - 1, rct.Top + 2);
            Canvas.LineTo(rct.Right - 1, rct.Bottom + 2);
          end;
        end;

        // horizontal positiongroup painting
        if (Planner.PositionGroup > 0) and (Orientation = hoHorizontal) and (SectionIndex > 1) then
        begin
          if SectionIndex = 2 then
            Orgx := R.Left;

          if (Planner.Header.GroupHeight = 0) then
          begin
            R.Top := R.Top - FTextHeight div 2;
            R.Bottom := R.Top + FTextHeight div 2;
          end
          else
          begin
            R.Top := R.Top - Planner.Header.GroupHeight;
            R.Bottom := R.Top + Planner.Header.GroupHeight;
          end;

          GroupImage := -1;

          if Planner.Header.CustomGroups.Count > 0 then
          begin
            IsGroup := ((SectionIndex - 1 + FLeftPos) = Planner.Header.GroupSpan[spanidx]);

            GroupWideCaption := '';
            GroupCaption := '';

            if IsGroup then
            begin
              if (Planner.Header.CustomGroups.Count > spanidx) then
              begin
                GroupWideCaption := Planner.Header.CustomGroups[spanidx].WideCaption;
                GroupCaption := Planner.Header.CustomGroups[spanidx].Caption;
                GroupImage := Planner.Header.CustomGroups[spanidx].ImageIndex;
              end;
              Inc(spanidx);
            end;
          end
          else
          begin
            IsGroup := ((SectionIndex - 1 + FLeftPos) mod Planner.PositionGroup = 0);
            GroupIdx := (SectionIndex - 2 + FLeftPos) div Planner.PositionGroup;
            if Planner.Header.GroupCaptions.Count > GroupIdx then
            begin
              GroupCaption := CLFToLF(Planner.Header.GroupCaptions.Strings[GroupIdx]);
            end
            else
              GroupCaption := '';
          end;

          // need to paint new positiongroup here ?
          if IsGroup or AllPainted then
          begin
            //inc(spanidx);
            Oldx := R.Left;
            R.Left := Orgx;
            rct := R;
            rct.Bottom := GroupFontHeight;

            if not FFlat then
            begin
              DrawEdge(Canvas.Handle, rct, BDR_RAISEDINNER, BF_TOPLEFT);
              DrawEdge(Canvas.Handle, rct, BDR_RAISEDINNER, BF_BOTTOMRIGHT);
            end
            else
            begin
              OffsetRect(rct, 2, 0);
              Canvas.MoveTo(rct.Left, rct.Top);
              Canvas.LineTo(rct.Right, rct.Top);
              Canvas.LineTo(rct.Right, rct.Bottom);
              Canvas.LineTo(rct.Left, rct.Bottom);
              Canvas.LineTo(rct.Left, rct.Top);

              OffsetRect(rct, -2, 0);
            end;

            s := GroupCaption;

            VerticalAlign := VAlignToFlag(Planner.Header.FVAlignment);
            if Pos(#13, s) = 0 then
              DrawGroupFlags := DT_NOPREFIX or HorizontalAlign or DT_SINGLELINE or VerticalAlign
            else
              DrawGroupFlags := DT_NOPREFIX or HorizontalAlign or DT_WORDBREAK or VerticalAlign;

            DrawGroupFlags := Planner.DrawTextBiDiModeFlags(DrawGroupFlags);
            Canvas.Font.Assign(Planner.Header.GroupFont);

            if (GroupImage >= 0) and Assigned(Planner.PlannerImages) then
            begin
              Planner.PlannerImages.Draw(Canvas, rct.Left, rct.Top, GroupImage);
              rct.Left := rct.Left + 2 + Planner.PlannerImages.Width;
            end;

            // Draw text transparent
            Canvas.Brush.Style := bsClear;

            rct.Left := rct.Left + 4;

            // HTML rendering
            if Pos('</', s) > 0 then
            begin
              HTMLDrawEx(Canvas, s, rct, Planner.PlannerImages, 0, 0, -1, -1, 1, False, False,
                False, False, False, False, True
                , False
                , 1, clBlue, clNone, clNone, clGray, Anchor, Strip, FocusAnchor, XSize, YSize, ml, hl, hr
                , CR, CID, CV, CT, Planner.FImageCache, Planner.FContainer, Handle
                );
            end
            else
            begin
              if (GroupWideCaption <> '') then
              begin
                DrawTextExW(Canvas.Handle, PWideChar(GroupWideCaption),
                  Length(GroupWideCaption), rct, DrawGroupFlags, nil);
              end
              else
              begin
                DrawText(Canvas.Handle, PChar(s), Length(s), rct, DrawGroupFlags);
              end;
            end;

            Canvas.Font.Assign(Font);

            R.Left := Oldx;
            Orgx := R.Right;
          end;

          R.Bottom := R.Top + FTextHeight;
        end;
        // end of horizontal positiongroup painting

        // vertical positiongroup painting
        if (Planner.PositionGroup > 0) and (Orientation = hoVertical) and (SectionIndex > 1) then
        begin
          if SectionIndex = 2 then
            Orgx := R.Top;
          R.Left := R.Left - FTextHeight shr 1;
          R.Right := R.Left + FTextHeight shr 1;

          GroupImage := -1;

          if Planner.Header.CustomGroups.Count > 0 then
          begin
            IsGroup := ((SectionIndex - 1 + FLeftPos) = Planner.Header.GroupSpan[spanidx]);

            GroupWideCaption := '';
            GroupCaption := '';

            //  if IsGroup then
            begin
              if (Planner.Header.CustomGroups.Count > spanidx) then
              begin
                GroupWideCaption := Planner.Header.CustomGroups[spanidx].WideCaption;
                GroupCaption := Planner.Header.CustomGroups[spanidx].Caption;
                GroupImage := Planner.Header.CustomGroups[spanidx].ImageIndex;
              end;
            end;
            if IsGroup then
            begin
              Inc(spanidx);
            end;
          end
          else
          begin
            IsGroup := ((SectionIndex - 1 + FLeftPos) mod Planner.PositionGroup = 0);
            GroupIdx := (SectionIndex - 2 + FLeftPos) div Planner.PositionGroup;
            if Planner.Header.GroupCaptions.Count > GroupIdx then
              GroupCaption := CLFToLF(Planner.Header.GroupCaptions.Strings[GroupIdx])
            else
              GroupCaption := '';
          end;

//          if ((SectionIndex - 1 + FLeftPos) mod Planner.PositionGroup = 0) or AllPainted then
          if IsGroup or AllPainted then
          begin
            Oldx := R.Top;
            R.Top := Orgx;
            rct := R;
            rct.Right := GroupFontHeight;

            if not FFlat then
            begin
              DrawEdge(Canvas.Handle, rct, BDR_RAISEDINNER, BF_TOPLEFT);
              DrawEdge(Canvas.Handle, rct, BDR_RAISEDINNER, BF_BOTTOMRIGHT);
            end
            else
            begin
              //OffsetRect(rct,2,0);
              Canvas.MoveTo(rct.Left, rct.Top + 2);
              Canvas.LineTo(rct.Right + 1, rct.Top + 2);
              Canvas.LineTo(rct.Right + 1, rct.Bottom + 2);
              Canvas.LineTo(rct.Left, rct.Bottom + 2);
              Canvas.LineTo(rct.Left, rct.Top + 2);
              //OffsetRect(rct,-2,0);
            end;

            tr := R;

            if (GroupImage >= 0) and Assigned(Planner.PlannerImages) then
            begin
              if not Planner.Header.RotateOnLeft then
              begin
                Planner.PlannerImages.Draw(Canvas, R.Left, R.Top + ((R.Bottom - R.Top) - Planner.PlannerImages.Height) div 2, GroupImage);
                tr.Left := 2 + Planner.PlannerImages.Width;
              end
              else
              begin
                Planner.PlannerImages.Draw(Canvas, R.Left, R.Bottom - Planner.PlannerImages.Height,  GroupImage);
                tr.Bottom := tr.Bottom - 2 - Planner.PlannerImages.Height;
              end;
            end;

            //GroupIdx := (SectionIndex - 2 + FLeftPos) div Planner.PositionGroup;

            if Planner.Header.RotateGroupOnLeft and (Planner.Sidebar.Position = spTop) then
            begin
              //if Planner.Header.GroupCaptions.Count > GroupIdx then
              //begin
                s := CLFToLF(GroupCaption);
                //s := CLFToLF(Planner.Header.GroupCaptions.Strings[GroupIdx]);
                SetBkMode(Canvas.Handle, Transparent); tf := TFont.Create;
                try
                  tf.Assign(Planner.Header.GroupFont);
                  GetObject(tf.Handle, SizeOf(lf), @lf);
                  lf.lfEscapement := 900;
                  lf.lfOrientation := 900;
                  tf.Handle := CreateFontIndirect(lf);
                  Canvas.Font.Assign(tf);
                  Canvas.Brush.Style := bsClear;

                  while Pos(#13, s) > 0 do
                  begin
                    TextRect(R, R.Left, R.Bottom - 4, Copy(s, 1, Pos(#13, s) - 1));
                    Delete(s, 1, Pos(#13, s) + 1);
                    tr.Left := tr.Left + TextHeight('gh');
                  end;

                  TextRect(tr, tr.Left, tr.Bottom - 4, s);
                finally
                  tf.Free;
                end;
             //end;
            end
            else
            begin
              if Planner.Header.WordWrap then
                InflateRect(tr,-4,-4);

              //if Planner.Header.GroupCaptions.Count > GroupIdx then
              begin
                Canvas.Font.Assign(Planner.Header.GroupFont);

                s := CLFToLF(GroupCaption);
                if Pos(#13, s) = 0 then
                  DrawGroupFlags := DrawFlags
                else
                  DrawGroupFlags := DT_NOPREFIX or HorizontalAlign or DT_WORDBREAK;

                DrawGroupFlags := Planner.DrawTextBiDiModeFlags(DrawGroupFlags);
                if Pos('</', s) > 0 then
                begin
                  HTMLDrawEx(Canvas, s, R, Planner.PlannerImages, 0, 0, -1, -1, 1, False, False,
                    False, False, False, False, True
                    , False
                    , 1, clBlue, clNone, clNone, clGray, Anchor, Strip,
                    FocusAnchor, XSize, YSize, ml, hl, hr
                    , CR, CID, CV, CT, Planner.FImageCache,
                    Planner.FContainer, Handle
                    );
                end
                else
                begin
                  if Planner.Header.WordWrap and (PLanner.Header.VAlignment <> vtaTop) then
                  begin
                    mr := tr;
                    h := DrawText(Canvas.Handle, PChar(s), Length(s), mr, DrawGroupFlags or DT_CALCRECT);

                    case Planner.Header.VAlignment of
                    vtaBottom: tr.Top := tr.Bottom - h;
                    vtaCenter: tr.Top := tr.Top + (tr.Bottom - tr.Top - h) div 2;
                    end;
                    tr.Bottom := tr.Top + h;
                  end;

                  if (w > 4) then
                    DrawText(Canvas.Handle, PChar(s), Length(s), tr, DrawGroupFlags);
                end;
                Canvas.Font.Assign(Planner.Header.Font);
              end;
            end;

            R.Top := Oldx;
            Orgx := R.Bottom;
          end;

          R.Right := R.Left + FTextHeight;
        end;

        if FShowFixed and (Orientation = hoHorizontal) and (SectionIndex > 1) then
        begin
          Canvas.Pen.Color := FLineColor;
          if FFlat then
          begin
            Canvas.MoveTo(R.Left + 1, R.Bottom);
            Canvas.LineTo(R.Left + 1, R.Bottom + FFixedHeight);
          end
          else
          begin
            Canvas.MoveTo(R.Right - 1, R.Bottom);
            Canvas.LineTo(R.Right - 1, R.Bottom + FFixedHeight);
          end;
          R.Bottom := R.Bottom + FFixedHeight;
        end;

        if FShowFixed and (Orientation = hoVertical) and (SectionIndex > 1) then
        begin
          Canvas.Pen.Color := FLineColor;
          Canvas.MoveTo(R.Right, R.Bottom + 2);
          Canvas.LineTo(R.Right + FFixedHeight, R.Bottom + 2);

          R.Right := R.Right + FFixedHeight;
        end;

        with Planner do
        begin
          if Sidebar.Position = spRight then
            APlannerItem := Items.HeaderFirst(SectionIndex - 1 + FLeftPos)
          else
            APlannerItem := Items.HeaderFirst(SectionIndex - 2 + FLeftPos);

          pr.Top := R.Top;
          pr.Bottom := Planner.Header.TextHeight;

          while Assigned(APlannerItem) and not IsSideSection(Planner, SectionIndex) do
          begin
            APlannerItem.FRepainted := False;
            //Paint full Items here
            if Orientation = hoHorizontal then
            begin
              pr.Left := R.Left + 2; pr.Right := R.Right - 2;
              pr.Top := pr.Bottom;
              pr.Bottom := pr.Bottom + FItemHeight;
              FGrid.PaintItemCol(Self.Canvas, pr, APlannerItem, False, False);
            end
            else
            begin
              pr.Left := R.Left + FTextHeight;
              pr.Right := R.Right - 2;
              pr.Bottom := pr.Top + FItemHeight;
              FGrid.PaintItemCol(Self.Canvas, pr, APlannerItem, False, False);
              pr.Top := pr.Top + FItemHeight;
            end;

            if Sidebar.Position = spRight then
              APlannerItem := Items.HeaderNext(SectionIndex - 1 + FLeftPos)
            else
              APlannerItem := Items.HeaderNext(SectionIndex - 2 + FLeftPos);
          end;
        end;

        Planner.HeaderDraw(Planner, SectionIndex + FLeftPos - SideOffset, Canvas, R);

        Font := Self.Font;
        Brush.Color := FColor;
        Pen.Color := FLineColor;
        Pen.Width := 1;
      end;
    until AllPainted;
  end;
end;

procedure TAdvHeader.CMHintShow(var Message: TMessage);
{$IFDEF DELPHI2_LVL}
type
  PHintInfo = ^THintInfo;
{$ENDIF}
var
  CanShow: Boolean;
  Hi: PHintInfo;
  CR, hr, pr, cor: TRect;
  APlannerItem: TPlannerItem;
  s, CID, CV, CT: string;
  Anchor, StrippedHTMLString,
  FocusAnchor: string;
  XSize, YSize, ml, hl: Integer;
  FPlanner: TCustomPlanner;
  SectionIdx: Integer;

begin
  Hi := PHintInfo(Message.LParam);
  CanShow := False;

  APlannerItem := ItemAtXY(Hi.CursorPos.X, Hi.CursorPos.Y, pr);

  FPlanner := TCustomPlanner(Owner);

  FLastHintPos := Point(Hi.CursorPos.X, Hi.CursorPos.Y);

  if Assigned(APlannerItem) and FPlanner.Header.ShowHint then
  begin
    s := APlannerItem.ItemText;
    if APlannerItem.Hint <> '' then
      s := APlannerItem.Hint;
    if IsRtf(s) then
    begin
      if not FPlanner.RichEdit.Visible then
      begin
        FPlanner.TextToRich(s);
        s := FPlanner.FRichEdit.Text;
      end;
    end;
    if IsHtml(APlannerItem, s, False) then
    begin
      //Change ? if HTML Hint is enabled ?
      if APlannerItem.Hint = '' then
        s := ConcatenateTextStrings(APlannerItem.Text);

      CR := ClientRect;
      if not FPlanner.HTMLHint then
      begin
        HTMLDrawEx(Canvas, s, CR, FPlanner.PlannerImages, 0, 0, -1, -1, 1, True,
          True, False, True, True, False, APlannerItem.WordWrap
          , False
          , 1.0, FPlanner.URLColor, clNone, clNone, clGray, Anchor,
          StrippedHTMLString, FocusAnchor, XSize, YSize, ml, hl, hr
          , cor, CID, CV, CT, FPlanner.FImageCache, FPlanner.FContainer, Handle
          );

        s := StrippedHTMLString;
      end;
    end;

{$IFNDEF VER90}
    Hi.HintStr := s;
    if Assigned(FPlanner.OnItemHint) then
      FPlanner.OnItemHint(FPlanner, APlannerItem, Hi.HintStr);
{$ENDIF}
    CanShow := True;
  end
  else
  begin
    SectionIdx := XYToSection(Hi.CursorPos.X, Hi.CursorPos.Y);

    if Assigned(OnHeaderHint) then
    begin
      OnHeaderHint(FPlanner, SectionIdx, Hi.HintStr);
      CanShow := Hi.HintStr <> '';
    end;
    //if Assigned(FPlanner.OnHeaderHint) then
    //begin
    //  FPlanner.OnHeaderHint(FPlanner, SectionIdx, Hi.HintStr);
    //  CanShow := Hi.HintStr <> '';
    //end;
  end;

  if FPlanner.HintColor <> clNone then
    Hi.HintColor := FPlanner.HintColor;

  Hi.HideTimeOut := FPlanner.HintPause;

  Message.Result := Ord(not CanShow);
end;

procedure TAdvHeader.WMNotify(var Message: TWMNotify);
var
  buffer: array [0 .. 255] of Char;
  pt: TPoint;
  plIt: TPlannerItem;
  di: PNMTTDispInfo;
  ATitle, AText: string;
  AIcon: Integer;
  cell: TPoint;
  len1, len2, i: Integer;
  FPlanner: TCustomPlanner;
  R: TRect;

begin
  with Message.NMHdr^ do
  case Code of
  TTN_NEEDTEXT:
    begin
      FPlanner := (Owner as TCustomPlanner);

      if not FPlanner.Balloon.Enable then
        Exit;
      di := PNMTTDispInfo(TMessage(Message).LParam);
      GetCursorPos(pt);
      pt := ScreenToClient(pt);

      plIt := ItemAtXY(pt.X, pt.Y, R);

//      cell := FPlanner.XYToCell(pt.X,pt.Y);

      cell.X := XYToSection(pt.X, pt.Y);
      cell.Y := -1;

      if Assigned(plIt) then
      begin
        ATitle := HTMLStrip(plIt.CaptionText);

        if IsRtf(plIt.NotesText) then
        begin
          if not FPlanner.RichEdit.Visible then
          begin
            FPlanner.TextToRich(plIt.NotesText);
            AText := FPlanner.FRichEdit.Text;
          end;
        end
        else
          AText := HTMLStrip(plIt.NotesText);
        len1 := Length(AText);
        len2 := SizeOf(FToolTipBuffer) div 4;

        // balloon tooltip cannot handle tabs well
        i := 1;
        while i < len1 do
        begin
          if (AText[i] = #9) then
            AText[i] := #32;
          Inc(i);
        end;

        i := 1;
        if AText <> '' then
          while ((AText[i] = #13) or (AText[i] = #10) or (AText[i] = #9)) do
            Inc(i);

        if len1 > len2 then
          AText := Copy(AText, i, len2 - 3) + '...'
        else
          if i > 1 then
            AText := Copy(AText, i, len1 - i + 1);
        AIcon := 1;
        // for some reason, balloon tips will not show multiline when there is no title  ...
        if ATitle = '' then
          ATitle := ' ';

        if Assigned(FPlanner.OnItemBalloon) then
          FPlanner.OnItemBalloon(FPlanner, plIt, ATitle, AText, AIcon);
      end
      else
      begin
        AText := '';
        ATitle := '';
        AIcon := 1;
        if Assigned(FPlanner.OnPlannerBalloon) then
          FPlanner.OnPlannerBalloon(FPlanner, cell.X, cell.Y, ATitle, AText, AIcon);
      end;
      strpcopy(FToolTipBuffer, AText);

      if Length(ATitle) > 99 then
        ATitle := Copy(ATitle, 1, 96) + '...';

      strpcopy(buffer, ATitle);
      di^.lpszText := @FToolTipBuffer;
      if FPlanner.Balloon.TextColor <> clNone then
        SendMessage(FHToolTip, TTM_SETTIPTEXTCOLOR, ColorToRGB(FPlanner.Balloon.TextColor), 0);
      if FPlanner.Balloon.BackgroundColor <> clNone then
        SendMessage(FHToolTip, TTM_SETTIPBKCOLOR, ColorToRGB(FPlanner.Balloon.BackgroundColor), 0);
      SendMessage(FHToolTip, TTM_SETTITLE, AIcon, LParam(@buffer));
    end;
  TTN_SHOW:
    begin
    end;
  TTN_POP:
    begin
    end;
  end;
end;

procedure TAdvHeader.WMLButtonDown(var Msg: TWMLButtonDown);
var
  SectionIndex: Integer;
  R, pr: TRect;
  plIt: TPlannerItem;
  nodrag: Boolean;
begin
  SectionIndex := XYToSection(Msg.XPos, Msg.YPos);

  R := GetSectionRect(SectionIndex);

  plIt := ItemAtXY(Msg.XPos, Msg.YPos, pr);

  nodrag := False;
  if Assigned(plIt) then
    nodrag := not plIt.ReadOnly;

  if FSectionDragDrop and not FDragging and not nodrag then
  begin
    FDragStart := SectionIndex;

    InflateRect(R, -2, -2);

    if (FDragStart >= FOffset) and PtInRect(R, Point(Msg.XPos, Msg.YPos)) then
    begin
      FDragging := True;
      Self.Cursor := crDrag;
      SetCapture(Self.Handle);
    end;
  end;
  inherited;
end;

procedure TAdvHeader.WMSize(var Msg: TWMSize);
begin
  inherited;
  if FSizing then
  begin
    with (Owner as TCustomPlanner) do
    begin
      FNoPositionSize := True;

      if Orientation = hoHorizontal then
        Header.Height := Self.Height
      else
        Header.Height := Self.Width;

      FNoPositionSize := False;

      HeaderHeightChange(Self.Height);
    end;
  end;
end;

procedure TAdvHeader.WMNCHitTest(var Msg: TWMNCHitTest);
var
  pt: TPoint;
begin
  inherited;

  FSizing := False;

  FHitTest := Point(Msg.XPos, Msg.YPos);

  if AllowSizing then
  begin
    pt := ScreenToClient(FHitTest);

    if Orientation = hoHorizontal then
    begin
      if (pt.Y >= Height - 2) then
      begin
        Msg.Result := HTBOTTOM;
        FSizing := True;
      end;
    end
    else
    begin
      if (pt.X >= Width - 2) then
      begin
        Msg.Result := HTRIGHT;
        FSizing := True;
      end;
    end;
  end;
end;

procedure TAdvHeader.WMSetCursor(var Msg: TWMSetCursor);
var
  Cur: HCURSOR;
  i: Integer;
  Y: Integer;

begin
  if (Cursor = crHandPoint) or (FDragging) then
  begin
    inherited;
    Exit;
  end;

  if Orientation = hoVertical then
  begin
    Cur := 0;
    FResizeSection := 0;
    FHitTest := ScreenToClient(FHitTest);
    Y := 2;
    with Msg do
      if HitTest = HTCLIENT then
      begin
        Inc(Y, SectionWidth[0]); // first fixed section

        for i := FLeftPos + 1 to Sections.Count - 2 do  // don't count last section
        begin
          Inc(Y, SectionWidth[i]);
          FMouseOffset := Y - (FHitTest.Y + 2);
          if Abs(FMouseOffset) < 4 then
          begin
            Cur := LoadCursor(0, IDC_SIZENS);
            FResizeSection := i;
            Break;
          end;
        end;
      end;

    FCanResize := (AllowResize or (csDesigning in ComponentState)) and (Cur <> 0);

    if FCanResize then
      SetCursor(Cur)
    else
    begin
      FMouseOffset := Self.Width - (FHitTest.X + 2);
      if (Abs(FMouseOffset) >= 4) and ((Owner as TCustomPlanner).PositionZoomWidth = 0) then
      begin
        if AllowResize then
          Msg.HitTest := Windows.HTNOWHERE;
        inherited;
      end
      else
        inherited;
    end;
  end
  else
  begin
    Cur := 0;
    FResizeSection := 0;
    FHitTest := ScreenToClient(FHitTest);
    Y := 2;

    with Msg do
      if HitTest = HTCLIENT then
      begin
        Inc(Y, SectionWidth[0]); // first fixed section

        for i := FLeftPos + 1 to Sections.Count - 2 do // don't count last section
        begin
          Inc(Y, SectionWidth[i]);

          FMouseOffset := Y - (FHitTest.X + 2);
          if Abs(FMouseOffset) < 4 then
          begin
            Cur := LoadCursor(0, IDC_SIZEWE);
            FResizeSection := i;
            Break;
          end;
        end;
      end;

      FCanResize := (AllowResize or (csDesigning in ComponentState)) and (Cur <> 0);

      if FCanResize then
        SetCursor(Cur)
      else
      begin
        FMouseOffset := Self.Width - (FHitTest.X + 2);

        if (Abs(FMouseOffset) >= 4) and ((Owner as TCustomPlanner).PositionZoomWidth = 0) then
        begin
          if AllowResize then
            Msg.HitTest := Windows.HTNOWHERE;
          inherited;
        end
        else
         inherited;
       end;
  end;
end;

procedure TAdvHeader.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var
  R, pr: TRect;
  APlannerItem: TPlannerItem;
  SectionIndex, EditIdx, ItemsX: Integer;
  FPlanner: TCustomPlanner;
  s: string;
  ScreenPoint: TPoint;
  CID, CV, CT: string;
  cor: TRect;
  FocusAnchor, Anchor, StrippedHTMLString: string;
  ml, hl: Integer; hr, tr, CR: TRect; XSize, YSize: Integer;
  Allow: Boolean; ImgSize, iw: Integer;
  AutoHandle: Boolean;

begin
  if ClassName = 'TAdvFooter' then
  begin
    inherited;
    Exit;
  end;

  SectionIndex := XYToSection(X, Y);

  if SectionIndex < 0 then
  begin
    inherited;
    Exit;
  end;

  R := GetSectionRect(SectionIndex);

  FPlanner := Owner as TCustomPlanner;

  if FPlanner.PositionGroup > 0 then
  begin
    if FPlanner.Header.GroupHeight = 0 then
    begin
      if (FPlanner.Sidebar.Position in [spTop]) then
        R.Left := R.Left + (R.Right - R.Left) div 2
      else
        R.Top := R.Top + (R.Bottom - R.Top) div 2;
    end
    else
    begin
      if (FPlanner.Sidebar.Position in [spTop]) then
        R.Left := R.Left + FPlanner.Header.GroupHeight
      else
        R.Top := R.Top + FPlanner.Header.GroupHeight;
    end;
  end;

  if (Button = mbLeft) and (Pos('</', Sections[SectionIndex]) > 0) then
  begin
    HTMLDrawEx(Canvas, Sections[SectionIndex], R, FPlanner.PlannerImages, X, Y, -1, -1, 1, True, False, False, False, False, False, True
    , False
    , 1, clBlue, clNone, clNone, clGray, Anchor, StrippedHTMLString, FocusAnchor, XSize, YSize, ml, hl, hr
    , CR, CID, CV, CT, FPlanner.FImageCache, FPlanner.FContainer, Handle
    );

    if (Anchor <> '') then
    begin
      FPlanner.HeaderAnchorClick(Self, SectionIndex, Anchor);
    end;
  end;

  if Button = mbRight then
  begin
    inherited;

    if Assigned(FOnRightClick) then
      FOnRightClick(Self, XYToSection(X, Y));

    APlannerItem := ItemAtXY(X, Y, pr);
    FPlanner := Owner as TCustomPlanner;

    ScreenPoint := ClientToScreen(Point(X, Y));

    if Assigned(APlannerItem) then
    begin
      with FPlanner do
        if Assigned(OnItemRightClick) then
          OnItemRightClick(Owner,APlannerItem);

      if Assigned(APlannerItem.PopupMenu) then
      begin
        if Assigned(FPlanner.OnItemPopupPrepare) then
          FPlanner.OnItemPopupPrepare(FPlanner, APlannerItem.PopupMenu, APlannerItem);

        FPlanner.PopupPlannerItem := APlannerItem;
        APlannerItem.PopupMenu.PopupComponent := FPlanner;
        APlannerItem.PopupMenu.Popup(ScreenPoint.X, ScreenPoint.Y);
      end;

      if (Assigned(FPlanner.FItemPopup)) then
      begin
        if Assigned(FPlanner.OnItemPopupPrepare) then
          FPlanner.OnItemPopupPrepare(FPlanner, FPlanner.ItemPopup, APlannerItem);

        FPlanner.PopupPlannerItem := APlannerItem;
        FPlanner.ItemPopup.PopupComponent := FPlanner;
        FPlanner.FItemPopup.Popup(ScreenPoint.X, ScreenPoint.Y);
      end;
    end
    else
    begin
      if Assigned(FPlanner.Header.PopupMenu) then
      begin
        FPlanner.Header.PopupMenu.PopupComponent := FPlanner;
        FPlanner.Header.PopupMenu.Popup(ScreenPoint.X, ScreenPoint.Y);
      end;
    end;
    Exit;
  end;

  if Button = mbLeft then
  begin
    if FCanResize {and (Orientation = hoVertical)} then
    begin
      SetCapture(Handle);
      Exit;
    end;
    if FPlanner.FGrid.FMemo.Visible then
      FPlanner.FGrid.FMemo.DoExit;

    APlannerItem := ItemAtXY(X, Y, pr);

    if Assigned(APlannerItem) then
    begin
      ImgSize := 0;
      if (APlannerItem.CaptionType <> ctNone) then
      begin
        tr := pr;
        tr.Right := tr.Right - FPlanner.ItemGap;
        tr.Bottom := tr.Top + 16;

        if APlannerItem.ShowDeleteButton and (R.Right - R.Left - ImgSize > 32) then
        begin
          tr.Left := tr.Right - FPlanner.DeleteGlyph.Width;
          if PtInRect(tr, Point(X, Y)) then
          begin
            if Assigned(FPlanner.OnItemDelete) then
              FPlanner.OnItemDelete(Self, APlannerItem);

            if FPlanner.AutoInsDel then
            begin
              if Assigned(FPlanner.OnItemDeleted) then
                FPlanner.OnItemDeleted(Self, APlannerItem);
              FPlanner.FreeItem(APlannerItem);
            end;

            Exit;
          end;

          tr.Right := tr.Right - FPlanner.DeleteGlyph.Width;
        end;

        if APlannerItem.Attachement <> '' then
        begin
          tr.Left := tr.Right - FPlanner.AttachementGlyph.Width;

          if PtInRect(tr, Point(X, Y)) then
          begin
            AutoHandle := True;

            if Assigned(FPlanner.FOnItemAttachementClick) then
              FPlanner.FOnItemAttachementClick(FPlanner, APlannerItem, APlannerItem.Attachement, AutoHandle);
            if AutoHandle then
              ShellExecute(0, 'open', PChar(APlannerItem.Attachement), nil, nil, SW_NORMAL);
            Exit;
          end;

          tr.Right := tr.Right - FPlanner.AttachementGlyph.Width;
        end;

        if APlannerItem.URL <> '' then
        begin
          tr.Left := tr.Right - FPlanner.URLGlyph.Width;

          if PtInRect(tr, Point(X, Y)) then
          begin
            AutoHandle := True;

            if Assigned(FPlanner.FOnItemURLClick) then
              FPlanner.FOnItemURLClick(FPlanner, APlannerItem,  APlannerItem.URL, AutoHandle);
            if AutoHandle then
              ShellExecute(0, 'open', PChar(APlannerItem.Attachement), nil, nil, SW_NORMAL);
            Exit;
          end;

          tr.Right := tr.Right - FPlanner.AttachementGlyph.Width;
        end;

        if APlannerItem.URL <> '' then
        begin
          tr.Left := tr.Right - FPlanner.URLGlyph.Width;

          if PtInRect(tr, Point(X, Y)) then
          begin
            AutoHandle := True;

            if Assigned(FPlanner.FOnItemURLClick) then
              FPlanner.FOnItemURLClick(FPlanner, APlannerItem,  APlannerItem.URL, AutoHandle);
            if AutoHandle then
              ShellExecute(0, 'open', PChar(APlannerItem.URL), nil, nil, SW_NORMAL);
            Exit;
          end;
        end;
      end;

      ImgSize := 0;

      if Assigned(FPlanner.PlannerImages) and ((APlannerItem.ImageID >= 0) or (APlannerItem.FImageIndexList.Count > 0)) then
      begin
        iw := FPlanner.PlannerImages.Width;
        if APlannerItem.ImagePosition = ipHorizontal then
          ImgSize := (iw * APlannerItem.FImageIndexList.Count) + iw
        else
          ImgSize := iw;
      end;

      if Assigned(FPlanner.PlannerImages) and Assigned(FPlanner.FOnItemImageClick) then
      begin
        if (Y > pr.Top) and (Y < pr.Top + FPlanner.PlannerImages.Height + 3) and
           (X >= pr.Left) and (X < pr.Left + ImgSize) and ((APlannerItem.ImageID >= 0) or
           (APlannerItem.FImageIndexList.Count > 0)) then
        begin
          iw := FPlanner.PlannerImages.Width + 1;

          if (X < pr.Left + ImgSize) and (iw > 0) then
          begin
            if (((X - pr.Left + 8) div iw) <= APlannerItem.FImageIndexList.Count) or (APlannerItem.ImageID >= 0) then
              FPlanner.FOnItemImageClick(FPlanner, APlannerItem, ((X - pr.Left + 8) div iw) - 1);
          end;
          Exit;
        end;
      end;

      if IsHtml(APlannerItem, APlannerItem.ItemText, False) and APlannerItem.Selected then
      begin
        pr.Top := pr.Top + 4 + APlannerItem.FCaptionHeight;
        pr.Left := pr.Left + FPlanner.TrackWidth;
{$IFDEF TMSDEBUG}
        outputdebugstring(PChar('height:' + IntToStr(APlannerItem.FCaptionHeight)));
        outputdebugstring(PChar(IntToStr(pr.Left) + ':' + IntToStr(pr.Top) + ':' + IntToStr(pr.Right) + ':' + IntToStr(pr.Bottom)));
        outputdebugstring(PChar('xy:' + IntToStr(X) + ':' + IntToStr(Y) + ':' + APlannerItem.ItemText));
{$ENDIF}
        if HTMLDrawEx(Canvas, APlannerItem.ItemText, pr, FPlanner.PlannerImages, X, Y, -1, -1, 1, True, False,
          False, True, True, False, APlannerItem.WordWrap
          , False
          , 1.0, FPlanner.URLColor, clNone, clNone, clGray, Anchor, StrippedHTMLString, FocusAnchor, XSize, YSize, ml, hl, hr
          , cor, CID, CV, CT, FPlanner.FImageCache, FPlanner.FContainer, Handle
          ) then
        begin
            if Assigned(FPlanner.OnItemAnchorClick) then
              FPlanner.OnItemAnchorClick(FPlanner,
            APlannerItem, Anchor);
            Exit;
        end;
      end;

      if Cursor = crSizeAll then
      begin
        FMouseDownMove := True;
        FDragItem := APlannerItem;
        Exit;
      end;

      with (Owner as TCustomPlanner) do
      begin
        if APlannerItem <> Items.Selected then
          Items.UnSelectAll;
        Items.Selected := APlannerItem;

        if Assigned(OnItemLeftClick) then
          OnItemLeftClick(Owner, APlannerItem);

        if not APlannerItem.NotEditable and (APlannerItem.Selected or FPlanner.EditDirect) then
          StartEdit(pr, APlannerItem, X, Y + TextHeight);

        APlannerItem.Selected := True;

        ItemSelected(APlannerItem);
      end;
    end;

    if FSectionEdit and not(csDesigning in ComponentState) then
    begin
      if FInplaceEdit.Visible then
      begin
        EditIdx := FEditSection;
        // EditIdx := GetSectionIdx(FEditSection);

        s := LFToCLF(FInplaceEdit.Text);

        if Assigned(FPlanner.OnHeaderEndEdit) then
          FPlanner.OnHeaderEndEdit(FPlanner, EditIdx, s);

        (Owner as TCustomPlanner).FEditMode := False;

        Sections[EditIdx] := s;
        SectionWidth[EditIdx] := FEditWidth;
      end;

      FEditSection := XYToSection(X, Y);
      R := GetSectionRect(FEditSection);

      //EditIdx := GetSectionIdx(FEditSection);

      EditIdx := FEditSection;

      InflateRect(R, -2, -2);
      OffsetRect(R, 2, 2);

      if EditIdx >= Self.Sections.Count then
        s := ''
      else
        s := CLFToLF(Self.Sections[EditIdx]);

      FPlanner.FEditMode := True;

      if Assigned(FPlanner.OnHeaderStartEdit) then
        FPlanner.OnHeaderStartEdit(FPlanner, EditIdx, s);
      FInplaceEdit.BiDiMode := FPlanner.BiDiMode;
      FInplaceEdit.Top := R.Top;
      FInplaceEdit.Left := R.Left;
      FInplaceEdit.Width := R.Right - R.Left - 2;
      FInplaceEdit.Height := R.Bottom - R.Top - 2;
      FInplaceEdit.Color := Self.Color;
      FInplaceEdit.Font.Assign(Self.Font);
      FInplaceEdit.Text := s;
      FInplaceEdit.BorderStyle := bsNone;
      FInplaceEdit.Visible := True;
      FInplaceEdit.SelectAll;

      FEditWidth := SectionWidth[FEditSection];

      FInplaceEdit.SetFocus;
    end;

    if FPlanner.Sidebar.Orientation = soVertical then
    begin
      if SectionIndex > FPlanner.FGrid.ColCount then
        SectionIndex := -1;
    end
    else
    begin
      if SectionIndex >= FPlanner.FGrid.RowCount then
        SectionIndex := -1;
    end;

    if Zoom and (SectionIndex > 0) and (FPlanner.PositionWidth > 0) then
    begin
      if Cursor = crZoomIn then
      begin
        ZoomCol := SectionIndex;
        Allow := True;
        if Assigned(FPlanner.OnPlannerBeforePositionZoom) then
          FPlanner.OnPlannerBeforePositionZoom(FPlanner, ZoomCol, True, Allow);

        if Allow then
        begin
          FPlanner.PositionWidths[SectionIndex - 1] := FPlanner.PositionZoomWidth;
          ZoomCol := SectionIndex;
          if Assigned(FPlanner.OnPlannerPositionZoom) then
            FPlanner.OnPlannerPositionZoom(FPlanner, ZoomCol, True);
        end;
      end
      else
      begin
        ZoomCol := SectionIndex;
        Allow := True;
        if Assigned(FPlanner.OnPlannerBeforePositionZoom) then
          FPlanner.OnPlannerBeforePositionZoom(FPlanner, ZoomCol, True, Allow);
        if Allow then
        begin
          if FPlanner.PositionAutoSize and (FPlanner.PositionWidth > 0) then
          begin
            ItemsX := FPlanner.Items.MaxItemsInPos(SectionIndex - 1);
            FPlanner.PositionWidths[SectionIndex - 1] := Max(1,ItemsX) * FPlanner.PositionWidth;
          end
          else
            FPlanner.PositionWidths[SectionIndex - 1] := FPlanner.PositionWidth;
          if Assigned(FPlanner.OnPlannerPositionZoom) then
            FPlanner.OnPlannerPositionZoom(FPlanner, ZoomCol, False);
          ZoomCol := -1;
        end;
      end;
    end;
  end;

  inherited;
  {
  if Assigned(FOnClick) then
    FOnClick(Self, XYToSection(X, Y));
  }
end;

procedure TAdvHeader.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var
  FDragStop: Integer;
begin
  if ClassName = 'TAdvFooter' then
  begin
    inherited;
    Exit;
  end;
  if FCanResize then
  begin
    ReleaseCapture;
    Sized(FResizeSection, SectionWidth[FResizeSection]);
    FCanResize := False;
    inherited;
    Exit;
  end;

  inherited;

  if Assigned(FOnClick) and (Button = mbLeft) then
    FOnClick(Self, XYToSection(X, Y));

  if FSectionDragDrop and FDragging then
  begin
    FDragging := False;
    Cursor := crDefault;
    ReleaseCapture;

    if Assigned(FOnDragDrop) then
    begin
      FDragStop := XYToSection(X, Y);
      if (FDragStop >= FOffset) and (FDragStop <> FDragStart) then
        FOnDragDrop(Self, FDragStart, FDragStop);
    end;
    Exit;
  end;
  FMouseDownMove := False;
end;

procedure TAdvHeader.WMLButtonDblClk(var Message: TWMLButtonDblClk);
var
  APlannerItem: TPlannerItem;
  pr: TRect;
begin
  APlannerItem := ItemAtXY(Message.XPos, Message.YPos, pr);
  if Assigned(APlannerItem) then
  begin
    with (Owner as TCustomPlanner) do
      if Assigned(OnItemDblClick) then
        OnItemDblClick(Owner, APlannerItem);
  end
  else
  if Assigned(FOnDblClick) then
    FOnDblClick(Self, XYToSection(Message.XPos, Message.YPos));
end;


procedure TAdvHeader.MouseMove(Shift: TShiftState; X, Y: Integer);
var
  SectionIdx: Integer;
  HdrYStart: Integer;
  FPlanner: TCustomPlanner;
  PosOk: Boolean;
  R, pr: TRect;
  APlannerItem: TPlannerItem;
  Allow: Boolean;
  i: Integer;
  sw: Integer;
  AbsPos: Integer;
  MinPos: Integer;
  MaxPos: Integer;
  CID, CV, CT: string;
  cor: TRect;
  FocusAnchor, Anchor, StrippedHTMLString: string;
  ml, hl: Integer;
  hr, tr, CR: TRect;
  XSize, YSize: Integer;

begin
  if (ClassName = 'TAdvFooter') then
  begin
    inherited;
    Exit;
  end;

  inherited;
  if (GetCapture = Handle) and FCanResize then
  begin
    if (Orientation = hoVertical) then
    begin
      // absolute position of this item
      AbsPos := 2;
      Inc(AbsPos, SectionWidth[0]);

      for i := FLeftPos + 1 to FResizeSection do
        Inc(AbsPos, SectionWidth[i]);

      if FResizeSection > 0 then
        MinPos := AbsPos - SectionWidth[FResizeSection] + 2
      else
        MinPos := 2;

      MaxPos := ClientHeight - 2;
      if Y < MinPos then
        Y := MinPos;
      if Y > MaxPos then
        Y := MaxPos;

      sw := SectionWidth[FResizeSection];
      Dec(sw, (AbsPos - Y - 2) - FMouseOffset);
      SectionWidth[FResizeSection] := sw;
      Sizing(FResizeSection, SectionWidth[FResizeSection]);
      Refresh;
    end
    else
    begin
      { absolute position of this item }
      AbsPos := 2;
      Inc(AbsPos, SectionWidth[0]);

      for i := FLeftPos + 1 to FResizeSection do
        Inc(AbsPos, SectionWidth[i]);

      if FResizeSection > 0 then
        MinPos := AbsPos - SectionWidth[FResizeSection] + 2
      else
        MinPos := 2;

      MaxPos := ClientWidth - 2;
      if X < MinPos then
        X := MinPos;
      if X > MaxPos then
        X := MaxPos;

      sw := SectionWidth[FResizeSection];
      Dec(sw, (AbsPos - X - 2) - FMouseOffset);
      SectionWidth[FResizeSection] := sw;
      Sizing(FResizeSection, SectionWidth[FResizeSection]);
      Refresh;
    end;
  end;
  if FDragging then
  begin
    Cursor := crDrag;
    Exit;
  end;

  if (FLastHintPos.X <> -1) then
    if (Abs(X - FLastHintPos.X) > 4) or (Abs(Y - FLastHintPos.Y) > 4) then
    begin
      Application.CancelHint;
      FLastHintPos := Point(-1, -1);
    end;

    SectionIdx := XYToSection(X, Y);
    FPlanner := Owner as TCustomPlanner;

    if Zoom then
    begin
      HdrYStart := 0;
      if FPlanner.PositionGroup > 0 then
        HdrYStart := TextHeight shr 1;

      if FPlanner.Sidebar.Orientation = soVertical then
        PosOk := (Y < TextHeight) and (Y >= HdrYStart) and (SectionIdx < FPlanner.FGrid.ColCount)
      else
        PosOk := (X < TextHeight) and (X >= HdrYStart) and (SectionIdx < FPlanner.FGrid.RowCount);

      if PosOk and (SectionIdx > 0) then
      begin
        if (SectionWidth[SectionIdx] <> FPlanner.PositionZoomWidth) then
          Cursor := crZoomIn
        else
          Cursor := crZoomOut;

        Exit;
      end
      {
      else
        if (Cursor <> crDefault) and not FDragging then
          Cursor := crDefault;
      }
    end;

    R := GetSectionRect(SectionIdx);

    if FPlanner.PositionGroup > 0 then
    begin
      if FPlanner.Header.GroupHeight = 0 then
      begin
        if (FPlanner.Sidebar.Position in [spTop]) then
          R.Left := R.Left + (R.Right - R.Left) div 2
        else
          R.Top := R.Top + (R.Bottom - R.Top) div 2;
      end
      else
      begin
        if (FPlanner.Sidebar.Position in [spTop]) then
          R.Left := R.Left + FPlanner.Header.GroupHeight
        else
          R.Top := R.Top + FPlanner.Header.GroupHeight;
      end;
    end;

    if (SectionIdx >= 0) and (Pos('</', Sections[SectionIdx]) > 0) then
    begin
      HTMLDrawEx(Canvas, Sections[SectionIdx], R, FPlanner.PlannerImages, X, Y, -1, -1, 1, True, False, False, False, False, False, True
        , False
        , 1, clBlue, clNone, clNone, clGray, Anchor, StrippedHTMLString, FocusAnchor, XSize, YSize, ml, hl, hr
        , CR, CID, CV, CT, FPlanner.FImageCache, FPlanner.FContainer, Handle
        );

      if (Anchor <> '') then
      begin
        Cursor := crHandPoint;
        if (FHeaderAnchor <> Anchor) then
        begin
          FPlanner.HeaderAnchorEnter(FPlanner, SectionIdx, Anchor);
          FHeaderAnchor := Anchor;
        end;
        Exit;
      end
      else
      begin
        if FHeaderAnchor <> '' then
          FPlanner.HeaderAnchorLeave(FPlanner, SectionIdx, FHeaderAnchor);
      end;
      FHeaderAnchor := Anchor;
    end;

    APlannerItem := ItemAtXY(X, Y, pr);

    if (FBalloonItem <> APlannerItem) and(FPlanner.Balloon.Enable) then
    begin
      // mouse over remove balloon here
      SendMessage(FHToolTip, TTM_POP, 0, 0);
    end;

    FBalloonItem := APlannerItem;

    if Assigned(APlannerItem) then
    begin
      if IsHtml(APlannerItem, APlannerItem.ItemText, False) and APlannerItem.Selected then
      begin
        pr.Top := pr.Top + 4 + APlannerItem.FCaptionHeight;
        pr.Left := pr.Left + FPlanner.TrackWidth;
{$IFDEF TMSDEBUG}
        outputdebugstring(PChar('height:' + IntToStr(APlannerItem.FCaptionHeight)));
        outputdebugstring(PChar(IntToStr(pr.Left) + ':' + IntToStr(pr.Top) + ':' + IntToStr(pr.Right) + ':' + IntToStr(pr.Bottom)));
        outputdebugstring(PChar('xy:' + IntToStr(X) + ':' + IntToStr(Y) + ':' + APlannerItem.ItemText));
{$ENDIF}
        if HTMLDrawEx(Canvas, APlannerItem.ItemText, pr, FPlanner.PlannerImages, X, Y, -1, -1, 1, True, False, False, True, True, False, APlannerItem.WordWrap
          , False
          , 1.0, FPlanner.URLColor, clNone, clNone, clGray, Anchor, StrippedHTMLString, FocusAnchor, XSize, YSize, ml, hl, hr
          , cor, CID, CV, CT, FPlanner.FImageCache, FPlanner.FContainer, Handle
          ) then
          begin
            Cursor := crHandPoint;
            if FOldAnchor <> Anchor then
              if Assigned(FPlanner.OnItemAnchorEnter) then
                FPlanner.OnItemAnchorEnter(FPlanner, APlannerItem, Anchor);
            FOldAnchor := Anchor;
            FAnchorItem := APlannerItem;
            Exit;
          end;
        end;

        if (APlannerItem.CaptionType <> ctNone) then
        begin
          tr := pr;
          tr.Bottom := tr.Top + 16;
          tr.Right := tr.Right - FPlanner.ItemGap;

          if APlannerItem.ShowDeleteButton then
          begin
            tr.Left := tr.Right - FPlanner.DeleteGlyph.Width;

            if PtInRect(tr, Point(X, Y)) then
            begin
              if Self.Cursor <> crHandPoint then
              begin
                Self.Cursor := crHandPoint;
              end;
              Exit;
            end;
            tr.Right := tr.Right - FPlanner.DeleteGlyph.Width;
          end;

          if APlannerItem.Attachement <> '' then
          begin
            tr.Left := tr.Right - FPlanner.AttachementGlyph.Width;

            if PtInRect(tr, Point(X, Y)) then
            begin
              if Self.Cursor <> crHandPoint then
              begin
                Self.Cursor := crHandPoint;
              end;
              Exit;
            end;

            tr.Right := tr.Right - FPlanner.AttachementGlyph.Width;
          end;

          if APlannerItem.URL <> '' then
          begin
            tr.Left := tr.Right - FPlanner.URLGlyph.Width;

            if PtInRect(tr, Point(X, Y)) then
            begin
              if Self.Cursor <> crHandPoint then
              begin
                Self.Cursor := crHandPoint;
              end;
              Exit;
            end;
          end;
        end;
     end;

  if (FOldAnchor <> '') then
  begin
    if Assigned(FPlanner.OnItemAnchorExit) then
      FPlanner.OnItemAnchorExit(FPlanner, FAnchorItem, FOldAnchor);
    FOldAnchor := '';
    FAnchorItem := nil;
  end;

  if FMouseDownMove and Assigned(FDragItem) and not Self.Dragging and FPlanner.DragItem then
  begin
    Allow := True;

    if Assigned(FPlanner.OnItemDrag) then
      FPlanner.OnItemDrag(FPlanner, FPlanner.Items.Selected, Allow);

    if Allow then
    begin
      FPlanner.GridControl.HintHide;

      if FPlanner.DragItemImage then
      begin
        FPlanner.CreateDragImage(FPlanner.Items.Selected);
        FPlanner.Items.Selected.Visible := false;
      end;

      FPlanner.BeginDrag(True, -1);
      FMouseDownMove := False;
      Exit;
    end;

    Exit;
  end;

  if Assigned(APlannerItem) then
  begin
    if APlannerItem.TrackVisible and APlannerItem.Selected then
    begin
      if (X < pr.Left + APlannerItem.FPlanner.TrackWidth) or (Y < pr.Top + APlannerItem.FCaptionHeight) then
        Cursor := crSizeAll
      else
        Cursor := crDefault;
    end
    else
      Cursor := crDefault;
  end
  else
    Cursor := crDefault;
end;

procedure TAdvHeader.SetItemHeight(const value: Integer);
begin
  FItemHeight := value;
  Invalidate;
end;

procedure TAdvHeader.SetTextHeight(const value: Integer);
begin
  FTextHeight := value;
  Invalidate;
end;

function TAdvHeader.ItemAtXY(X, Y: Integer; var ARect: TRect): TPlannerItem;
var
  SectionIndex: Integer;
  R, pr: TRect;
  APlannerItem: TPlannerItem;

begin
  Result := nil;

  SectionIndex := XYToSection(X, Y);
  R := GetSectionRect(SectionIndex);

  with (Owner as TCustomPlanner) do
  begin
    APlannerItem := Items.HeaderFirst(SectionIndex - 1);

    InflateRect(R, -2, -2);
    pr := R;

    if Orientation = hoHorizontal then
      pr.Top := R.Top + FTextHeight
    else
      pr.Left := R.Left + FTextHeight;

    while Assigned(APlannerItem) do
    begin
      pr.Bottom := pr.Top + FItemHeight;

      if PtInRect(pr, Point(X, Y)) then
      begin
        ARect := pr;
        Result := APlannerItem;
        Break;
      end;
      APlannerItem := Items.HeaderNext(SectionIndex - 1);
      pr.Top := pr.Bottom;
    end;
  end;
end;

procedure TAdvHeader.StopEdit;
var
  FPlanner: TCustomPlanner;
begin
  FPlanner := Owner as TCustomPlanner;

  with FPlanner.FGrid do
  begin
    if FMemo.Visible then
    begin
      FMemo.DoExit;
      FMemo.Visible := False;
    end;
  end;
end;

procedure TAdvHeader.StartEdit(ARect: TRect;  APlannerItem: TPlannerItem; X, Y: Integer);
var
  ColumnHeight, ih, iw, ew: Integer;
  s: string;
  ER: TRect;
  FPlanner: TCustomPlanner;

begin
  if APlannerItem = nil then
    Exit;

  FPlanner := Owner as TCustomPlanner;

  if Assigned(APlannerItem.Editor) then
  begin
    if APlannerItem.Editor.EditorUse = euAlways then
    begin
      FPlanner.FEditMode := True;

      if Assigned(FPlanner.OnItemStartEdit) then
      begin
        FPlanner.OnItemStartEdit(Self, APlannerItem);
      end;

      APlannerItem.Editor.Edit(FPlanner, APlannerItem);

      if Assigned(FPlanner.OnItemEndEdit) then
        FPlanner.OnItemEndEdit(Self, APlannerItem);

      FPlanner.FEditMode := False;
      Exit;
    end;
  end;

  if FPlanner.InplaceEdit = ieNever then
    Exit;

  FPlanner.FEditMode := True;

  if Assigned(FPlanner.OnItemStartEdit) then
    FPlanner.OnItemStartEdit(Self, APlannerItem);

  ColumnHeight := 0;
  ih := 0;
  iw := 0;
  ew := 0;

  case APlannerItem.Shape of
  psRounded: ew := ew + (CORNER_EFFECT shr 1) - 1;
  psHexagon: ew := ew + CORNER_EFFECT;
  end;

  if ((APlannerItem.ImageID >= 0) or (APlannerItem.FImageIndexList.Count > 0)) and
    Assigned(FPlanner.PlannerImages) then
  begin
    ih := FPlanner.PlannerImages.Height + 2;
    iw := FPlanner.PlannerImages.Width + 2;
  end;

  if (APlannerItem.CaptionType <> ctNone) or (APlannerItem.FImageIndexList.Count > 1) then
  begin
    Canvas.Font.Assign(APlannerItem.CaptionFont);
    ColumnHeight := Canvas.TextHeight('gh') + 2;
    iw := 0;
  end
  else
    ih := 0;

  if (ih > ColumnHeight) then
    ColumnHeight := ih;

  s := APlannerItem.Text.Text;

  with FPlanner.FGrid do
  begin
    if IsRtf(s) or (APlannerItem.InplaceEdit = peRichText) then
    begin
      FPlanner.FRichEdit.Parent := Self;
      FPlanner.FRichEdit.ScrollBars := FPlanner.EditScroll;
      FPlanner.FRichEdit.PlannerItem := APlannerItem;
      FPlanner.TextToRich(s);
      FPlanner.FRichEdit.Top := ARect.Top + 3 + ColumnHeight;
      FPlanner.FRichEdit.Left := ARect.Left;
      FPlanner.FRichEdit.Width := ARect.Right - ARect.Left - 3;
      FPlanner.FRichEdit.Height := ItemHeight - 3;

      FPlanner.FRichEdit.Visible := True;
      BringWindowToTop(FPlanner.FRichEdit.Handle);
      FPlanner.FRichEdit.SetFocus;
      FPlanner.FRichEdit.SelectAll;
    end
    else
      case APlannerItem.InplaceEdit of
        {
        peMaskEdit, peEdit:
          begin
            if APlannerItem.InplaceEdit = peMaskEdit then
              FMaskEdit.EditMask := APlannerItem.EditMask
            else
              FMaskEdit.EditMask := '';
            FMaskEdit.Font.Assign(FPlanner.Font);
            if APlannerItem.ShowSelection then
              FMaskEdit.Color := APlannerItem.SelectColor
            else
              FMaskEdit.Color := APlannerItem.Color;
            FMaskEdit.PlannerItem := APlannerItem;
            FMaskEdit.Top := ARect.Top + 6 + ColumnHeight;
            FMaskEdit.Left := ARect.Left + tw + 1 + iw + ew;
            FMaskEdit.Width := ARect.Right - ARect.Left - tw - 3 - FPlanner.FItemGap -
              iw - 2 * ew;
            FMaskEdit.Height := (APlannerItem.ItemEnd - APlannerItem.ItemBegin) * RowHeights[0] - 8
              - ColumnHeight;
            FMaskEdit.BorderStyle := bsNone;
            FMaskEdit.Visible := True;
            if (APlannerItem.Text.Count > 0) then
              FMaskEdit.Text := APlannerItem.Text[0];
            BringWindowToTop(FMaskEdit.Handle);
            FMaskEdit.SetFocus;
          end;
        }
        peMemo, peMaskEdit, peEdit:
          begin
            FMemo.Parent := Self;
            FMemo.ScrollBars := FPlanner.EditScroll;
            FMemo.BiDiMode := FPlanner.BiDiMode;
            FMemo.Font.Assign(APlannerItem.Font);
            if APlannerItem.ShowSelection then
              FMemo.Color := APlannerItem.SelectColor
            else
              FMemo.Color := APlannerItem.Color;
            FMemo.PlannerItem := APlannerItem;
            FMemo.Top := ARect.Top + 3 + ColumnHeight;
            FMemo.Left := ARect.Left + 1 + iw + ew;
            FMemo.Width := ARect.Right - ARect.Left - 3;
            FMemo.Height := ItemHeight - 6;
            FMemo.BorderStyle := bsNone;
            FMemo.Visible := True;
            BringWindowToTop(FMemo.Handle);
            FMemo.Lines.Text := HTMLStrip(APlannerItem.Text.Text);
            FMemo.SetFocus;
            SetEditDirectSelection(ARect, X, Y);
          end;
        peCustom:
          begin
            ER.Left := ARect.Left + 3;
            ER.Top := ARect.Top + 3  + ColumnHeight;
            ER.Right := ARect.Right - 3;
            ER.Bottom := ARect.Top + ItemHeight - 6;
            if Assigned(FPlanner.FOnCustomEdit) then
              FPlanner.FOnCustomEdit(Self,ER,APlannerItem);
          end;
      end;
  end;
end;

function TAdvHeader.GetSectionIdx(X: Integer): Integer;
var
  FPlanner: TCustomPlanner;
begin
  FPlanner := Owner as TCustomPlanner;

  if FPlanner.Sidebar.Position = spTop then
    Result := X + FPlanner.FGrid.TopRow - 1
  else
    Result := X + FPlanner.FGrid.LeftCol - 1;
end;

procedure TAdvHeader.SetFixedColor(const value: TColor);
begin
  FFixedColor := value;
  Invalidate;
end;

procedure TAdvHeader.SetFixedHeight(const value: Integer);
begin
  FFixedHeight := value;
  Invalidate;
end;

procedure TAdvHeader.SetShowFixed(const value: Boolean);
begin
  FShowFixed := value;
  Invalidate;
end;

procedure TAdvHeader.SetColorTo(const value: TColor);
begin
  FColorTo := value;
  Invalidate;
end;

procedure TAdvHeader.SetRotate(const value: Boolean);
begin
  FRotate := value;
  Invalidate;
end;

procedure TAdvHeader.DragOver(Source: TObject; X, Y: Integer; State: TDragState;
  var Accept: Boolean); var FPlanner: TCustomPlanner; SectionIdx: Integer;
begin
  inherited;
  FPlanner := (Owner as TCustomPlanner);

  Accept := Source = FPlanner;

  SectionIdx := XYToSection(X, Y);

  if Assigned(FPlanner.OnDragOverHeader) then
    FPlanner.OnDragOverHeader(FPlanner, Source, SectionIdx, State, Accept);
end;

procedure TAdvHeader.DragDrop(Source: TObject; X, Y: Integer);
var
  FPlanner: TCustomPlanner;
  SectionIdx: Integer;
begin
  inherited;

  FPlanner := (Owner as TCustomPlanner);

  SectionIdx := XYToSection(X, Y);

  if Assigned(FPlanner.OnDragDropHeader) then
    FPlanner.OnDragDropHeader(FPlanner, Source, SectionIdx);

  if (Source = FPlanner) then
  begin
    if Assigned(FPlanner.Items.Selected) then
    begin
      FPlanner.Items.Selected.InHeader := True;
      FPlanner.Items.Selected.ItemPos := SectionIdx - 1;
      FPlanner.Items.Selected.Update;
    end;
  end;
end;

{ TAdvFooter }
procedure TAdvFooter.BeginUpdate;
begin
  Inc(FUpdateCount);
end;

constructor TAdvFooter.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  FUpdateCount := 0;
end;

procedure TAdvFooter.EndUpdate;
begin
  if FUpdateCount > 0 then
  begin
    Dec(FUpdateCount);
    if FUpdateCount = 0 then
      Invalidate;
  end;
end;

procedure TAdvFooter.Paint;
var
  SectionIndex, w, AIdx, BIdx, MergeNum, GPos, Err: Integer;
  s: string;
  CT, CID, CV: string;
  CR: TRect;
  DrawFlags: dword;
  R: TRect;
  pr: TRect;
  HorizontalAlign: Word;
  VerticalAlign: Word;
  AllPainted: Boolean;
  DoDraw: Boolean;
  Anchor, Strip, FocusAnchor: string;
  ml, hl, XSize, YSize: Integer;
  hr: TRect;
  Planner: TCustomPlanner;
  gs: TGaugeSettings;
  txtdraw: Boolean;
  paintcompl: Boolean;
  startsection: Integer;

begin
  if FUpdateCount > 0 then
    Exit;

  Planner := Owner as TCustomPlanner;

  with Canvas do
  begin
    Font.Assign(Planner.Footer.Font);
    Brush.Color := FColor;

    if FLineColor = clNone then
      Pen.Color := FColor
    else
      Pen.Color := FLineColor;

    Pen.Width := 1;
    SectionIndex := 0;

    if (Orientation = hoHorizontal) then
      R := Rect(0, 0, 0, ClientHeight)
    else
      R := Rect(0, 0, ClientWidth, 0);

    AIdx := 0;
    w := 0;
    s := '';

    HorizontalAlign := AlignToFlag(FAlignment);
    VerticalAlign := 0;

    AllPainted := False;

    repeat
      MergeNum := 1;
      paintcompl := True;

      s := '';

      if (SectionIndex + FLeftPos < Sections.Count) and (SectionIndex + FLeftPos <= Planner.Positions) then
      begin
        if (SectionIndex > 0) or (Flat and (Orientation = hoVertical)) then
          w := SectionWidth[SectionIndex + FLeftPos]
        else
        begin
          if (Orientation = hoHorizontal) then
            w := SectionWidth[SectionIndex] - 1
          else
            w := SectionWidth[SectionIndex] + 1;
        end;

        VerticalAlign := VAlignToFlag(FVAlignment);

        if FOffset = 1 then
        begin
          if (SectionIndex < Sections.Count - 1 - FLeftPos) and (SectionIndex > 0) then
          begin
            AIdx := SectionIndex + FLeftPos;
            s := Sections[AIdx];
          end
          else
          begin
            AIdx := -1;
            s := '';
          end;
        end
        else
        begin
          if (SectionIndex < Sections.Count - FLeftPos) then
            AIdx := SectionIndex + 1 + FLeftPos - 1
          else
            AIdx := 0;
          s := Sections[AIdx];
        end;

        if SectionIndex < FOffset then
          s := '';

        if (Planner.Sidebar.Position in [spRight]) and (SectionIndex >= Sections.Count - 2) then
          s := '';

        if (Pos('#', s) = 1) and (AIdx > 0) then
        begin
          BIdx := AIdx - 1;
          while (BIdx >= 0) and (Pos('#', Sections[BIdx]) = 1) do
          begin
            Dec(BIdx);
          end;
          s := Sections[BIdx];
        end;

        if AIdx <> -1 then
        begin
          BIdx := AIdx + 1;
          while BIdx < Sections.Count do
          begin
            if Pos('#', Sections[BIdx]) = 1 then
            begin
              w := w + SectionWidth[SectionIndex];
              Inc(MergeNum);
            end;
            Inc(BIdx);
          end;
        end;

        Inc(SectionIndex, MergeNum);
      end;

      if (Orientation = hoHorizontal) then
      begin
        R.Left := R.Right;
        Inc(R.Right, w);
        if (ClientWidth - R.Right < 2) or (SectionIndex + FLeftPos = Sections.Count) then
        begin
          R.Right := ClientWidth;
          AllPainted := True;
        end;
        if R.Right - R.Left < 32 then
          paintcompl := False;
      end
      else
      begin
        R.Top := R.Bottom;
        Inc(R.Bottom, w);

        if (ClientHeight - R.Bottom < 2) or (SectionIndex + FLeftPos = Sections.Count) then
        begin
          R.Bottom := ClientHeight;
          AllPainted := True;
        end;

        if R.Bottom - R.Top < 32 then
          paintcompl := False;
      end;

      pr := R;

      if FShowFixed and (SectionIndex > 1) then
      begin
        Canvas.Brush.Color := FFixedColor;

        if Orientation = hoHorizontal then
          R.Top := R.Bottom - FFixedHeight
        else
          R.Left := R.Right - FFixedHeight;

        FillRect(R);

        R := pr;

        if Orientation = hoHorizontal then
          R.Bottom := R.Bottom - FFixedHeight
        else
          R.Right := R.Right - FFixedHeight;

        Canvas.Brush.Color := FColor;
      end;

      DrawGradient(Canvas, FColor, FColorTo, 64, R, Orientation = hoVertical);

      R := pr;

      if FLineColor = clNone then
        Pen.Color := FColor
      else
        Pen.Color := FLineColor;

      DoDraw := True;

      if Assigned(Planner.FOnPlannerFooterDraw) then
      begin
        Font := Planner.Footer.Font;
        Brush.Color := FColor;
        Pen.Color := FLineColor;
        Pen.Width := 1;
        Planner.FOnPlannerFooterDraw(TCustomPlanner(Owner), Canvas, R, AIdx, DoDraw);
      end;

      if Planner.Sidebar.Position = spRight then
        startsection := 0
      else
        startsection := 1;

      if (Planner.Footer.ShowCompletion) and ((s <> '') and (SectionIndex > startsection)) and paintcompl then
      begin
        pr := R;
        val(s, GPos, Err);
        gs.Level0Color := Planner.Footer.Completion.Level0Color;
        gs.Level0ColorTo := Planner.Footer.Completion.Level0ColorTo;
        gs.Level1Color := Planner.Footer.Completion.Level1Color;
        gs.Level1ColorTo := Planner.Footer.Completion.Level1ColorTo;
        gs.Level2Color := Planner.Footer.Completion.Level2Color;
        gs.Level2ColorTo := Planner.Footer.Completion.Level2ColorTo;
        gs.Level3Color := Planner.Footer.Completion.Level3Color;
        gs.Level3ColorTo := Planner.Footer.Completion.Level3ColorTo;
        gs.BorderColor := Planner.Footer.Completion.BorderColor;
        gs.ShowBorder := Planner.Footer.Completion.ShowBorder;
        gs.Level1Perc := Planner.Footer.Completion.Level1Perc;
        gs.Level2Perc := Planner.Footer.Completion.Level2Perc;
        gs.BackgroundColor := Planner.Footer.Completion.BackgroundColor;
        gs.ShowGradient := Planner.Footer.Completion.ShowGradient;
        gs.ShowPercentage := Planner.Footer.Completion.ShowPercentage;
        gs.Stacked := Planner.Footer.Completion.Stacked;
        gs.CompletionSmooth := Planner.Footer.Completion.CompletionSmooth;
        gs.Font := Planner.Footer.Completion.Font;
        gs.Steps := Planner.Footer.Completion.Steps;
        gs.CompletionFormat := Planner.Footer.CompletionFormat;

        if Planner.Sidebar.Position = spTop then
          gs.Orientation := goVertical
        else
          gs.Orientation := goHorizontal;

        InflateRect(pr, -6, -6);
        DrawGauge(Canvas, pr, GPos, gs);
        s := '';
      end;

      if FShowFixed and (Orientation = hoHorizontal) and (SectionIndex > 1) then
        R.Bottom := R.Bottom - FFixedHeight;

      if FShowFixed and (Orientation = hoVertical) and (SectionIndex > 1) then
        R.Right := R.Right - FFixedHeight;

      if not FFlat then
      begin
        DrawEdge(Canvas.Handle, R, BDR_RAISEDINNER, BF_TOPLEFT);
        DrawEdge(Canvas.Handle, R, BDR_RAISEDINNER, BF_BOTTOMRIGHT);
      end;

      if DoDraw and paintcompl then
      begin
        InflateRect(pr, -4, -2);

        if Assigned(FImageList) and (FImageList.Count + 1 + FOffset - FLeftPos > SectionIndex) and
          (SectionIndex > FOffset) and (SectionIndex <= Sections.Count - 1 - FLeftPos) then
        begin
          if FImagePosition = ipLeft then
          begin
            FImageList.Draw(Canvas, pr.Left, pr.Top, SectionIndex - 1 - FOffset + FLeftPos);
            pr.Left := pr.Left + FImageList.Width;
          end
          else
          begin
            pr.Right := pr.Right - FImageList.Width;
            FImageList.Draw(Canvas, pr.Right, pr.Top, SectionIndex - 1 - FOffset);
          end;
        end;

        s := CLFToLF(s);

        if Pos(#13, s) = 0 then
          VerticalAlign := VerticalAlign or DT_SINGLELINE
        else
          VerticalAlign := 0;

        pr.Bottom := pr.Top + ClientHeight;

        if (Orientation = hoVertical) then
        begin
          pr.Right := Width - 2;
          pr.Bottom := pr.Top + w - 2;
        end;

        DrawFlags := DT_NOPREFIX or DT_END_ELLIPSIS or HorizontalAlign or VerticalAlign;
        DrawFlags := Planner.DrawTextBiDiModeFlags(DrawFlags);

        txtdraw := True;

        if (Planner.Sidebar.Position in [spLeft, spLeftRight]) then
          txtdraw := SectionIndex > 1;

        if txtdraw then
        begin
          if Pos('</', s) > 0 then
          begin
            HTMLDrawEx(Canvas, s, pr, Planner.PlannerImages, 0, 0, -1, -1, 1, False, False, False, False, False, False, True
              , False
              , 1, clBlue, clNone, clNone, clGray, Anchor, Strip, FocusAnchor, XSize, YSize, ml, hl, hr
              , CR, CID, CV, CT, Planner.FImageCache, Planner.FContainer, Handle
              );
          end
          else
          begin
            Canvas.Brush.Style := bsClear;
            DrawText(Canvas.Handle, PChar(s), Length(s), pr, DrawFlags);
          end;
        end
        else
        begin
          if (SectionIndex > 1) and (Orientation = hoHorizontal) and (FLineColor <> clNone) then
          begin
            Canvas.MoveTo(R.Left + 2, R.Top);
            Canvas.LineTo(R.Left + 2, R.Bottom);
          end;
          if (SectionIndex > 1) and (Orientation = hoVertical) and (FLineColor <> clNone) then
          begin
            Canvas.MoveTo(R.Left, R.Top + 2);
            Canvas.LineTo(R.Right, R.Top + 2);
          end;
        end;

        if FShowFixed and (Orientation = hoHorizontal) and (SectionIndex > 1) then
        begin
          Canvas.Pen.Color := FLineColor;
          if FFlat then
          begin
            Canvas.MoveTo(R.Left + 1, R.Bottom);
            Canvas.LineTo(R.Left + 1, R.Bottom + FFixedHeight);
          end
          else
          begin
            Canvas.MoveTo(R.Right - 1, R.Bottom);
            Canvas.LineTo(R.Right - 1, R.Bottom + FFixedHeight);
          end;
          R.Bottom := R.Bottom + FFixedHeight;
        end;

        if FShowFixed and (Orientation = hoVertical) and (SectionIndex > 1) then
        begin
          Canvas.Pen.Color := FLineColor; Canvas.MoveTo(R.Right, R.Bottom - 1);
          Canvas.LineTo(R.Right + +FFixedHeight, R.Bottom - 1);
          R.Right := R.Right + FFixedHeight;
        end;

        Font := Planner.Footer.Font;
        Brush.Color := FColor;
        Pen.Color := FLineColor;
        Pen.Width := 1;
      end;

    until AllPainted;
  end;
end;

{ TPlannerPrintOptions }

constructor TPlannerPrintOptions.Create;
begin
  inherited Create;
  FHeaderFont := TFont.Create;
  FFooterFont := TFont.Create;
  FFooter := TStringList.Create;
  FHeader := TStringList.Create;
  FFitToPage := True;
end;

destructor TPlannerPrintOptions.Destroy;
begin
  FFooterFont.Free;
  FHeaderFont.Free;
  FFooter.Free;
  FHeader.Free;
  inherited;
end;

procedure TPlannerPrintOptions.Assign(Source: TPersistent);
begin
  if (Source is TPlannerPrintOptions) then
  begin
    FCellHeight :=(Source as TPlannerPrintOptions).CellHeight;
    FCellWidth := (Source as TPlannerPrintOptions).CellWidth;
    FLineWidth := (Source as TPlannerPrintOptions).LineWidth;
    FFitToPage := (Source as TPlannerPrintOptions).FitToPage;
    FFooter.Assign((Source as TPlannerPrintOptions).Footer);
    FFooterAlignment := (Source as TPlannerPrintOptions).FooterAlignment;
    FFooterFont.Assign((Source as TPlannerPrintOptions).FooterFont);
    FFooterSize := (Source as TPlannerPrintOptions).FooterSize;
    FHeader.Assign((Source as TPlannerPrintOptions).Header);
    FHeaderAlignment := (Source as TPlannerPrintOptions).HeaderAlignment;
    FHeaderFont.Assign((Source as TPlannerPrintOptions).HeaderFont);
    FHeaderSize := (Source as TPlannerPrintOptions).HeaderSize;
    FJobname := (Source as TPlannerPrintOptions).JobName;
    FLeftMargin := (Source as TPlannerPrintOptions).LeftMargin;
    FOrientation := (Source as TPlannerPrintOptions).Orientation;
    FRightMargin := (Source as TPlannerPrintOptions).RightMargin;
    FTopMargin := (Source as TPlannerPrintOptions).TopMargin;
    FSidebarWidth := (Source as TPlannerPrintOptions).SidebarWidth;
  end;
end;

procedure TPlannerPrintOptions.SetFooter(const value: TStrings);
begin
  if Assigned(value) then
    FFooter.Assign(value);
end;

procedure TPlannerPrintOptions.SetFooterFont(const value: TFont);
begin
  if Assigned(value) then
    FFooterFont.Assign(value);
end;

procedure TPlannerPrintOptions.SetHeader(const value: TStrings);
begin
  if Assigned(value) then
    FHeader.Assign(value);
end;

procedure TPlannerPrintOptions.SetHeaderFont(const value: TFont);
begin
  if Assigned(value) then
    FHeaderFont.Assign(value);
end;

{ TPlannerHTMLOptions }

constructor TPlannerHTMLOptions.Create;
begin
  inherited Create;
  FBorderSize := 1;
  FCellSpacing := 0;
  FWidth := 100;
end;

{ TPlannerItemIO }

constructor TPlannerItemIO.CreateItem(AOwner: TPlannerItems);
begin
  inherited Create(nil);
  FItem := TPlannerItem(AOwner.GetItemClass.Create(AOwner));
end;

destructor TPlannerItemIO.Destroy;
begin
  FItem.Free;
  inherited;
end;

{ TWeekDays }

procedure TWeekDays.Changed;
begin
  if Assigned(OnChanged) then
    OnChanged(Self);
end;

constructor TWeekDays.Create;
begin
  inherited;
  FSun := True;
  FSat := True;
end;

procedure TWeekDays.SetFri(const value: Boolean);
begin
  FFri := value;
  Changed;
end;

procedure TWeekDays.SetMon(const value: Boolean);
begin
  FMon := value;
  Changed;
end;

procedure TWeekDays.SetSat(const value: Boolean);
begin
  FSat := value;
  Changed;
end;

procedure TWeekDays.SetSun(const value: Boolean);
begin
  FSun := value;
  Changed;
end;

procedure TWeekDays.SetThu(const value: Boolean);
begin
  FThu := value;
  Changed;
end;

procedure TWeekDays.SetTue(const value: Boolean);
begin
  FTue := value;
  Changed;
end;

procedure TWeekDays.SetWed(const value: Boolean);
begin
  FWed := value;
  Changed;
end;

{ TPlannerPanel }

function TPlannerPanel.IsAnchor(X, Y: Integer): string;
var
  R, hr: TRect;
  XSize, YSize, ml, hl: Integer;
  a, s, fa: string;
  CID, CV, CT: string;
  CR: TRect;
begin
  R := ClientRect;
  a := '';

  if HTMLDrawEx(Canvas, Caption, R,(Owner as TCustomPlanner).PlannerImages, X, Y, -1, -1,
    1, True, False, False, True, True, False, True
    , False
    , 1.0, clBlue, clNone, clNone, clGray, a, s, fa, XSize, YSize, ml, hl, hr
    , CR, CID, CV, CT, (Owner as TCustomPlanner).FImageCache, (Owner as TCustomPlanner).FContainer, Handle
    ) then
    Result := a;
end;

procedure TPlannerPanel.MouseDown(Button: TMouseButton; Shift: TShiftState;
  X, Y: Integer);
var
  Anchor: string;
begin
  inherited;

  if (csDesigning in ComponentState) then
  begin
    Anchor := FPlanner.Caption.Title;
    if InputQuery('Planner caption title', 'Text:', Anchor) then
    begin
      FPlanner.Caption.Title := Anchor;
    end;
    Exit;
  end;

  if Pos('</', Caption) = 0 then
    Exit;

  Anchor := IsAnchor(X, Y);

  if Anchor <> '' then
  begin
    with Owner as TCustomPlanner do
    begin
      if Assigned(FOnCaptionAnchorClick) then
        FOnCaptionAnchorClick (Self.Owner, X, Y, Anchor);
    end;
  end;
end;

procedure TPlannerPanel.MouseMove(Shift: TShiftState; X, Y: Integer);
var
  Anchor: string;
begin
  inherited;

  if Pos('</', Caption) = 0 then
    Exit;

  Anchor := IsAnchor(X, Y);

  if Anchor <> '' then
  begin
    if (Cursor = crDefault) or (FOldAnchor <> Anchor) then
    begin
      Self.Cursor := crHandPoint;

      with Owner as TCustomPlanner do
      begin
        if Assigned (FOnCaptionAnchorEnter) then
          FOnCaptionAnchorEnter (Self.Owner, X, Y, Anchor);
      end;
    end;
    FOldAnchor := Anchor;
  end
  else
  begin
    if (Self.Cursor = crHandPoint) then
    begin
      Self.Cursor := crDefault;

      with (Owner as TCustomPlanner) do
      begin
        if Assigned (FOnCaptionAnchorExit) then
          FOnCaptionAnchorExit (Self.Owner, X, Y, FOldAnchor);
      end;
      FOldAnchor := '';
    end;
  end;
end;

constructor TPlannerPanel.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  ControlStyle := ControlStyle - [csAcceptsControls];
  FPlanner := TCustomPlanner(AOwner);
end;

procedure TPlannerPanel.CMDesignHitTest(var Msg: TCMDesignHitTest);
begin
  if (Width - Msg.XPos < 20) and (Msg.YPos < 20) and FPlanner.ShowDesignHelper then
    Msg.Result := 1
  else
    inherited;
end;

procedure TPlannerPanel.WMEraseBkGnd(var Message: TMessage);
begin
  message.Result := 1;
end;

procedure TPlannerPanel.Paint;
var
  DoDraw: Boolean;
  a, s, fa: string;
  CID, CV, CT: string;
  CR: TRect;
  XSize, YSize, ml, hl: Integer;
  hr: TRect;
  FPlanner: TCustomPlanner;
  DTFLAGS: dword;
  BMP: TBitmap;
begin
  FPlanner := (Owner as TCustomPlanner);

  DoDraw := True;

  if Assigned(FPlanner.OnPlannerCaptionDraw) then
    FPlanner.OnPlannerCaptionDraw(FPlanner, Canvas, GetClientRect, DoDraw);

  if DoDraw then
  begin
    //if (Pos('</', Caption) > 0) or ((Owner as TCustomPlanner).Caption.BackgroundTo <> clNone) then
    begin
      Canvas.Brush.Color := (Owner as TCustomPlanner).Caption.Background;
      Canvas.Pen.Color := Canvas.Brush.Color;

      if ((Owner as TCustomPlanner).Caption.BackgroundTo <> clNone) then
        DrawGradient(Canvas, Canvas.Brush.Color, (Owner as TCustomPlanner).Caption.BackgroundTo,
         (Owner as TCustomPlanner).Caption.BackgroundSteps, ClientRect,
         (Owner as TCustomPlanner).Caption.GradientDirection = gdHorizontal)
      else
        Canvas.Rectangle(ClientRect.Left, ClientRect.Top, ClientRect.Right, ClientRect.Bottom);

      Canvas.Font.Assign(Font);

      if (Pos('</', Caption) > 0) then
      begin
        HTMLDrawEx(Canvas, Caption, ClientRect, (Owner as TCustomPlanner).PlannerImages, 0, 0, -1, -1,
          1, False, False, False, False, False, False, True
          , False
          , 1.0, (Owner as TCustomPlanner).URLColor, clNone,
          clNone, clGray, a, s, fa, XSize, YSize, ml, hl, hr
         , CR, CID, CV, CT, FPlanner.FImageCache, FPlanner.FContainer, Handle
         );
       end
       else
       begin
         if Pos(#13, Caption) = 0 then
           DTFLAGS := DT_VCENTER or DT_END_ELLIPSIS or DT_SINGLELINE
         else
           DTFLAGS := DT_END_ELLIPSIS or DT_WORDBREAK;

         case (Owner as TCustomPlanner).Caption.Alignment of
         taLeftJustify: DTFLAGS := DTFLAGS or DT_LEFT;
         taRightJustify: DTFLAGS := DTFLAGS or DT_RIGHT;
         taCenter: DTFLAGS := DTFLAGS or DT_CENTER;
         end;
         CR := ClientRect;

         SetBkMode(Canvas.Handle, Transparent);
         DrawText(Canvas.Handle, PChar(Caption), Length(Caption), CR, DTFLAGS);
       end;
     end
     //else
     //begin
     //  inherited;
     //end;
   end;

   if (csDesigning in ComponentState) and FPlanner.ShowDesignHelper then
   begin
     BMP := TBitmap.Create;
     try
       BMP.LoadFromResourceID(HInstance, 505);
       BMP.TransparentMode := tmAuto;
       BMP.Transparent := True;
       Canvas.Draw(Width - 20, 2, BMP);
     finally
       BMP.Free;
     end;
  end;
end;

{ TPlannerScrollBar }

constructor TPlannerScrollBar.Create(AOwner: TCustomPlanner);
begin
  inherited Create;
  FOwner := AOwner;
  FStyle := ssNormal;
  FWidth := 16;
  FColor := clNone;
  FFlat := False;
end;

procedure TPlannerScrollBar.SetColor(const value: TColor);
begin
  if FColor <> value then
  begin
    FColor := value;
    UpdateProps;
  end;
end;

procedure TPlannerScrollBar.SetFlat(const value: Boolean);
begin
  if FFlat <> value then
  begin
    FFlat := value;
    if FFlat then
      FOwner.FGrid.FlatScrollInit
    else
      FOwner.FGrid.FlatScrollDone;

    if FOwner.PositionWidth = 0 then
    begin
      if FOwner.Sidebar.Position = spTop then
        FOwner.FGrid.FlatShowScrollBar(SB_VERT, False)
      else
        FOwner.FGrid.FlatShowScrollBar(SB_HORZ, False);
    end;
  end;
end;

procedure TPlannerScrollBar.SetStyle(const value: TPlannerScrollStyle);
begin
  if FStyle <> value then
  begin
    FStyle := value;
    UpdateProps;
  end;
end;

procedure TPlannerScrollBar.SetWidth(const value: Integer);
begin
  if FWidth <> value then
  begin
    FWidth := value;
    UpdateProps;
  end;
end;

procedure TPlannerScrollBar.UpdateProps;
begin
  if FFlat then
  begin
    if FColor <> clNone then
    begin
      FOwner.FGrid.FlatSetScrollProp(WSB_PROP_VBKGCOLOR, Integer(FColor), True);
      FOwner.FGrid.FlatSetScrollProp(WSB_PROP_HBKGCOLOR, Integer(FColor), True);
    end;

    FOwner.FGrid.FlatSetScrollProp(WSB_PROP_CXVSCROLL, FWidth, True);
    FOwner.FGrid.FlatSetScrollProp(WSB_PROP_CYHSCROLL, FWidth, True);

    case FStyle of
    ssNormal: FOwner.FGrid.FlatSetScrollProp(WSB_PROP_VSTYLE, FSB_REGULAR_MODE, True);
    ssFlat: FOwner.FGrid.FlatSetScrollProp(WSB_PROP_VSTYLE, FSB_FLAT_MODE, True);
    ssEncarta: FOwner.FGrid.FlatSetScrollProp(WSB_PROP_VSTYLE, FSB_ENCARTA_MODE, True);
    end;

    case FStyle of
    ssNormal: FOwner.FGrid.FlatSetScrollProp(WSB_PROP_HSTYLE, FSB_REGULAR_MODE, True);
    ssFlat: FOwner.FGrid.FlatSetScrollProp(WSB_PROP_HSTYLE, FSB_FLAT_MODE, True);
    ssEncarta: FOwner.FGrid.FlatSetScrollProp(WSB_PROP_HSTYLE, FSB_ENCARTA_MODE, True);
    end;
  end;
end;

{ TBackground }

procedure TBackground.BackgroundChanged(Sender: TObject);
begin
  FPlanner.FGrid.Invalidate;
end;

constructor TBackground.Create(APlanner: TCustomPlanner);
begin
  inherited Create;
  FPlanner := APlanner;
  FBitmap := TBitmap.Create;
  FBitmap.OnChange := BackgroundChanged;
end;

destructor TBackground.Destroy;
begin
  FBitmap.Free;
  inherited;
end;

procedure TBackground.SetBitmap(value: TBitmap);
begin
  FBitmap.Assign(value);
  FPlanner.Invalidate;
end;

procedure TBackground.SetDisplay(value: TBackgroundDisplay);
begin
  if FDisplay <> value then
  begin
    FDisplay := value;
    FPlanner.Invalidate;
  end;
end;

procedure TBackground.SetLeft(value: Integer);
begin
  if FLeft <> value then
  begin
    FLeft := value;
    FPlanner.Invalidate;
  end;
end;

procedure TBackground.SetTop(value: Integer);
begin
  if FTop <> value then
  begin
    FTop := value;
    FPlanner.Invalidate;
  end;
end;

{ TPlannerAlarmHandler }

function TPlannerAlarmHandler.HandleAlarm(Address, Message: string;
   Tag, ID: Integer; Item: TPlannerItem): Boolean;
begin
  Result := True;
end;

{ TAlarmMessage }

function TAlarmMessage.HandleAlarm(Address, Message: string; Tag, ID: Integer;
  Item: TPlannerItem): Boolean;
begin
  case Item.Alarm.NotifyType of
  anMessage: MessageDlg(Item.Alarm.Message, mtInformation, [mbok], 0);
  anNotes: MessageDlg(HTMLStrip(Item.Text.Text), mtInformation, [mbok], 0);
  anCaption: MessageDlg(Item.CaptionText, mtInformation, [mbok], 0);
  end;
  Result := True;
end;

{ TAdvSpeedButton }
procedure TAdvSpeedButton.CMMouseEnter(var Message: TMessage);
begin
  inherited;
  Invalidate;
end;

procedure TAdvSpeedButton.CMMouseLeave(var Message: TMessage);
begin
  inherited;
  Invalidate;
end;

constructor TAdvSpeedButton.Create(AOwner: TComponent);
var
  VerInfo: TOSVersioninfo;
begin
  inherited;
  Flat := True; // change default value
  VerInfo.dwOSVersionInfoSize := SizeOf(TOSVersioninfo);
  GetVersionEx(VerInfo);
  FIsWinXP := (VerInfo.dwMajorVersion > 5) OR ((VerInfo.dwMajorVersion = 5) AND
    (VerInfo.dwMinorVersion >= 1));
end;

procedure TAdvSpeedButton.Paint;
const
  DownStyles: array [Boolean] of Integer = (BDR_RAISEDINNER, BDR_SUNKENOUTER);
var
  PaintRect: TRect;
  Offset: TPoint;
  DrawFlags: Integer;
  HTheme: THandle;
  Hot: Boolean;
  pt: TPoint;
begin
  Canvas.Font := Self.Font;
  PaintRect := Rect(0, 0, Width, Height);
  if FIsWinXP then
  begin
    if IsThemeActive then
    begin
      GetCursorPos(pt);
      pt := ScreenToClient(pt);

      Hot := PtInRect(PaintRect, pt);

      HTheme := OpenThemeData(Parent.Handle, 'Scrollbar');

      if Direction = bdLeft then
      begin
        if FState in [bsDown, bsExclusive] then
          DrawThemeBackground(HTheme, Canvas.Handle, SBP_ARROWBTN, ABS_LEFTPRESSED, @PaintRect, nil)
        else
          if Hot then
            DrawThemeBackground(HTheme, Canvas.Handle, SBP_ARROWBTN, ABS_LEFTHOT, @PaintRect, nil)
          else
            DrawThemeBackground(HTheme, Canvas.Handle, SBP_ARROWBTN, ABS_LEFTNORMAL, @PaintRect, nil)
      end
      else
      begin
        if FState in [bsDown, bsExclusive] then
          DrawThemeBackground(HTheme, Canvas.Handle, SBP_ARROWBTN, ABS_RIGHTPRESSED, @PaintRect, nil)
        else
          if Hot then
            DrawThemeBackground(HTheme, Canvas.Handle, SBP_ARROWBTN, ABS_RIGHTHOT, @PaintRect, nil)
          else
            DrawThemeBackground(HTheme, Canvas.Handle, SBP_ARROWBTN, ABS_RIGHTNORMAL, @PaintRect, nil);
      end;
      CloseThemeData(HTheme);
      Exit;
    end;
  end;

  if not Flat then
  begin
    DrawFlags := DFCS_BUTTONPUSH or DFCS_ADJUSTRECT;
    if FState in [bsDown, bsExclusive] then
      DrawFlags := DrawFlags or DFCS_PUSHED;

    DrawFrameControl(Canvas.Handle, PaintRect, DFC_BUTTON, DrawFlags);
  end
  else
  begin
    DrawEdge(Canvas.Handle, PaintRect, DownStyles[FState in [bsDown, bsExclusive]], BF_MIDDLE or BF_RECT);
    InflateRect(PaintRect, -1, -1);
  end;

  if not(FState in [bsDown, bsExclusive]) then
  begin
    Offset.X := 0;
    Offset.Y := 0;
  end;
  if Assigned(Glyph) then
    if not Glyph.Empty then
    begin
      Glyph.Transparent := True;
      Offset.X := 0;
      Offset.Y := 0;
      if Glyph.Width < Width then
        Offset.X := (Width - Glyph.Width) shr 1;
      if Glyph.Height < Height then
        Offset.Y := (Height - Glyph.Height) shr 1;

      if FState = bsDown then
        Canvas.Draw(Offset.X + 1, Offset.Y + 1, Glyph)
      else
        Canvas.Draw(Offset.X, Offset.Y, Glyph)
    end
    else
    begin
      if FState = bsDown then
      begin
        Offset.X := 5;
        Offset.Y := 5;
      end
      else
      begin
        Offset.X := 4;
        Offset.Y := 4;
      end;
      Canvas.TextRect(PaintRect, Offset.X, Offset.Y, Caption);
   end;
end;

{ TPositionProps }

function TPositionProps.Add: TPositionProp;
begin
  Result := TPositionProp (inherited Add);
end;

constructor TPositionProps.Create(AOwner: TCustomPlanner);
begin
  inherited Create(TPositionProp);
  FOwner := AOwner;
end;

function TPositionProps.GetItem(Index: Integer): TPositionProp;
begin
  Result := TPositionProp (inherited Items[Index]);
end;

function TPositionProps.GetOwner: TPersistent;
begin
  Result := FOwner;
end;

function TPositionProps.Insert(Index: Integer): TPositionProp;
begin
  Result := TPositionProp (inherited Insert(Index));
end;

procedure TPositionProps.SetItem(Index: Integer; const value: TPositionProp);
begin
  inherited SetItem(Index, value);
end;

{ TPositionProp }

procedure TPositionProp.Assign(Source: TPersistent);
begin
  inherited;
  FActiveStart := (Source as TPositionProp).ActiveStart;
  FActiveEnd := (Source as TPositionProp).ActiveEnd;
  FBackGround := (Source as TPositionProp).Background;
  FColorActive := (Source as TPositionProp).ColorActive;
  FColorNonActive := (Source as TPositionProp).ColorNonActive;
  FMinSelection := (Source as TPositionProp).MinSelection;
  FMaxSelection := (Source as TPositionProp).MaxSelection;
  FColorNoSelect := (Source as TPositionProp).ColorNoSelect;
  FBrushNoSelect := (Source as TPositionProp).BrushNoSelect;
  FUse := (Source as TPositionProp).Use;
end;

procedure TPositionProp.BackgroundChanged(Sender: TObject);
begin
  TPositionProps(Collection).FOwner.FGrid.Invalidate;
end;

constructor TPositionProp.Create(Collection: TCollection);
begin
  inherited;
  FActiveStart := TPositionProps(Collection).FOwner.Display.ActiveStart;
  FActiveEnd := TPositionProps(Collection).FOwner.Display.ActiveEnd;
  FColorActive := TPositionProps(Collection).FOwner.Display.ColorActive;
  FColorNonActive := TPositionProps(Collection).FOwner.Display.ColorNonActive;
  FColorNoSelect := clRed;
  FBrushNoSelect := bsSolid;
  FBackGround := TBitmap.Create;
  FBackGround.OnChange := BackgroundChanged;
  FUse := True;
  FShowGap := True;
end;

destructor TPositionProp.Destroy;
begin
  TPositionProps(Collection).FOwner.Invalidate;
  FBackGround.Free;
  inherited;
end;

procedure TPositionProp.SetActiveEnd(const value: Integer);
begin
  FActiveEnd := value;
  TPositionProps(Collection).FOwner.FGrid.Invalidate;
end;

procedure TPositionProp.SetActiveStart(const value: Integer);
begin
  FActiveStart := value;
  TPositionProps(Collection).FOwner.FGrid.Invalidate;
end;

procedure TPositionProp.SetBackground(const value: TBitmap);
begin
  FBackGround.Assign(value);
  TPositionProps(Collection).FOwner.FGrid.Invalidate;
end;

procedure TPositionProp.SetBrushNoSelect(const value: TBrushStyle);
begin
  FBrushNoSelect := value;
  TPositionProps(Collection).FOwner.FGrid.Invalidate;
end;

procedure TPositionProp.SetColorActive(const value: TColor);
begin
  FColorActive := value;
  TPositionProps(Collection).FOwner.FGrid.Invalidate;
end;

procedure TPositionProp.SetColorNonActive(const value: TColor);
begin
  FColorNonActive := value;
  TPositionProps(Collection).FOwner.FGrid.Invalidate;
end;

procedure TPositionProp.SetColorNoSelect(const value: TColor);
begin
  FColorNoSelect := value;
  TPositionProps(Collection).FOwner.FGrid.Invalidate;
end;

procedure TPositionProp.SetMaxSelection(const value: Integer);
begin
  FMaxSelection := value;
  TPositionProps(Collection).FOwner.FGrid.Invalidate;
end;

procedure TPositionProp.SetMinSelection(const value: Integer);
begin
  FMinSelection := value;
  TPositionProps(Collection).FOwner.FGrid.Invalidate;
end;

procedure TPositionProp.SetShowGap(const value: Boolean);
begin
  FShowGap := value;
  TPositionProps(Collection).FOwner.FGrid.Invalidate;
end;

procedure TPositionProp.SetUse(const value: Boolean);
begin
  FUse := value;
  TPositionProps(Collection).FOwner.FGrid.Invalidate;
end;

{ TPlannerExChange }

procedure TPlannerExChange.DoExport;
begin
end;

procedure TPlannerExChange.DoImport;
begin
end;

procedure TPlannerExChange.Notification(AComponent: TComponent; AOperation: TOperation);
begin
  if (AOperation = opRemove) and (AComponent = FPlanner) then
    FPlanner := nil;
  inherited;
end;

function TPlannerExChange.NumItemsForExport: Integer;
var
  i: Integer;
begin
  Result := 0;

  if not Assigned(FPlanner) then
    Exit;

  for i := 1 to FPlanner.Items.Count do
  begin
    if FPlanner.Items[i - 1].DoExport then
      Result := Result + 1;
  end;
end;

{ TPlannerAlarm }

procedure TPlannerAlarm.Assign(Source: TPersistent);
begin
  Active := TPlannerAlarm(Source).Active;
  Address := TPlannerAlarm(Source).Address;
  Handler := TPlannerAlarm(Source).Handler;
  ID := TPlannerAlarm(Source).ID;
  Message := TPlannerAlarm(Source).Message;
  NotifyType := TPlannerAlarm(Source).NotifyType;
  Tag := TPlannerAlarm(Source).Tag;
  TimeBefore := TPlannerAlarm(Source).TimeBefore;
  TimeAfter := TPlannerAlarm(Source).TimeAfter;
  Time := TPlannerAlarm(Source).Time;
end;

{ TPlannerBarItem }

function TPlannerBarItem.CheckOwners: Boolean;
begin
  Result := False;

  // check for list
  if not Assigned(Owner) then Exit;
  // check for planner item
  if not Assigned(Owner.Owner) then Exit;
  // check for planner
  if not Assigned(Owner.Owner.Owner) then Exit;

  Result := True;
end;

constructor TPlannerBarItem.Create(pOwner: TPlannerBarItemList);
begin
  inherited Create;
  FOwner := pOwner;
  FColor := clGreen;
  FBegin := -1;
  FEnd := -1;
  FStyle := bsSolid;
  FOnDestroy := nil;
end;

destructor TPlannerBarItem.Destroy;
begin
  if Assigned(FOwner) then
    FOwner.Remove(Self);

  if Assigned(FOnDestroy) then
    FOnDestroy(Self);
  inherited;
end;

function TPlannerBarItem.GetEndTime: TDateTime;
var
  du: Integer;
begin
  Result := 0;

  if not CheckOwners then
    Exit;

  // Get display unit from planner
  du := Owner.Owner.Owner.Display.DisplayUnit;

  Result := (BarEnd * du) / 24 / 60 + Owner.Owner.ItemStartTime;
end;

function TPlannerBarItem.GetStartTime: TDateTime;
var
  du: Integer;
begin
  Result := 0;

  if not CheckOwners then
    Exit;

  // Get display unit from planner
  du := Owner.Owner.Owner.Display.DisplayUnit;

  Result := (BarBegin * du) / 24 / 60 + Owner.Owner.ItemStartTime;
end;

procedure TPlannerBarItem.SetEndTime(const pEndTime: TDateTime);
var
  du: Integer;
  dDiff: double;
begin
  if not CheckOwners then Exit;

  // Get display unit from planner
  du := Owner.Owner.Owner.Display.DisplayUnit;
  dDiff := Frac(pEndTime - Owner.Owner.ItemStartTime);

  // if over start of day
  if dDiff < 0 then
    dDiff := dDiff + 1;

  BarEnd := Round(dDiff * 24 * 60 / du);
end;

procedure TPlannerBarItem.SetStartTime(const pStartTime: TDateTime);
var
  du: Integer;
  dDiff: double;
begin
  if not CheckOwners then
    Exit;

  // get display unit from planner
  du := Owner.Owner.Owner.Display.DisplayUnit;
  dDiff := Frac(pStartTime - Owner.Owner.ItemStartTime);

  // if over start of day
  if dDiff < 0 then
    dDiff := dDiff + 1;

  BarBegin := Round(dDiff * 24 * 60 / du);
end;

{ TPlannerBarItemList }

constructor TPlannerBarItemList.Create(AOwner: TPlannerItem);
begin
  inherited Create;
  FOwner := AOwner;
end;

function TPlannerBarItemList.GetItem(Index: Integer): TPlannerBarItem;
begin
  Result := nil;
  if ((Index > -1) and (Index < Count)) then
    Result := TPlannerBarItem( inherited Items[Index]);
end;

function TPlannerBarItemList.AddItem(pStart, pEnd: TDateTime; pColor: TColor;
  pStyle: TBrushStyle): Integer;
var
  pbi: TPlannerBarItem;
begin
  Result := -1;
  if pEnd < pStart then
    Exit;
  pbi := TPlannerBarItem.Create(Self);
  pbi.StartTime := pStart;
  pbi.EndTime := pEnd;
  pbi.BarColor := pColor;
  pbi.BarStyle := pStyle;
  Result := inherited Add(pbi);
end;

destructor TPlannerBarItemList.Destroy;
var
  i: Integer;
begin
  if Count > 0 then
    for i := Count - 1 downto 0 do
      Items[i].Free;
  inherited;
end;

{ TBands }

constructor TBands.Create(AOwner: TCustomPlanner);
begin
  inherited Create;
  FOwner := AOwner;
  FActivePrimary := $00FEE7CB;
  FActiveSecondary := $00FAD9AF;
  FNonActivePrimary := clSilver;
  FNonActiveSecondary := $00A8A8A8;
end;

procedure TBands.SetActivePrimary(const value: TColor);
begin
  FActivePrimary := value;
  FOwner.Invalidate;
end;

procedure TBands.SetActiveSecondary(const value: TColor);
begin
  FActiveSecondary := value;
  FOwner.Invalidate;
end;

procedure TBands.SetNonActivePrimary(const value: TColor);
begin
  FNonActivePrimary := value;
  FOwner.Invalidate;
end;

procedure TBands.SetNonActiveSecondary(const value: TColor);
begin
  FNonActiveSecondary := value;
  FOwner.Invalidate;
end;

procedure TBands.SetShow(const value: Boolean);
begin
  FShow := value;
  FOwner.Invalidate;
end;

{ TCustomItemEditor }

procedure TCustomItemEditor.CreateEditor(AOwner: TComponent);
begin
end;

procedure TCustomItemEditor.DestroyEditor;
begin
  if Assigned(FOnEditDone) then
    FOnEditDone(Self, FModalResult);
end;

procedure TCustomItemEditor.Edit(APlanner: TCustomPlanner; APlannerItem: TPlannerItem);
begin
  FPlanner := APlanner;
  if QueryEdit(APlannerItem) then
  begin
    if Assigned(OnBeforeEditShow) then
      OnBeforeEditShow(Self, APlannerItem);

    CreateEditor(APlanner.Owner);
    try
      //FEditItem := TPlannerItem(APlanner.Items.GetItemClass.Create(APlanner.Items));
      //FEditItem.Assign(APlannerItem);
      PlannerItemToEdit(APlannerItem);
      FModalResult := Execute;
      if FModalResult = mrOK then
        EditToPlannerItem(APlannerItem);
    finally
      DestroyEditor;
    end;
  end;
end;

procedure TCustomItemEditor.EditToPlannerItem(APlannerItem: TPlannerItem);
begin
end;

function TCustomItemEditor.Execute: Integer;
begin
  Result := mrOK;
end;

procedure TCustomItemEditor.PlannerItemToEdit(APlannerItem: TPlannerItem);
begin
end;

function TCustomItemEditor.QueryEdit(APlannerItem: TPlannerItem): Boolean;
begin
  Result := True;
end;

{ TCustomItemDrawTool }

procedure TCustomItemDrawTool.DrawItem(PlannerItem: TPlannerItem; Canvas: TCanvas;
  Rect: TRect; Selected, Print: Boolean);
begin
end;

{ TPlannerItemSelection }

procedure TPlannerItemSelection.Assign(Source: TPersistent);
begin
  if Assigned(Source) then
  begin
    FAutoUnSelect := (Source as TPlannerItemSelection).AutoUnSelect;
    FButton := (Source as TPlannerItemSelection).Button;
  end;
end;

constructor TPlannerItemSelection.Create;
begin
  inherited Create;
  FAutoUnSelect := True;
  FAutoSelectOnAutoInsert := True;
  Button := sbLeft;
end;

{ TPlannerSelections }

function TPlannerSelections.Add: TPlannerSelection;
begin
  Result := TPlannerSelection(inherited Add);
end;

procedure TPlannerSelections.Clear;
begin
  while Count > 0 do
  begin
    with Items[0] do
      FOwner.UpdateSelection(SelBegin, SelEnd, SelPos, False);
    Items[0].Free;
  end;
end;

constructor TPlannerSelections.Create(AOwner: TCustomPlanner);
begin
  inherited Create(TPlannerSelection);
  FOwner := AOwner;
end;

function TPlannerSelections.GetItem(Index: Integer): TPlannerSelection;
begin
  Result := TPlannerSelection(inherited Items[Index]);
end;

function TPlannerSelections.Insert(Index: Integer): TPlannerSelection;
begin
  Result := TPlannerSelection(inherited Insert(Index));
end;

procedure TPlannerSelections.SetItem(Index: Integer; const value: TPlannerSelection);
begin
  inherited Items[Index] := value;
end;

{ TPlannerFooter }

procedure TPlannerFooter.Assign(Source: TPersistent);
begin
  if (Source is TPlannerFooter) then
  begin
    FAlignment := (Source as TPlannerFooter).Alignment;
    FCaptions.Assign((Source as TPlannerFooter).Captions);
    FCompletionFormat := (Source as TPlannerFooter).CompletionFormat;
    FCompletionType := (Source as TPlannerFooter).CompletionType;
    FColor := (Source as TPlannerFooter).Color;
    FColorTo := (Source as TPlannerFooter).ColorTo;
    FCompletion.Assign((Source as TPlannerFooter).Completion);
    FCustomCompletionValue := (Source as TPlannerFooter).CustomCompletionValue;
    FHeight := (Source as TPlannerFooter).Height;
    FFlat := (Source as TPlannerFooter).Flat;
    FFont.Assign((Source as TPlannerFooter).Font);
    FImages.Assign((Source as TPlannerFooter).Images);
    FImagePosition := (Source as TPlannerFooter).ImagePosition;
    FLineColor := (Source as TPlannerFooter).LineColor;
    FShowCompletion := (Source as TPlannerFooter).ShowCompletion;
    FVAlignment := (Source as TPlannerFooter).VAlignment;
    FVisible := (Source as TPlannerFooter).Visible;
  end;
end;

constructor TPlannerFooter.Create(AOwner: TCustomPlanner);
begin
  inherited Create;
  FOwner := AOwner;
  FHeight := 32;
  FColor := clBtnFace;
  FColorTo := clWhite;
  FCompletionFormat := '%d%%';
  FCompletion := TCompletion.Create;
  FCompletion.OnChange := ItemsChanged;
  FFont := TFont.Create;
  FCaptions := TStringList.Create;
  FCaptions.OnChange := ItemsChanged;
end;

destructor TPlannerFooter.Destroy;
begin
  FCaptions.Free;
  FCompletion.Free;
  FFont.Free;
  inherited;
end;

function TPlannerFooter.GetCompletionValue(Index: Integer): Integer;
var
  e, R: Integer;
begin
  R := 0;
  if FCaptions.Count > Index then
  begin
    if (FOwner.Sidebar.Visible) and (FOwner.Sidebar.Position <> spRight) then
      val(FCaptions[Index + 1], R, e)
    else
      val(FCaptions[Index], R, e);
  end;
  Result := R;
end;

procedure TPlannerFooter.ItemsChanged(Sender: TObject);
var
  SectionIndex, SectionWidth: Integer;
begin
  if (FOwner.FFooter.Sections.Count = 0) then
    Exit;

  SectionIndex := 0;
  while (SectionIndex < FCaptions.Count) and (SectionIndex < FOwner.FFooter.Sections.Count) do
  begin
    SectionWidth := FOwner.FFooter.SectionWidth[SectionIndex];
    FOwner.FFooter.Sections[SectionIndex] := FCaptions.Strings[SectionIndex];
    FOwner.FFooter.SectionWidth[SectionIndex] := SectionWidth;
    Inc(SectionIndex);
  end;
end;

procedure TPlannerFooter.SetAlignment(const value: TAlignment);
begin
  FAlignment := value;
  FOwner.FFooter.Alignment := FAlignment;
end;

procedure TPlannerFooter.SetCaptions(const value: TStringList);
begin
  FCaptions.Assign(value);
end;

procedure TPlannerFooter.SetColor(const value: TColor);
begin
   FColor := value;
   FOwner.FFooter.Color := value;
end;

procedure TPlannerFooter.SetColorTo(const value: TColor);
begin
  FColorTo := value;
  FOwner.FFooter.ColorTo := value;
end;

procedure TPlannerFooter.SetCompletionFormat(const value: string);
begin
  FCompletionFormat := value;
  FOwner.Invalidate;
end;

procedure TPlannerFooter.SetCompletionType(const value: TCompletionType);
begin
  FCompletionType := value;

  if FShowCompletion then
    FOwner.UpdateCompletion
  else
    if not (csLoading in FOwner.ComponentState) then
      Captions.Clear;
  FOwner.Invalidate;
end;

procedure TPlannerFooter.SetCompletionValue(Index: Integer; const value: Integer);
begin
  while FCaptions.Count < Index do
    FCaptions.Add('0');

  if (FOwner.Sidebar.Visible) and (FOwner.Sidebar.Position <> spRight) then
    FCaptions[Index + 1] := IntToStr(value)
  else
    FCaptions[Index] := IntToStr(value)
end;

procedure TPlannerFooter.SetCustomCompletionValue(const value: Boolean);
begin
  FCustomCompletionValue := value;
  FOwner.FFooter.Invalidate;
end;

procedure TPlannerFooter.SetFlat(const value: Boolean);
begin
  FFlat := value;
  FOwner.FFooter.Flat := value;
  FOwner.FGrid.UpdatePositions;
end;

procedure TPlannerFooter.SetFont(const value: TFont);
begin
  FFont.Assign(value);
  FOwner.FFooter.Font.Assign(value);
end;

procedure TPlannerFooter.SetHeight(const value: Integer);
begin
  if FHeight <> value then
  begin
    FHeight := value;
    FOwner.UpdateSizes;
  end;
end;

procedure TPlannerFooter.SetImagePosition(const value: TImagePosition);
begin
  FImagePosition := value;
end;

procedure TPlannerFooter.SetImages(const value: TImageList);
begin
  FImages := value;
end;

procedure TPlannerFooter.SetLineColor(const value: TColor);
begin
  FLineColor := value;
  FOwner.FFooter.LineColor := value;
end;

procedure TPlannerFooter.SetShowCompletion(const value: Boolean);
begin
  if (value <> FShowCompletion) then
  begin
    FShowCompletion := value;

    if FShowCompletion then
      FOwner.UpdateCompletion
    else
      Captions.Clear;

    FOwner.Invalidate;
  end;
end;

procedure TPlannerFooter.SetVAlignment(const value: TVAlignment);
begin
  FVAlignment := value;
  FOwner.FFooter.VAlignment := value;
end;

procedure TPlannerFooter.SetVisible(const value: Boolean);
begin
  if (FVisible <> value) then
  begin
    FVisible := value;
    if FVisible then
    begin
      FOwner.FFooter.Color := Color;
      FOwner.FFooter.Flat := Flat;
    end;
    FOwner.UpdateSizes;
  end;
end;

{ TCompletion }

procedure TCompletion.Assign(Source: TPersistent);
begin
  if (Source is TCompletion) then
  begin
    FLevel0Color := (Source as TCompletion).Level0Color;
    FLevel0ColorTo := (Source as TCompletion).Level0ColorTo;
    FLevel1Color := (Source as TCompletion).Level1Color;
    FLevel1ColorTo := (Source as TCompletion).Level1ColorTo;
    FLevel2Color := (Source as TCompletion).Level2Color;
    FLevel2ColorTo := (Source as TCompletion).Level2ColorTo;
    FLevel3Color := (Source as TCompletion).Level3Color;
    FLevel3ColorTo := (Source as TCompletion).Level3ColorTo;
    FLevel1Perc := (Source as TCompletion).Level1Perc;
    FLevel2Perc := (Source as TCompletion).Level2Perc;
    FBorderColor := (Source as TCompletion).BorderColor;
    FShowBorder := (Source as TCompletion).ShowBorder;
    FStacked := (Source as TCompletion).Stacked;
    FShowPercentage := (Source as TCompletion).ShowPercentage;
    FFont.Assign((Source as TCompletion).Font);
    FCompletionSmooth := (Source as TCompletion).CompletionSmooth;
    FShowGradient := (Source as TCompletion).ShowGradient;
    FSteps := (Source as TCompletion).Steps;
    FBackgroundColor := (Source as TCompletion).BackgroundColor;
  end;
end;

procedure TCompletion.Changed;
begin
  if Assigned(OnChange) then
    OnChange(Self);
end;

constructor TCompletion.Create;
begin
  inherited Create;
  FFont := TFont.Create;
  FLevel0Color := clLime;
  FLevel0ColorTo := clWhite;
  FLevel1Color := clYellow;
  FLevel1ColorTo := clWhite;
  FLevel2Color := $0000C6FF;
  FLevel2ColorTo := clWhite;
  FLevel3Color := clRed;
  FLevel3ColorTo := clWhite;
  FLevel1Perc := 70;
  FLevel2Perc := 90;
  FBorderColor := clGray;
  FShowBorder := True;
  FStacked := False;
  FShowPercentage := True;
  FCompletionSmooth := True;
  FShowGradient := True;
  FBackgroundColor := clBtnFace;
  FSteps := 8;
  // make sure to select a truetype font for rotation
  FFont.Name := 'Arial';
end;

destructor TCompletion.Destroy;
begin
  FFont.Free;
  inherited;
end;

procedure TCompletion.SetBackGroundColor(const value: TColor);
begin
  FBackgroundColor := value;
  Changed;
end;

procedure TCompletion.SetBorderColor(const value: TColor);
begin
  FBorderColor := value;
  Changed;
end;

procedure TCompletion.SetCompletionSmooth(const value: Boolean);
begin
  FCompletionSmooth := value;
  Changed;
end;

procedure TCompletion.SetFont(const value: TFont);
begin
  FFont := value;
  Changed;
end;

procedure TCompletion.SetLevel0Color(const value: TColor);
begin
  FLevel0Color := value;
  Changed;
end;

procedure TCompletion.SetLevel0ColorTo(const value: TColor);
begin
  FLevel0ColorTo := value;
  Changed;
end;

procedure TCompletion.SetLevel1Color(const value: TColor);
begin
  FLevel1Color := value;
  Changed;
end;

procedure TCompletion.SetLevel1ColorTo(const value: TColor);
begin
  FLevel1ColorTo := value;
  Changed;
end;

procedure TCompletion.SetLevel1Perc(const value: Integer);
begin
  FLevel1Perc := value;
  Changed;
end;

procedure TCompletion.SetLevel2Color(const value: TColor);
begin
  FLevel2Color := value;
  Changed;
end;

procedure TCompletion.SetLevel2ColorTo(const value: TColor);
begin
  FLevel2ColorTo := value;
  Changed;
end;

procedure TCompletion.SetLevel2Perc(const value: Integer);
begin
  FLevel2Perc := value;
  Changed;
end;

procedure TCompletion.SetLevel3Color(const value: TColor);
begin
  FLevel3Color := value;
  Changed;
end;

procedure TCompletion.SetLevel3ColorTo(const value: TColor);
begin
  FLevel3ColorTo := value;
  Changed;
end;

procedure TCompletion.SetShowBorder(const value: Boolean);
begin
  FShowBorder := value;
  Changed;
end;

procedure TCompletion.SetShowGradient(const value: Boolean);
begin
  FShowGradient := value;
  Changed;
end;

procedure TCompletion.SetShowPercentage(const value: Boolean);
begin
  FShowPercentage := value;
  Changed;
end;

procedure TCompletion.SetStacked(const value: Boolean);
begin
  FStacked := value;
  Changed;
end;

procedure TCompletion.SetSteps(const value: Integer);
begin
  FSteps := value;
  Changed;
end;

{ TBalloonSettings }

constructor TBalloonSettings.Create;
begin
  inherited Create;
  FTextColor := clNone;
  FBackgroundColor := clNone;
  FInitialDelay := -1;
  FAutoHideDelay := -1;
  FReshowDelay := -1;
  FEnable := True;
end;

procedure TBalloonSettings.SetEnable(const value: Boolean);
begin
  if (value <> FEnable) then
  begin
    FEnable := value;
    if Assigned(FOnEnableChange) then
      FOnEnableChange(Self);
  end;
end;

{$IFDEF TMSSKINS}
{ TPlannerSkin }

procedure TPlannerSkin.Assign(Source: TPersistent);
begin
  if (Source is TPlannerSkin) then
  begin
    FSkinTop.Assign((Source as TPlannerSkin).SkinTop);
    FSkinBottom.Assign((Source as TPlannerSkin).SkinBottom);
    FSkinCenter.Assign((Source as TPlannerSkin).SkinCenter);
    FSkinSelectTop.Assign((Source as TPlannerSkin).SkinSelectTop);
    FSkinSelectBottom.Assign((Source as TPlannerSkin).SkinSelectBottom);
    FSkinSelectCenter.Assign((Source as TPlannerSkin).SkinSelectCenter);
    FSkinX := (Source as TPlannerSkin).SkinX;
    FSkinY := (Source as TPlannerSkin).SkinY;
    FSkinCaptionX := (Source as TPlannerSkin).SkinCaptionX;
    FSkinCaptionY := (Source as TPlannerSkin).SkinCaptionY;
  end
  else
  raise
    Exception.Create('Cannot assign object to ' + ClassName);
end;

constructor TPlannerSkin.Create(AOwner: TCustomControl);
begin
  inherited Create;
  FOwner := AOwner;
  FSkinTop := TBitmap.Create;
  FSkinCenter := TBitmap.Create;
  FSkinBottom := TBitmap.Create;
  FSkinSelectTop := TBitmap.Create;
  FSkinSelectCenter := TBitmap.Create;
  FSkinSelectBottom := TBitmap.Create;
end;

destructor TPlannerSkin.Destroy;
begin
  FSkinTop.Free;
  FSkinBottom.Free;
  FSkinCenter.Free;
  FSkinSelectTop.Free;
  FSkinSelectBottom.Free;
  FSkinSelectCenter.Free;
  inherited;
end;

procedure TPlannerSkin.LoadFromFile(Filename: string);
var
  inifile: TIniFile;
  fn: string;
begin
  inifile := TIniFile.Create(Filename);

  fn := inifile.ReadString('NORMAL', 'TOP', '');
  if fn <> '' then SkinTop.LoadFromFile(fn);

  fn := inifile.ReadString('NORMAL', 'CENTER', '');
  if fn <> '' then SkinCenter.LoadFromFile(fn);

  fn := inifile.ReadString('NORMAL', 'BOTTOM', '');
  if fn <> '' then SkinBottom.LoadFromFile(fn);

  fn := inifile.ReadString('SELECTED', 'TOP', '');
  if fn <> '' then SkinSelectTop.LoadFromFile(fn);

  fn := inifile.ReadString('SELECTED', 'CENTER', '');
  if fn <> '' then SkinSelectCenter.LoadFromFile(fn);

  fn := inifile.ReadString('SELECTED', 'BOTTOM', '');
  if fn <> '' then SkinSelectBottom.LoadFromFile(fn);

  SkinX := inifile.ReadInteger('MARGIN', 'X', 0);
  SkinY := inifile.ReadInteger('MARGIN', 'Y', 0);
  SkinCaptionX := inifile.ReadInteger('MARGIN', 'CAPTIONX', 0);
  SkinCaptionY := inifile.ReadInteger('MARGIN', 'CAPTIONY', 0);

  inifile.Free;

  if Assigned(OnChange) then
    OnChange(Self);

  FOwner.Invalidate;
end;

procedure TPlannerSkin.ClearSkin;
begin
  SkinTop.Assign(nil);
  SkinCenter.Assign(nil);
  SkinBottom.Assign(nil);
  SkinSelectTop.Assign(nil);
  SkinSelectCenter.Assign(nil);
  SkinSelectBottom.Assign(nil);
  if Assigned(OnChange) then
    OnChange(Self);
end;

procedure TPlannerSkin.SetSkinBottom(const AValue: TBitmap);
begin
  FSkinBottom.Assign(AValue);
  FOwner.Invalidate;
end;

procedure TPlannerSkin.SetSkinCenter(const AValue: TBitmap);
begin
  FSkinCenter.Assign(AValue);
  FOwner.Invalidate;
end;

procedure TPlannerSkin.SetSkinSelectBottom(const AValue: TBitmap);
begin
  FSkinSelectBottom.Assign(AValue);
  FOwner.Invalidate;
end;

procedure TPlannerSkin.SetSkinSelectCenter(const AValue: TBitmap);
begin
  FSkinSelectCenter.Assign(AValue);
  FOwner.Invalidate;
end;

procedure TPlannerSkin.SetSkinSelectTop(const AValue: TBitmap);
begin
  FSkinSelectTop.Assign(AValue);
  FOwner.Invalidate;
end;

procedure TPlannerSkin.SetSkinTop(const AValue: TBitmap);
begin
  FSkinTop.Assign(AValue);
  FOwner.Invalidate;
end;
{$ENDIF}


{ TPlannerSelection }

procedure TPlannerSelection.Update;
begin
  with (Collection as TPlannerSelections) do
    FOwner.UpdateSelection(SelBegin, SelEnd, SelPos, True);
end;

{ TGroupCollectionItem }

procedure TGroupCollectionItem.Assign(Source: TPersistent);
begin
  if (Source is TGroupCollectionItem) then
  begin
    FCaption := (Source as TGroupCollectionItem).Caption;
    FWideCaption := (Source as TGroupCollectionItem).Caption;
    FSpan := (Source as TGroupCollectionItem).Span;
    FTag := (Source as TGroupCollectionItem).Tag;
    FImageIndex := (Source as TGroupCollectionItem).ImageIndex;
  end;
end;

constructor TGroupCollectionItem.Create(Collection: TCollection);
begin
  inherited;
  FTag := 0;
  FSpan := 1;
  FImageIndex := -1;
end;

procedure TGroupCollectionItem.SetCaption(const value: string);
begin
  FCaption := value;
  (Collection as TGroupCollection).DoChanged;
end;

procedure TGroupCollectionItem.SetImageIndex(const value: Integer);
begin
  FImageIndex := value;
  (Collection as TGroupCollection).DoChanged;
end;

procedure TGroupCollectionItem.SetSpan(const value: Integer);
begin
  FSpan := value;
  (Collection as TGroupCollection).DoChanged;
end;

procedure TGroupCollectionItem.SetWideCaption(const value: widestring);
begin
  FWideCaption := value;
  (Collection as TGroupCollection).DoChanged;
end;

{ TGroupCollection }

function TGroupCollection.Add: TGroupCollectionItem;
begin
  Result := TGroupCollectionItem(inherited Add);
  DoChanged;
end;

constructor TGroupCollection.Create(AOwner: TPersistent; AItemClass: TCollectionItemClass);
begin
  inherited Create(AOwner, TGroupCollectionItem);
  FOwner := AOwner;
end;

procedure TGroupCollection.Assign(Source: TPersistent);
begin
  inherited;
end;

procedure TGroupCollection.DoChanged;
begin
  if Assigned(FOnChange) then
    FOnChange(Self);
end;

function TGroupCollection.GetItem(Index: Integer): TGroupCollectionItem;
begin
  Result := TGroupCollectionItem(inherited GetItem(Index));
end;

function TGroupCollection.Insert(Index: Integer): TGroupCollectionItem;
begin
  Result := TGroupCollectionItem(inherited Insert(Index));
  DoChanged;
end;

procedure TGroupCollection.SetItem(Index: Integer; AItem: TGroupCollectionItem);
begin
  inherited SetItem(Index, AItem);
  DoChanged;
end;

{ TPlannerStringList }

function TPlannerStringList.GetItem(Index: Integer): string;
begin
  if (Index >= Count) or (Index < 0) then
    Result := ''
  else
    Result := inherited Strings[Index];
end;

procedure TPlannerStringList.SetItem(Index: Integer; const value: string);
begin
  if (Index < Count) then
    inherited Strings[Index] := value;
end;

{$IFDEF FREEWARE}
function Scramble(s: string): string;
var
  R: string;
  i: Integer;
  C: Char;
  b: Byte;
begin
  R := '';
  for i := 1 to Length(s) do
  begin
    b := Ord(s[i]);
    b := (b and $E0) + ((b and $1F) xor 5);
    C := chr(b);
    R := R + C;
  end;
  Result := R;
end;
{$ENDIF}

{ TSyncPlanner }

procedure TSyncPlanner.Assign(Source: TPersistent);
begin
  if (Source is TSyncPlanner) then
  begin
    Planner := (Source as TSyncPlanner).Planner;
    ScrollVertical := (Source as TSyncPlanner).ScrollVertical;
    ScrollHorizontal:= (Source as TSyncPlanner).ScrollHorizontal;
    SelectionColumn := (Source as TSyncPlanner).SelectionColumn;
    SelectionRow := (Source as TSyncPlanner).SelectionRow;
  end;
end;

constructor TSyncPlanner.Create(AOwner: TComponent);
begin
  inherited Create;
  FOwner := AOwner;
end;

procedure TSyncPlanner.SetPlanner(const Value: TCustomPlanner);
begin
  if (Value <> FOwner) then
    FPlanner := Value;
end;



{ TPlannerTimePointers }

function TPlannerTimePointers.Add: TPlannerTimePointer;
begin
  Result := TPlannerTimePointer(inherited Add);
end;

constructor TPlannerTimePointers.Create(AOwner: TCustomPlanner);
begin
  inherited Create(TPlannerTimePointer);
  FOwner := AOwner;
end;

function TPlannerTimePointers.GetItem(Index: Integer): TPlannerTimePointer;
begin
  Result := TPlannerTimePointer(inherited Items[Index]);
end;

function TPlannerTimePointers.Insert(Index: Integer): TPlannerTimePointer;
begin
  Result := TPlannerTimePointer(inherited Insert(Index));
end;

procedure TPlannerTimePointers.SetItem(Index: Integer;
  const Value: TPlannerTimePointer);
begin
  inherited Items[Index] := Value;
end;

{ TPlannerTimePointer }

constructor TPlannerTimePointer.Create(Collection: TCollection);
begin
  inherited Create(Collection);
  Color := clBlue;
  Width := 1;
  Style := psSolid;
end;

initialization
{$IFDEF ISDELPHI}
  try
    RegisterClass(TSpeedButton);
    RegisterClass(TPlannerGrid);
    RegisterClass(TPlannerItem);
    RegisterClass(TPlannerItems);
    RegisterClass(TPlannerPanel);
    RegisterClass(TPlannerAlarm);
  except
  end;
{$ENDIF}
  RegisterClass(THeader);
  CF_PLANNERITEM := RegisterClipboardFormat('TPlanner Item');
  Screen.Cursors[crZoomIn] := LoadCursor(HInstance, 'TMSZOOMIN');
  Screen.Cursors[crZoomOut] := LoadCursor(HInstance, 'TMSZOOMOUT');
{$IFDEF FREEWARE}
  if (FindWindow(PChar(Scramble('QDuuilfdqljk')), nil) = 0) OR
  (FindWindow(PChar(Scramble('QDuuGplia`w')), nil) = 0) then
  begin
    MessageBox(0, PChar(Scramble('Duuilfdqljk%pv`v%qwldi%s`wvljk%jc%QHV%vjcqrdw`%fjhujk`kqv+') + #13#10 + Scramble
      ('Fjkqdfq%QHV%vjcqrdw`%mqqu?**rrr+qhvvjcqrdw`+fjh%cjw%sdila%ilf`kvlkb+')), PChar(Scramble('Rdwklkb')), MB_OK);
  end;
{$ENDIF}
end.
