unit uSplitView;
{$I ..\..\..\Lib\PDFiumVcl.inc}

interface

uses
{$IFDEF XE2+}
  Winapi.Windows,
  Winapi.Messages,
  System.SysUtils,
  System.StrUtils,
  System.Variants,
  System.Classes,
  Vcl.Graphics,
  Vcl.Controls,
  Vcl.Forms,
  Vcl.Dialogs,
  Vcl.Buttons,
  Vcl.StdCtrls,
  Vcl.ExtCtrls,
  Vcl.XPMan,
  Vcl.ExtDlgs,
  Vcl.ImgList,
  Vcl.ComCtrls,
  Vcl.ToolWin,
  Vcl.Printers,
  Vcl.Menus,
  Vcl.Imaging.jpeg,
  Vcl.Imaging.pngimage,
{$ELSE}
  Windows,
  Messages,
  SysUtils,
  StrUtils,
  Variants,
  Classes,
  Graphics,
  Controls,
  Forms,
  Dialogs,
  Buttons,
  StdCtrls,
  ExtCtrls,
  XPMan,
  ExtDlgs,
  ImgList,
  ComCtrls,
  ToolWin,
  Printers,
  Menus,
  jpeg,
  pngimage,
{$ENDIF}
  PDFium,
  uSettings;

type
  TFormMain= class(TForm)
    Pdf1: TPdf;
    Pdf2: TPdf;
    Pdf3: TPdf;
    OpenDialog: TOpenDialog;
    ScrollBox1: TScrollBox;
    ScrollBox2: TScrollBox;
    ScrollBox3: TScrollBox;
    PdfView1: TPdfView;
    PdfView2: TPdfView;
    PdfView3: TPdfView;
    SavePictureDialog: TSavePictureDialog;
    PrintDialog: TPrintDialog;
    Splitter1: TSplitter;
    Splitter2: TSplitter;
    ProgressBar: TProgressBar;
    PanelCancel: TPanel;
    PanelButtons: TPanel;
    SpeedButtonOpenPdf1: TSpeedButton;
    SpeedButtonOpenPdf2: TSpeedButton;
    SpeedButtonOpenPdf3: TSpeedButton;
    SpeedButtonThreeView: TSpeedButton;
    SpeedButtonShowInfo: TSpeedButton;
    SpeedButtonShowText: TSpeedButton;
    SpeedButtonPreviousPage: TSpeedButton;
    SpeedButtonNextPage: TSpeedButton;
    SpeedButtonSaveAs: TSpeedButton;
    SpeedButtonFirstPage: TSpeedButton;
    SpeedButtonLastPage: TSpeedButton;
    SpeedButtonPrint: TSpeedButton;
    SpeedButtonPageNumber: TSpeedButton;
    SpeedButtonZoomOut: TSpeedButton;
    SpeedButtonZoomIn: TSpeedButton;
    SpeedButtonRotateLeft: TSpeedButton;
    SpeedButtonRotateRight: TSpeedButton;
    SpeedButtonSettings: TSpeedButton;
    SpeedButtonSearch: TSpeedButton;
    ComboBoxZoom: TComboBox;
    EditSearch: TEdit;
    Panel: TPanel;
    ButtonCancel: TButton;
    SaveDialog: TSaveDialog;
    SpeedButtonSaveBitmap: TSpeedButton;
    PopupMenu1: TPopupMenu;
    PopupMenu2: TPopupMenu;
    PopupMenu3: TPopupMenu;
    MenuItemSaveAsImage1: TMenuItem;
    MenuItemSaveAsImage2: TMenuItem;
    MenuItemSaveAsImage3: TMenuItem;
    procedure SpeedButtonOpenPdf1Click(Sender: TObject);
    procedure SpeedButtonOpenPdf2Click(Sender: TObject);
    procedure SpeedButtonOpenPdf3Click(Sender: TObject);
    procedure SpeedButtonThreeViewClick(Sender: TObject);
    procedure PdfView1PageChange(Sender: TObject);
    procedure PdfView2PageChange(Sender: TObject);
    procedure PdfView3PageChange(Sender: TObject);
    procedure SpeedButtonShowInfoClick(Sender: TObject);
    procedure SpeedButtonShowTextClick(Sender: TObject);
    procedure SpeedButtonPreviousPageClick(Sender: TObject);
    procedure SpeedButtonNextPageClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormResize(Sender: TObject);
    procedure SpeedButtonSaveAsClick(Sender: TObject);
    procedure SpeedButtonFirstPageClick(Sender: TObject);
    procedure SpeedButtonLastPageClick(Sender: TObject);
    procedure SpeedButtonPrintClick(Sender: TObject);
    procedure SpeedButtonPageNumberClick(Sender: TObject);
    procedure SpeedButtonZoomOutClick(Sender: TObject);
    procedure SpeedButtonZoomInClick(Sender: TObject);
    procedure Splitter1Moved(Sender: TObject);
    procedure SpeedButtonRotateLeftClick(Sender: TObject);
    procedure SpeedButtonRotateRightClick(Sender: TObject);
    procedure ComboBoxZoomChange(Sender: TObject);
    procedure PdfView1MouseDown(
      Sender: TObject;
      Button: TMouseButton;
      Shift : TShiftState;
      X, Y  : Integer);
    procedure PdfView1MouseUp(
      Sender: TObject;
      Button: TMouseButton;
      Shift : TShiftState;
      X, Y  : Integer);
    procedure PdfView1Paint(Sender: TObject);
    procedure PdfView1MouseMove(
      Sender: TObject;
      Shift : TShiftState;
      X, Y  : Integer);
    procedure SpeedButtonSettingsClick(Sender: TObject);
    procedure FormKeyDown(
      Sender : TObject;
      var Key: Word;
      Shift  : TShiftState);
    procedure SpeedButtonSearchClick(Sender: TObject);
    procedure FormMouseWheel(
      Sender     : TObject;
      Shift      : TShiftState;
      WheelDelta : Integer;
      MousePos   : TPoint;
      var Handled: Boolean);
    procedure EditSearchChange(Sender: TObject);
    procedure ButtonCancelClick(Sender: TObject);
    procedure ScrollBox1Click(Sender: TObject);
    procedure ScrollBox2Click(Sender: TObject);
    procedure ScrollBox3Click(Sender: TObject);
    procedure SpeedButtonSaveBitmapClick(Sender: TObject);
    procedure MenuItemSaveAsImage1Click(Sender: TObject);
    procedure MenuItemSaveAsImage2Click(Sender: TObject);
    procedure MenuItemSaveAsImage3Click(Sender: TObject);
    procedure PdfView1Click(Sender: TObject);
    procedure PdfView2Click(Sender: TObject);
    procedure PdfView3Click(Sender: TObject);
    procedure FormClick(Sender: TObject);
    procedure PanelButtonsClick(Sender: TObject);
  private
    { Private declarations }
    FActivePdfView: TPdfView; // Track the currently active PdfView
    FAllViewsMode: Boolean;
    // Track if all views are selected (no single active view)
    Selecting: Boolean;
    SelectionStart: Integer;
    SelectionEnd: Integer;
    Cancel: Boolean;

    SearchStart: Integer;
    SearchEnd: Integer;
    ThreeViewMode: Boolean;
    procedure DoZoom1;
    procedure DoZoom2;
    procedure DoZoom3;
    procedure UpdateLayout;
    procedure OpenPdfFile(
      PdfComponent    : TPdf;
      PdfViewComponent: TPdfView;
      const Title     : string);
    procedure PrintBitmap(
      Printer: TPrinter;
      Bitmap : TBitmap);
    function GetActivePdfView: TPdfView;
    function GetActivePdf: TPdf;
    procedure SetActivePdfView(PdfView: TPdfView);

    procedure UpdateControlsState;
    procedure ApplyToAllViews(const Operation: string);
    procedure ClearAllPdfViewSelections;
  public
    { Public declarations }
  end;

var
  FormMain: TFormMain;

implementation

uses
{$IFDEF XE2+}
  Vcl.Clipbrd,
  System.Types,
  Winapi.ShellApi;
{$ELSE}
  Clipbrd,
  Types,
  ShellApi;
{$ENDIF}

{$R *.dfm}

procedure Open(const Url: string);
begin
  ShellExecute(0, 'open', PChar(Url), '', '', SW_SHOWNORMAL);
end;

var
  BookmarkPages: array of TTreeNode;

procedure TFormMain.SpeedButtonThreeViewClick(Sender: TObject);
begin
  ThreeViewMode:= not ThreeViewMode;
  SpeedButtonThreeView.Down:= ThreeViewMode;
  UpdateLayout;
end;

procedure TFormMain.UpdateLayout;
var
  TotalWidth: Integer;
  ViewWidth: Integer;
begin
  if ThreeViewMode
  then
  begin
    // Three view mode: left, middle, right vertical layout (equal thirds)
    ScrollBox1.Align:= alNone;
    ScrollBox2.Align:= alNone;
    ScrollBox3.Align:= alNone;

    Splitter1.Visible:= False;

    TotalWidth:= ClientWidth;
    ViewWidth:= (TotalWidth- 6)div 3; // 6 = width of 2 splitters (3px each)

    // First ScrollBox (left) - force visible
    ScrollBox1.Left:= 0;
    ScrollBox1.Top:= Panel.Height;
    ScrollBox1.Width:= ViewWidth;
    ScrollBox1.Height:= ClientHeight- Panel.Height;
    ScrollBox1.Visible:= True;

    // Second ScrollBox (centre) - directly adjacent
    ScrollBox2.Left:= ScrollBox1.Left+ ScrollBox1.Width;
    ScrollBox2.Top:= Panel.Height;
    ScrollBox2.Width:= ViewWidth;
    ScrollBox2.Height:= ClientHeight- Panel.Height;
    ScrollBox2.Visible:= True;

    // Third ScrollBox (right) - directly adjacent
    ScrollBox3.Left:= ScrollBox2.Left+ ScrollBox2.Width;
    ScrollBox3.Top:= Panel.Height;
    ScrollBox3.Width:= TotalWidth- ScrollBox3.Left; // fill remaining space
    ScrollBox3.Height:= ClientHeight- Panel.Height;
    ScrollBox3.Visible:= True;

    // Temporarily hide Splitter2 to simplify layout
    Splitter2.Visible:= False;

    // Three-view mode: show the third open button
    SpeedButtonOpenPdf3.Visible:= True;
  end
  else
  begin
    // Two view mode: left and right vertical layout (equal halves)
    ScrollBox3.Visible:= False;
    Splitter2.Visible:= False;

    Splitter1.Visible:= False;

    // Layout: start from 0, left-side components are not used
    TotalWidth:= ClientWidth;
    ViewWidth:= TotalWidth div 2;

    ScrollBox1.Left:= 0;
    ScrollBox1.Top:= Panel.Height;
    ScrollBox1.Width:= ViewWidth;
    ScrollBox1.Height:= ClientHeight- Panel.Height;

    ScrollBox2.Left:= ScrollBox1.Left+ ScrollBox1.Width;
    ScrollBox2.Top:= Panel.Height;
    ScrollBox2.Width:= TotalWidth- ScrollBox2.Left; // fill remaining space
    ScrollBox2.Height:= ClientHeight- Panel.Height;
    ScrollBox2.Visible:= True;

    // Two-view mode: hide the third open button
    SpeedButtonOpenPdf3.Visible:= False;
  end;
end;

procedure TFormMain.OpenPdfFile(
  PdfComponent    : TPdf;
  PdfViewComponent: TPdfView;
  const Title     : string);
var
  Password: string;
begin
  if OpenDialog.Execute
  then
  begin
    PdfComponent.Active:= False;
    PdfComponent.FileName:= OpenDialog.FileName;
    PdfComponent.Password:= '';
    PdfComponent.PageNumber:= 0;
    PdfViewComponent.PageNumber:= 1;
    try
      PdfViewComponent.Active:= True;
      // Set this PdfView as the active one after successfully opening the document
      SetActivePdfView(PdfViewComponent);
    except
      on Error: EPdfError do
        if Error.Message= 'Password required or incorrect password'
        then
        begin
          if not InputQuery('Enter Password for '+ Title, 'Password: ', Password)
          then
            raise;
          PdfComponent.Password:= Password;
          PdfViewComponent.Active:= True;
          // Set this PdfView as the active one after successfully opening the document
          SetActivePdfView(PdfViewComponent);
        end
        else
          raise;
    end;
  end;
end;

procedure TFormMain.SpeedButtonOpenPdf2Click(Sender: TObject);
begin
  OpenPdfFile(Pdf2, PdfView2, 'PDF 2');
end;

procedure TFormMain.SpeedButtonOpenPdf3Click(Sender: TObject);
begin
  OpenPdfFile(Pdf3, PdfView3, 'PDF 3');
end;

procedure TFormMain.SpeedButtonOpenPdf1Click(Sender: TObject);
var
  Password: string;
begin
  if OpenDialog.Execute
  then
  begin
    Selecting:= False;
    SelectionStart:= - 1;
    SelectionEnd:= - 1;

    SpeedButtonSaveAs.Enabled:= False;
    SpeedButtonSaveBitmap.Enabled:= False;
    SpeedButtonPrint.Enabled:= False;
    SpeedButtonShowInfo.Enabled:= False;
    SpeedButtonShowText.Enabled:= False;
    SpeedButtonFirstPage.Enabled:= False;
    SpeedButtonPreviousPage.Enabled:= False;
    SpeedButtonPageNumber.Enabled:= False;
    SpeedButtonPageNumber.Caption:= '';
    SpeedButtonNextPage.Enabled:= False;
    SpeedButtonLastPage.Enabled:= False;
    SpeedButtonZoomIn.Enabled:= False;
    SpeedButtonZoomOut.Enabled:= False;
    ComboBoxZoom.Enabled:= False;
    SpeedButtonRotateLeft.Enabled:= False;
    SpeedButtonRotateRight.Enabled:= False;
    SpeedButtonSettings.Enabled:= False;
    SpeedButtonSearch.Enabled:= False;
    EditSearch.Enabled:= False;
    Splitter1.Visible:= False;

    Pdf1.Active:= False;
    Pdf1.FileName:= OpenDialog.FileName;
    Pdf1.Password:= '';
    Pdf1.PageNumber:= 0;
    PdfView1.PageNumber:= 1;
    BookmarkPages:= nil;
    try
      PdfView1.Active:= True;
    except
      on Error: EPdfError do
        if Error.Message= 'Password required or incorrect password'
        then
        begin
          if not InputQuery('Enter Password', 'Password: ', Password)
          then
            raise;
          Pdf1.Password:= Password;
          PdfView1.Active:= True;
        end
        else
          raise;
    end;

    DoZoom1;
  end;
end;

procedure TFormMain.PdfView2PageChange(Sender: TObject);
begin
  DoZoom2;
end;

procedure TFormMain.PdfView3PageChange(Sender: TObject);
begin
  DoZoom3;
end;

procedure TFormMain.PdfView1PageChange(Sender: TObject);
begin
  if PdfView1.Active
  then
  begin
    SpeedButtonSaveAs.Enabled:= True;
    SpeedButtonSaveBitmap.Enabled:= True;
    SpeedButtonPrint.Enabled:= True;
    SpeedButtonShowInfo.Enabled:= True;
    SpeedButtonShowText.Enabled:= True;
    SpeedButtonFirstPage.Enabled:= PdfView1.PageNumber> 1;
    SpeedButtonPreviousPage.Enabled:= PdfView1.PageNumber> 1;
    SpeedButtonPageNumber.Enabled:= PdfView1.PageCount> 1;
    SpeedButtonPageNumber.Caption:= IntToStr(PdfView1.PageNumber)+ ' of '+ IntToStr(PdfView1.PageCount);
    SpeedButtonNextPage.Enabled:= PdfView1.PageNumber< PdfView1.PageCount;
    SpeedButtonLastPage.Enabled:= PdfView1.PageNumber< PdfView1.PageCount;
    SpeedButtonZoomIn.Enabled:= True;
    SpeedButtonZoomOut.Enabled:= True;
    ComboBoxZoom.Enabled:= True;
    SpeedButtonRotateLeft.Enabled:= True;
    SpeedButtonRotateRight.Enabled:= True;
    SpeedButtonSettings.Enabled:= True;
    SpeedButtonSearch.Enabled:= EditSearch.Text<> '';
    EditSearch.Enabled:= True;
  end
  else
  begin
    SpeedButtonSaveAs.Enabled:= False;
    SpeedButtonSaveBitmap.Enabled:= False;
    SpeedButtonPrint.Enabled:= False;
    SpeedButtonShowInfo.Enabled:= False;
    SpeedButtonShowText.Enabled:= False;
    SpeedButtonFirstPage.Enabled:= False;
    SpeedButtonPreviousPage.Enabled:= False;
    SpeedButtonPageNumber.Enabled:= False;
    SpeedButtonPageNumber.Caption:= '';
    SpeedButtonNextPage.Enabled:= False;
    SpeedButtonLastPage.Enabled:= False;
    SpeedButtonZoomIn.Enabled:= False;
    SpeedButtonZoomOut.Enabled:= False;
    ComboBoxZoom.Enabled:= False;
    SpeedButtonRotateLeft.Enabled:= False;
    SpeedButtonRotateRight.Enabled:= False;
    SpeedButtonSettings.Enabled:= False;
    SpeedButtonSearch.Enabled:= False;
    EditSearch.Enabled:= False;
  end;

  Selecting:= False;
  SelectionStart:= - 1;
  SelectionEnd:= - 1;

  SearchStart:= - 1;
  SearchEnd:= - 1;

  DoZoom1;
  PdfView1.Invalidate;

end;

procedure TFormMain.SpeedButtonShowInfoClick(Sender: TObject);
const
  NewLine= #13#10;
begin
  ShowMessage('Author: '+ Pdf1.Author+ NewLine+ 'Creator: '+ Pdf1.Creator+ NewLine+ 'Keywords: '+ Pdf1.Keywords+ NewLine+ 'Producer: '+ Pdf1.Producer+ NewLine+
    'Subject: '+ Pdf1.Subject+ NewLine+ 'Title: '+ Pdf1.Title+ NewLine+ 'Creation date: '+ Pdf1.CreationDate+ NewLine+ 'Modified date: '+ Pdf1.ModifiedDate);
end;

procedure TFormMain.SpeedButtonShowTextClick(Sender: TObject);
begin
  ShowMessage(PdfView1.Text);
end;

procedure TFormMain.SpeedButtonFirstPageClick(Sender: TObject);
var
  ActivePdfView: TPdfView;
begin
  if FAllViewsMode
  then
    ApplyToAllViews('FirstPage')
  else
  begin
    ActivePdfView:= GetActivePdfView;
    if Assigned(ActivePdfView)
    then
      ActivePdfView.PageNumber:= 1;
  end;
end;

procedure TFormMain.SpeedButtonPreviousPageClick(Sender: TObject);
var
  ActivePdfView: TPdfView;
begin
  if FAllViewsMode
  then
    ApplyToAllViews('PreviousPage')
  else
  begin
    ActivePdfView:= GetActivePdfView;
    if Assigned(ActivePdfView)and (ActivePdfView.PageNumber> 1)
    then
      ActivePdfView.PageNumber:= ActivePdfView.PageNumber- 1;
  end;
end;

procedure TFormMain.SpeedButtonNextPageClick(Sender: TObject);
var
  ActivePdfView: TPdfView;
begin
  if FAllViewsMode
  then
    ApplyToAllViews('NextPage')
  else
  begin
    ActivePdfView:= GetActivePdfView;
    if Assigned(ActivePdfView)and (ActivePdfView.PageNumber< ActivePdfView.PageCount)
    then
      ActivePdfView.PageNumber:= ActivePdfView.PageNumber+ 1;
  end;
end;

procedure TFormMain.SpeedButtonLastPageClick(Sender: TObject);
var
  ActivePdfView: TPdfView;
begin
  if FAllViewsMode
  then
    ApplyToAllViews('LastPage')
  else
  begin
    ActivePdfView:= GetActivePdfView;
    if Assigned(ActivePdfView)
    then
      ActivePdfView.PageNumber:= ActivePdfView.PageCount;
  end;
end;

procedure TFormMain.DoZoom1;
var
  PageX, PageY, PdfPageWidth, PdfPageHeight, PageWidth, PageHeight, Zoom: Double;
  ActivePdfView: TPdfView;
  ActiveScrollBox: TScrollBox;
begin
  ActivePdfView:= GetActivePdfView;
  if Assigned(ActivePdfView)and ActivePdfView.Active
  then
  begin
    // Get the corresponding ScrollBox for the active PdfView
    if ActivePdfView= PdfView1
    then
      ActiveScrollBox:= ScrollBox1
    else if ActivePdfView= PdfView2
    then
      ActiveScrollBox:= ScrollBox2
    else if ActivePdfView= PdfView3
    then
      ActiveScrollBox:= ScrollBox3
    else
      Exit; // Should not happen

    SendMessage(ActiveScrollBox.Handle, WM_SETREDRAW, WPARAM(False), 0);

    try
      if ActivePdfView.Rotation in [ro0, ro180]
      then
      begin
        PdfPageWidth:= ActivePdfView.PageWidth;
        PdfPageHeight:= ActivePdfView.PageHeight;
      end
      else
      begin
        PdfPageWidth:= ActivePdfView.PageHeight;
        PdfPageHeight:= ActivePdfView.PageWidth;
      end;

      Zoom:= 1.0;

      case ComboBoxZoom.ItemIndex of
      0:
        Zoom:= 0.1;
      1:
        Zoom:= 0.25;
      2:
        Zoom:= 0.5;
      3:
        Zoom:= 0.75;
      4:
        Zoom:= 1.0;
      5:
        Zoom:= 1.25;
      6:
        Zoom:= 1.5;
      7:
        Zoom:= 2.0;
      8:
        Zoom:= 4.0;
      9:
        Zoom:= 8.0;
      10: // custom zoom
        begin
          if TryStrToFloat(StringReplace(ComboBoxZoom.Text, '%', '', [rfReplaceAll]), Zoom)
          then
            Zoom:= Zoom/ 100.0
          else
            Zoom:= 1.0;
        end;

      11: // zoom to page
        begin
          ActiveScrollBox.HorzScrollBar.Visible:= False;
          ActiveScrollBox.VertScrollBar.Visible:= False;

          if ActiveScrollBox.Width/ PdfPageWidth> ActiveScrollBox.Height/ PdfPageHeight
          then
          begin
            // Calculate size first
            PageWidth:= ActiveScrollBox.Height* PdfPageWidth/ PdfPageHeight;
            PageHeight:= ActiveScrollBox.Height;
            // Center both horizontally and vertically
            PageX:= (ActiveScrollBox.ClientWidth- PageWidth)/ 2.0;
            if PageX< 0
            then
              PageX:= 0;
            PageY:= (ActiveScrollBox.ClientHeight- PageHeight)/ 2.0;
            if PageY< 0
            then
              PageY:= 0;
            ActivePdfView.SetBounds(Round(PageX)- ActiveScrollBox.HorzScrollBar.ScrollPos, Round(PageY)- ActiveScrollBox.VertScrollBar.ScrollPos,
              Round(PageWidth), Round(PageHeight));
          end
          else
          begin
            // Calculate size first
            PageWidth:= ActiveScrollBox.Width;
            PageHeight:= ActiveScrollBox.Width* PdfPageHeight/ PdfPageWidth;
            // Center both horizontally and vertically
            PageX:= (ActiveScrollBox.ClientWidth- PageWidth)/ 2.0;
            if PageX< 0
            then
              PageX:= 0;
            PageY:= (ActiveScrollBox.ClientHeight- PageHeight)/ 2.0;
            if PageY< 0
            then
              PageY:= 0;
            ActivePdfView.SetBounds(Round(PageX)- ActiveScrollBox.HorzScrollBar.ScrollPos, Round(PageY)- ActiveScrollBox.VertScrollBar.ScrollPos,
              Round(PageWidth), Round(PageHeight));
          end;
        end;

      12: // fit width
        begin
          ActiveScrollBox.HorzScrollBar.Visible:= False;
          ActiveScrollBox.VertScrollBar.Visible:= True;

          // Calculate size first
          PageWidth:= ActiveScrollBox.Width;
          PageHeight:= ActiveScrollBox.Width* PdfPageHeight/ PdfPageWidth;
          // Center both horizontally and vertically
          PageX:= (ActiveScrollBox.ClientWidth- PageWidth)/ 2.0;
          if PageX< 0
          then
            PageX:= 0;
          PageY:= (ActiveScrollBox.ClientHeight- PageHeight)/ 2.0;
          if PageY< 0
          then
            PageY:= 0;
          ActivePdfView.SetBounds(Round(PageX)- ActiveScrollBox.HorzScrollBar.ScrollPos, Round(PageY)- ActiveScrollBox.VertScrollBar.ScrollPos,
            Round(PageWidth), Round(PageHeight));
        end;
      end;

      if ComboBoxZoom.ItemIndex< 11
      then
      begin
        ActiveScrollBox.HorzScrollBar.Visible:= True;
        ActiveScrollBox.VertScrollBar.Visible:= True;

        // set page size
        PageWidth:= PointsToPixels(Zoom* PdfPageWidth, Screen.PixelsPerInch);
        PageHeight:= PointsToPixels(Zoom* PdfPageHeight, Screen.PixelsPerInch);
        ActivePdfView.SetBounds(- ActiveScrollBox.HorzScrollBar.ScrollPos, - ActiveScrollBox.VertScrollBar.ScrollPos, Round(PageWidth), Round(PageHeight));

        // center page
        PageX:= (ActiveScrollBox.ClientWidth- PageWidth)/ 2.0;
        if PageX< 0
        then
          PageX:= 0;
        PageY:= (ActiveScrollBox.ClientHeight- PageHeight)/ 2.0;
        if PageY< 0
        then
          PageY:= 0;
        ActivePdfView.SetBounds(Round(PageX)- ActiveScrollBox.HorzScrollBar.ScrollPos, Round(PageY)- ActiveScrollBox.VertScrollBar.ScrollPos, Round(PageWidth),
          Round(PageHeight));
      end;

      // update zoom buttons visibility
      SpeedButtonZoomIn.Enabled:= ComboBoxZoom.ItemIndex< 9;
      SpeedButtonZoomOut.Enabled:= (ComboBoxZoom.ItemIndex> 0)and (ComboBoxZoom.ItemIndex< 10);
    finally
      SendMessage(ActiveScrollBox.Handle, WM_SETREDRAW, WPARAM(True), 0);
      ActiveScrollBox.Invalidate;
      ActivePdfView.Invalidate;
    end;
  end;
end;

procedure TFormMain.DoZoom2;
var
  PdfPageWidth, PdfPageHeight, PageWidth, PageHeight, PageX, PageY, Zoom: Double;
begin
  if PdfView2.Active
  then
  begin
    SendMessage(ScrollBox2.Handle, WM_SETREDRAW, WPARAM(False), 0);
    try
      if PdfView2.Rotation in [ro0, ro180]
      then
      begin
        PdfPageWidth:= PdfView2.PageWidth;
        PdfPageHeight:= PdfView2.PageHeight;
      end
      else
      begin
        PdfPageWidth:= PdfView2.PageHeight;
        PdfPageHeight:= PdfView2.PageWidth;
      end;

      Zoom:= 1.0;
      case ComboBoxZoom.ItemIndex of
      0:
        Zoom:= 0.1;
      1:
        Zoom:= 0.25;
      2:
        Zoom:= 0.5;
      3:
        Zoom:= 0.75;
      4:
        Zoom:= 1.0;
      5:
        Zoom:= 1.25;
      6:
        Zoom:= 1.5;
      7:
        Zoom:= 2.0;
      8:
        Zoom:= 4.0;
      9:
        Zoom:= 8.0;
      11: // zoom to page
        begin
          if ScrollBox2.Width/ PdfPageWidth> ScrollBox2.Height/ PdfPageHeight
          then
          begin
            PageWidth:= Round(ScrollBox2.Height* PdfPageWidth/ PdfPageHeight);
            PageHeight:= ScrollBox2.Height;
            PageX:= (ScrollBox2.Width- PageWidth)/ 2;
            PageY:= (ScrollBox2.Height- PageHeight)/ 2;
            PdfView2.SetBounds(Round(PageX), Round(PageY), Round(PageWidth), Round(PageHeight));
          end
          else
          begin
            PageWidth:= ScrollBox2.Width;
            PageHeight:= Round(ScrollBox2.Width* PdfPageHeight/ PdfPageWidth);
            PageX:= (ScrollBox2.Width- PageWidth)/ 2;
            PageY:= (ScrollBox2.Height- PageHeight)/ 2;
            PdfView2.SetBounds(Round(PageX), Round(PageY), Round(PageWidth), Round(PageHeight));
          end;
        end;
      12: // fit width
        begin
          PageWidth:= ScrollBox2.Width;
          PageHeight:= Round(ScrollBox2.Width* PdfPageHeight/ PdfPageWidth);
          PageX:= (ScrollBox2.Width- PageWidth)/ 2;
          PageY:= (ScrollBox2.Height- PageHeight)/ 2;
          PdfView2.SetBounds(Round(PageX), Round(PageY), Round(PageWidth), Round(PageHeight));
        end;
      end;

      if ComboBoxZoom.ItemIndex< 11
      then
      begin
        PageWidth:= PointsToPixels(Zoom* PdfPageWidth, Screen.PixelsPerInch);
        PageHeight:= PointsToPixels(Zoom* PdfPageHeight, Screen.PixelsPerInch);
        PageX:= (ScrollBox2.Width- PageWidth)/ 2;
        PageY:= (ScrollBox2.Height- PageHeight)/ 2;
        PdfView2.SetBounds(Round(PageX), Round(PageY), Round(PageWidth), Round(PageHeight));
      end;
    finally
      SendMessage(ScrollBox2.Handle, WM_SETREDRAW, WPARAM(True), 0);
      ScrollBox2.Invalidate;
      PdfView2.Invalidate;
    end;
  end;
end;

procedure TFormMain.DoZoom3;
var
  PdfPageWidth, PdfPageHeight, PageWidth, PageHeight, PageX, PageY, Zoom: Double;
begin
  if PdfView3.Active
  then
  begin
    SendMessage(ScrollBox3.Handle, WM_SETREDRAW, WPARAM(False), 0);
    try
      if PdfView3.Rotation in [ro0, ro180]
      then
      begin
        PdfPageWidth:= PdfView3.PageWidth;
        PdfPageHeight:= PdfView3.PageHeight;
      end
      else
      begin
        PdfPageWidth:= PdfView3.PageHeight;
        PdfPageHeight:= PdfView3.PageWidth;
      end;

      Zoom:= 1.0;
      case ComboBoxZoom.ItemIndex of
      0:
        Zoom:= 0.1;
      1:
        Zoom:= 0.25;
      2:
        Zoom:= 0.5;
      3:
        Zoom:= 0.75;
      4:
        Zoom:= 1.0;
      5:
        Zoom:= 1.25;
      6:
        Zoom:= 1.5;
      7:
        Zoom:= 2.0;
      8:
        Zoom:= 4.0;
      9:
        Zoom:= 8.0;
      11: // zoom to page
        begin
          if ScrollBox3.Width/ PdfPageWidth> ScrollBox3.Height/ PdfPageHeight
          then
          begin
            PageWidth:= Round(ScrollBox3.Height* PdfPageWidth/ PdfPageHeight);
            PageHeight:= ScrollBox3.Height;
            PageX:= (ScrollBox3.Width- PageWidth)/ 2;
            PageY:= (ScrollBox3.Height- PageHeight)/ 2;
            PdfView3.SetBounds(Round(PageX), Round(PageY), Round(PageWidth), Round(PageHeight));
          end
          else
          begin
            PageWidth:= ScrollBox3.Width;
            PageHeight:= Round(ScrollBox3.Width* PdfPageHeight/ PdfPageWidth);
            PageX:= (ScrollBox3.Width- PageWidth)/ 2;
            PageY:= (ScrollBox3.Height- PageHeight)/ 2;
            PdfView3.SetBounds(Round(PageX), Round(PageY), Round(PageWidth), Round(PageHeight));
          end;
        end;
      12: // fit width
        begin
          PageWidth:= ScrollBox3.Width;
          PageHeight:= Round(ScrollBox3.Width* PdfPageHeight/ PdfPageWidth);
          PageX:= (ScrollBox3.Width- PageWidth)/ 2;
          PageY:= (ScrollBox3.Height- PageHeight)/ 2;
          PdfView3.SetBounds(Round(PageX), Round(PageY), Round(PageWidth), Round(PageHeight));
        end;
      end;

      if ComboBoxZoom.ItemIndex< 11
      then
      begin
        PageWidth:= PointsToPixels(Zoom* PdfPageWidth, Screen.PixelsPerInch);
        PageHeight:= PointsToPixels(Zoom* PdfPageHeight, Screen.PixelsPerInch);
        PageX:= (ScrollBox3.Width- PageWidth)/ 2;
        PageY:= (ScrollBox3.Height- PageHeight)/ 2;
        PdfView3.SetBounds(Round(PageX), Round(PageY), Round(PageWidth), Round(PageHeight));
      end;
    finally
      SendMessage(ScrollBox3.Handle, WM_SETREDRAW, WPARAM(True), 0);
      ScrollBox3.Invalidate;
      PdfView3.Invalidate;
    end;
  end;
end;

procedure TFormMain.FormResize(Sender: TObject);
begin
  UpdateLayout;
  DoZoom1;
  DoZoom2;
  DoZoom3;
end;

procedure TFormMain.SpeedButtonSaveAsClick(Sender: TObject);
var
  ActivePdf: TPdf;
begin
  ActivePdf:= GetActivePdf;
  if not Assigned(ActivePdf)or (ActivePdf.PageCount= 0)
  then
  begin
    ShowMessage('Please open a PDF file first');
    Exit;
  end;

  SaveDialog.FileName:= 'document.pdf';
  if SaveDialog.Execute
  then
    ActivePdf.SaveAs(SaveDialog.FileName);
end;

procedure TFormMain.SpeedButtonSaveBitmapClick(Sender: TObject);
var
  Bitmap: TBitmap;
  ActivePdfView: TPdfView;
  ActivePdf: TPdf;
begin
  ActivePdfView:= GetActivePdfView;
  ActivePdf:= GetActivePdf;

  if not Assigned(ActivePdf)or (ActivePdf.PageCount= 0)
  then
  begin
    ShowMessage('Please open a PDF file first');
    Exit;
  end;

  if SavePictureDialog.Execute
  then
  begin
    Bitmap:= ActivePdfView.RenderPage(0, 0, ActivePdfView.Width, ActivePdfView.Height, ActivePdfView.Rotation, ActivePdfView.Options);
    try
      Bitmap.SaveToFile(SavePictureDialog.FileName);
    finally
      Bitmap.Free;
    end;
  end;
end;

procedure TFormMain.PrintBitmap(
  Printer: TPrinter;
  Bitmap : TBitmap);
var
  InfoHeaderSize, ImageSize: DWORD;
  InfoHeader: PBitmapInfo;
  Image: Pointer;
begin
  GetDIBSizes(Bitmap.Handle, InfoHeaderSize, ImageSize);

  InfoHeader:= AllocMem(InfoHeaderSize);
  try
    Image:= AllocMem(ImageSize);
    try
      GetDIB(Bitmap.Handle, 0, InfoHeader^, Image^);

      StretchDIBits(Printer.Canvas.Handle, 0, 0, Bitmap.Width, Bitmap.Height, 0, 0, Bitmap.Width, Bitmap.Height, Image, InfoHeader^, DIB_RGB_COLORS, SRCCOPY);
    finally
      FreeMem(Image);
    end;
  finally
    FreeMem(InfoHeader);
  end;
end;

procedure TFormMain.SpeedButtonPrintClick(Sender: TObject);
function GetPrintRotation(Rotation: TRotation): TRotation;
begin
  case Rotation of
  ro90:
    Result:= ro270;
  ro270:
    Result:= ro90;
else
  Result:= Rotation;
  end;
end;

var
  FromPage, ToPage, Page, Copy, CopyCount, CollateCopy, CollateCopyCount: Integer;
  FirstPage: Boolean;
  Bitmap: TBitmap;
  ActivePdf: TPdf;
  ActivePdfView: TPdfView;
begin
  ActivePdf:= GetActivePdf;
  ActivePdfView:= GetActivePdfView;

  if not Assigned(ActivePdf)or (ActivePdf.PageCount= 0)
  then
  begin
    ShowMessage('Please open a PDF file first');
    Exit;
  end;

  if ActivePdfView.Rotation in [ro0, ro180]
  then
    Printer.Orientation:= poPortrait
  else
    Printer.Orientation:= poLandscape;

  PrintDialog.MinPage:= 1;
  PrintDialog.MaxPage:= ActivePdf.PageCount;
  PrintDialog.Options:= [poPageNums];
  PrintDialog.FromPage:= ActivePdfView.PageNumber;
  PrintDialog.ToPage:= ActivePdfView.PageNumber;
  PrintDialog.PrintRange:= prPageNums;

  if PrintDialog.Execute
  then
  begin
    if PrintDialog.PrintRange= prPageNums
    then
    begin
      FromPage:= PrintDialog.FromPage;
      ToPage:= PrintDialog.ToPage;
    end
    else
    begin
      FromPage:= 1;
      ToPage:= ActivePdf.PageCount;
    end;

    if PrintDialog.Collate
    then
    begin
      CollateCopyCount:= PrintDialog.Copies;
      CopyCount:= 1;
    end
    else
    begin
      CollateCopyCount:= 1;
      CopyCount:= PrintDialog.Copies;
    end;

    if ActivePdf.Title<> ''
    then
      Printer.Title:= ActivePdf.Title
    else
      Printer.Title:= Caption;

    FirstPage:= True;
    Printer.BeginDoc;
    try
      Cancel:= False;
      ProgressBar.Max:= (ToPage- FromPage+ 1)* PrintDialog.Copies;
      ProgressBar.Position:= 0;
      PanelButtons.Visible:= False;
      PanelCancel.Visible:= True;

      for CollateCopy:= 1 to CollateCopyCount do
        for Page:= FromPage to ToPage do
          for Copy:= 1 to CopyCount do
          begin
            if FirstPage
            then
              FirstPage:= False
            else
              Printer.NewPage;

            ProgressBar.Position:= ProgressBar.Position+ 1;

            ActivePdf.PageNumber:= Page;
            if ActivePdf.FormFill
            then
            begin
              Bitmap:= ActivePdf.RenderPage(0, 0, Printer.PageWidth, Printer.PageHeight, GetPrintRotation(ActivePdf.PageRotation), [rePrinting]);
              try
                PrintBitmap(Printer, Bitmap);
              finally
                Bitmap.Free;
              end;
            end
            else
              ActivePdf.RenderPage(Printer.Handle, 0, 0, Printer.PageWidth, Printer.PageHeight, GetPrintRotation(ActivePdf.PageRotation), [rePrinting]);

            Application.ProcessMessages;
            if Cancel
            then
            begin
              ToPage:= 0;
              CopyCount:= 0;
            end;
          end;
    finally
      PanelCancel.Visible:= False;
      PanelButtons.Visible:= True;
      Printer.EndDoc;
    end;
  end;
end;

procedure TFormMain.SpeedButtonPageNumberClick(Sender: TObject);
var
  PageNumber: string;
  NewPageNumber: Integer;
  ActivePdfView: TPdfView;
begin
  ActivePdfView:= GetActivePdfView;
  if not Assigned(ActivePdfView)
  then
    Exit;

  PageNumber:= IntToStr(ActivePdfView.PageNumber);
  if InputQuery('Select page', 'Page number: ', PageNumber)
  then
  begin
    NewPageNumber:= StrToIntDef(PageNumber, ActivePdfView.PageNumber);
    if (NewPageNumber> 0)and (NewPageNumber<= ActivePdfView.PageCount)
    then
      ActivePdfView.PageNumber:= NewPageNumber;
  end;
end;

procedure TFormMain.SpeedButtonZoomOutClick(Sender: TObject);
begin
  if ComboBoxZoom.ItemIndex> 0
  then
    ComboBoxZoom.ItemIndex:= ComboBoxZoom.ItemIndex- 1;
  DoZoom1;
end;

procedure TFormMain.SpeedButtonZoomInClick(Sender: TObject);
begin
  if ComboBoxZoom.ItemIndex< ComboBoxZoom.Items.Count- 1
  then
    ComboBoxZoom.ItemIndex:= ComboBoxZoom.ItemIndex+ 1;
  DoZoom1;
end;

procedure TFormMain.Splitter1Moved(Sender: TObject);
begin
  DoZoom1;
end;

procedure TFormMain.SpeedButtonRotateLeftClick(Sender: TObject);
var
  ActivePdfView: TPdfView;
begin
  if FAllViewsMode
  then
    ApplyToAllViews('RotateLeft')
  else
  begin
    ActivePdfView:= GetActivePdfView;
    if Assigned(ActivePdfView)
    then
    begin
      case ActivePdfView.Rotation of
      ro0:
        ActivePdfView.Rotation:= ro270;
      ro90:
        ActivePdfView.Rotation:= ro0;
      ro180:
        ActivePdfView.Rotation:= ro90;
      ro270:
        ActivePdfView.Rotation:= ro180;
      end;
      DoZoom1;
    end;
  end;
end;

procedure TFormMain.SpeedButtonRotateRightClick(Sender: TObject);
var
  ActivePdfView: TPdfView;
begin
  if FAllViewsMode
  then
    ApplyToAllViews('RotateRight')
  else
  begin
    ActivePdfView:= GetActivePdfView;
    if Assigned(ActivePdfView)
    then
    begin
      case ActivePdfView.Rotation of
      ro0:
        ActivePdfView.Rotation:= ro90;
      ro90:
        ActivePdfView.Rotation:= ro180;
      ro180:
        ActivePdfView.Rotation:= ro270;
      ro270:
        ActivePdfView.Rotation:= ro0;
      end;
      DoZoom1;
    end;
  end;
end;

procedure TFormMain.ComboBoxZoomChange(Sender: TObject);
var
  ActivePdfView: TPdfView;
begin
  if FAllViewsMode
  then
    ApplyToAllViews('SetZoom')
  else
  begin
    DoZoom1;
    ActivePdfView:= GetActivePdfView;
    if Assigned(ActivePdfView)
    then
      ActivePdfView.SetFocus;
  end;
end;

procedure TFormMain.PdfView1MouseDown(
  Sender: TObject;
  Button: TMouseButton;
  Shift : TShiftState;
  X, Y  : Integer);
const
  Tolerance= 2.0;
var
  PageNumber, LinkIndex: Integer;
begin
  if not PdfView1.Active
  then
    Exit;

  PdfView1.SetFocus;

  LinkIndex:= PdfView1.WebLinkAtPos(X, Y, PageNumber);
  if LinkIndex<> - 1
  then
  begin
    Open(PdfView1.WebLink[PageNumber, LinkIndex].Url);
    Exit;
  end;

  LinkIndex:= PdfView1.LinkAnnotationAtPos(X, Y, PageNumber);
  if LinkIndex<> - 1
  then
  begin
    with PdfView1.LinkAnnotation[PageNumber, LinkIndex] do
      case Action of
      acGotoRemote, acLaunch, acUri:
        Open(ActionPath);
    else
      if (PageNumber>= 1)and (PageNumber<= PdfView1.PageCount)
      then
        PdfView1.PageNumber:= PageNumber;
      end;
    Exit;
  end;

  if ssDouble in Shift
  then
  begin
    // select current word
    SelectionStart:= PdfView1.CharacterIndexAtPos(X, Y, Tolerance, Tolerance);
    SelectionEnd:= SelectionStart;
    if SelectionStart>= 0
    then
    begin
      while (SelectionStart> 0)and IsCharAlphaNumericW(PdfView1.Character[SelectionStart- 1]) do
        Dec(SelectionStart);

      while (SelectionEnd< PdfView1.CharacterCount- 1)and IsCharAlphaNumericW(PdfView1.Character[SelectionEnd+ 1]) do
        Inc(SelectionEnd);

      PdfView1.Invalidate;
    end;
  end
  else
  begin
    Selecting:= True;
    SelectionStart:= - 1;
    SelectionEnd:= - 1;
  end;
end;

procedure TFormMain.PdfView1MouseMove(
  Sender: TObject;
  Shift : TShiftState;
  X, Y  : Integer);
const
  Tolerance= 2.0;
var
  SelectedIndex: Integer;
  NeedRepaint: Boolean;
begin
  if not PdfView1.Active
  then
    Exit;

  SelectedIndex:= PdfView1.CharacterIndexAtPos(X, Y, Tolerance, Tolerance);
  if (not Selecting)and (PdfView1.WebLinkAtPos(X, Y)<> - 1)
  then
    PdfView1.Cursor:= crHandPoint
  else if (not Selecting)and (PdfView1.LinkAnnotationAtPos(X, Y)<> - 1)
  then
    PdfView1.Cursor:= crHandPoint
  else if SelectedIndex>= 0
  then
    PdfView1.Cursor:= crIBeam
  else
    PdfView1.Cursor:= crDefault;

  if Selecting
  then
    if SelectedIndex>= 0
    then
    begin
      NeedRepaint:= False;

      if SelectionStart= - 1
      then
      begin
        SelectionStart:= SelectedIndex;
        NeedRepaint:= True;
      end;

      if SelectionEnd<> SelectedIndex
      then
      begin
        SelectionEnd:= SelectedIndex;
        NeedRepaint:= True;
      end;

      if NeedRepaint
      then
        PdfView1.Invalidate;
    end;
end;

procedure TFormMain.PdfView1MouseUp(
  Sender: TObject;
  Button: TMouseButton;
  Shift : TShiftState;
  X, Y  : Integer);
var
  Text: WString;
begin
  if Selecting
  then
  begin
    Selecting:= False;
    if (SelectionStart>= 0)and (SelectionEnd>= 0)
    then
    begin
      if SelectionEnd< SelectionStart
      then
        Text:= PdfView1.Text(SelectionEnd, SelectionStart- SelectionEnd+ 1)
      else
        Text:= PdfView1.Text(SelectionStart, SelectionEnd- SelectionStart+ 1);

      Clipboard.AsText:= Text;
    end;
  end;
end;

procedure TFormMain.PdfView1Paint(Sender: TObject);
begin
  PdfView1.PaintSelection(SelectionStart, SelectionEnd, $F0C080);
  PdfView1.PaintSelection(SearchStart, SearchEnd, $00E000);
end;

procedure TFormMain.SpeedButtonSettingsClick(Sender: TObject);
var
  Options: TRenderOptions;
begin
  with TFormSettings.Create(nil) do
    try
      CheckListBox.Checked[0]:= reAnnotations in PdfView1.Options;
      CheckListBox.Checked[1]:= reLcd in PdfView1.Options;
      CheckListBox.Checked[2]:= not (reNoNativeText in PdfView1.Options);
      CheckListBox.Checked[3]:= reGrayscale in PdfView1.Options;
      CheckListBox.Checked[4]:= reLimitCache in PdfView1.Options;
      CheckListBox.Checked[5]:= reHalftone in PdfView1.Options;
      CheckListBox.Checked[6]:= rePrinting in PdfView1.Options;
      CheckListBox.Checked[7]:= reReverseByteOrder in PdfView1.Options;
      CheckListBox.Checked[8]:= not (reNoSmoothText in PdfView1.Options);
      CheckListBox.Checked[9]:= not (reNoSmoothImage in PdfView1.Options);
      CheckListBox.Checked[10]:= not (reNoSmoothPath in PdfView1.Options);
      if ShowModal= mrOk
      then
      begin
        Options:= [];
        if CheckListBox.Checked[0]
        then
          Options:= Options+ [reAnnotations];
        if CheckListBox.Checked[1]
        then
          Options:= Options+ [reLcd];
        if not CheckListBox.Checked[2]
        then
          Options:= Options+ [reNoNativeText];
        if CheckListBox.Checked[3]
        then
          Options:= Options+ [reGrayscale];
        if CheckListBox.Checked[4]
        then
          Options:= Options+ [reLimitCache];
        if CheckListBox.Checked[5]
        then
          Options:= Options+ [reHalftone];
        if CheckListBox.Checked[6]
        then
          Options:= Options+ [rePrinting];
        if CheckListBox.Checked[7]
        then
          Options:= Options+ [reReverseByteOrder];
        if not CheckListBox.Checked[8]
        then
          Options:= Options+ [reNoSmoothText];
        if not CheckListBox.Checked[9]
        then
          Options:= Options+ [reNoSmoothImage];
        if not CheckListBox.Checked[10]
        then
          Options:= Options+ [reNoSmoothPath];
        PdfView1.Options:= Options;
      end;
    finally
      Free;
    end;
end;

procedure TFormMain.FormKeyDown(
  Sender : TObject;
  var Key: Word;
  Shift  : TShiftState);
begin
  if Key in [VK_LEFT, VK_RIGHT, VK_HOME, VK_END]
  then
    if EditSearch.Focused
    then
      Exit;

  case Key of
  VK_PRIOR, VK_UP, VK_LEFT:
    begin
      if SpeedButtonPreviousPage.Enabled
      then
        SpeedButtonPreviousPage.Click;
      Key:= 0;
    end;

  VK_NEXT, VK_DOWN, VK_RIGHT:
    begin
      if SpeedButtonNextPage.Enabled
      then
        SpeedButtonNextPage.Click;
      Key:= 0;
    end;

  VK_HOME:
    begin
      if SpeedButtonFirstPage.Enabled
      then
        SpeedButtonFirstPage.Click;
      Key:= 0;
    end;

  VK_END:
    begin
      if SpeedButtonLastPage.Enabled
      then
        SpeedButtonLastPage.Click;
      Key:= 0;
    end;
  end;
end;

procedure TFormMain.FormMouseWheel(
  Sender     : TObject;
  Shift      : TShiftState;
  WheelDelta : Integer;
  MousePos   : TPoint;
  var Handled: Boolean);
begin
  ScrollBox1.VertScrollBar.Position:= ScrollBox1.VertScrollBar.Position- WheelDelta;
end;

procedure TFormMain.EditSearchChange(Sender: TObject);
var
  ActivePdfView: TPdfView;
begin
  if SearchStart<> - 1
  then
  begin
    SearchStart:= - 1;
    SearchEnd:= - 1;
    ActivePdfView:= GetActivePdfView;
    if Assigned(ActivePdfView)
    then
      ActivePdfView.Repaint;
  end;
  SpeedButtonSearch.Enabled:= EditSearch.Text<> '';
end;

procedure TFormMain.SpeedButtonSearchClick(Sender: TObject);
var
  FoundIndex: Integer;
  ActivePdfView: TPdfView;
  ActivePdf: TPdf;
begin
  if EditSearch.Text<> ''
  then
  begin
    ActivePdfView:= GetActivePdfView;
    if not Assigned(ActivePdfView)or not ActivePdfView.Active
    then
      Exit;

    // Get the corresponding Pdf component for the active PdfView
    if ActivePdfView= PdfView1
    then
      ActivePdf:= Pdf1
    else if ActivePdfView= PdfView2
    then
      ActivePdf:= Pdf2
    else if ActivePdfView= PdfView3
    then
      ActivePdf:= Pdf3
    else
      Exit;

    Cancel:= False;
    ProgressBar.Max:= ActivePdf.PageCount- ActivePdfView.PageNumber+ 1;
    ProgressBar.Position:= 0;
    // PanelButtons.Visible := False;
    PanelCancel.Visible:= True;

    try
      ActivePdf.PageNumber:= ActivePdfView.PageNumber;
      if SearchStart= - 1
      then
        FoundIndex:= ActivePdf.FindFirst(EditSearch.Text, [])
      else
        FoundIndex:= ActivePdf.FindNext;

      SearchStart:= - 1;
      SearchEnd:= - 1;

      while (FoundIndex= - 1)and (ActivePdf.PageNumber< ActivePdf.PageCount) do
      begin
        ProgressBar.Position:= ProgressBar.Position+ 1;
        Application.ProcessMessages;
        if Cancel
        then
          Break;

        ActivePdf.PageNumber:= ActivePdf.PageNumber+ 1;
        FoundIndex:= ActivePdf.FindFirst(EditSearch.Text, [])
      end;

      if FoundIndex<> - 1
      then
      begin
        ActivePdfView.PageNumber:= ActivePdf.PageNumber;
        SearchStart:= FoundIndex;
        SearchEnd:= FoundIndex+ Length(EditSearch.Text)- 1;
        ActivePdfView.Invalidate; // repaint
      end
      else
      begin
        ActivePdfView.Invalidate; // repaint
        if not Cancel
        then
          ShowMessage('Text not found');
      end;
    finally
      PanelCancel.Visible:= False;
      PanelButtons.Visible:= True;
    end;
  end;
end;

procedure TFormMain.ButtonCancelClick(Sender: TObject);
begin
  Cancel:= True;
end;

procedure TFormMain.ScrollBox1Click(Sender: TObject);
begin
  // Set PdfView1 as active when ScrollBox1 is clicked
  SetActivePdfView(PdfView1);
end;

procedure TFormMain.ScrollBox2Click(Sender: TObject);
begin
  // Set PdfView2 as active when ScrollBox2 is clicked
  SetActivePdfView(PdfView2);
end;

procedure TFormMain.ScrollBox3Click(Sender: TObject);
begin
  // Set PdfView3 as active when ScrollBox3 is clicked
  SetActivePdfView(PdfView3);
end;

procedure TFormMain.MenuItemSaveAsImage1Click(Sender: TObject);
var
  Bitmap: TBitmap;
  FileExt: string;
  JpegImage: TJPEGImage;
  pngimage: TPngImage;
begin
  if not Assigned(Pdf1)or (Pdf1.PageCount= 0)
  then
  begin
    ShowMessage('Please open a PDF file in View 1 first');
    Exit;
  end;

  if SavePictureDialog.Execute
  then
  begin
    Bitmap:= PdfView1.RenderPage(0, 0, PdfView1.Width, PdfView1.Height, PdfView1.Rotation, PdfView1.Options);
    try
      FileExt:= LowerCase(ExtractFileExt(SavePictureDialog.FileName));

      if FileExt= '.jpg'
      then
      begin
        JpegImage:= TJPEGImage.Create;
        try
          JpegImage.Assign(Bitmap);
          JpegImage.SaveToFile(SavePictureDialog.FileName);
        finally
          JpegImage.Free;
        end;
      end
      else if FileExt= '.png'
      then
      begin
        pngimage:= TPngImage.Create;
        try
          pngimage.Assign(Bitmap);
          pngimage.SaveToFile(SavePictureDialog.FileName);
        finally
          pngimage.Free;
        end;
      end
      else
        Bitmap.SaveToFile(SavePictureDialog.FileName);

      ShowMessage('Image saved to: '+ SavePictureDialog.FileName);
    except
      on E: Exception do
        ShowMessage('Save failed: '+ E.Message);
    end;
    Bitmap.Free;
  end;
end;

procedure TFormMain.MenuItemSaveAsImage2Click(Sender: TObject);
var
  Bitmap: TBitmap;
  FileExt: string;
  JpegImage: TJPEGImage;
  pngimage: TPngImage;
begin
  if not Assigned(Pdf2)or (Pdf2.PageCount= 0)
  then
  begin
    ShowMessage('Please open a PDF file in View 2 first');
    Exit;
  end;

  if SavePictureDialog.Execute
  then
  begin
    Bitmap:= PdfView2.RenderPage(0, 0, PdfView2.Width, PdfView2.Height, PdfView2.Rotation, PdfView2.Options);
    try
      FileExt:= LowerCase(ExtractFileExt(SavePictureDialog.FileName));

      if FileExt= '.jpg'
      then
      begin
        JpegImage:= TJPEGImage.Create;
        try
          JpegImage.Assign(Bitmap);
          JpegImage.SaveToFile(SavePictureDialog.FileName);
        finally
          JpegImage.Free;
        end;
      end
      else if FileExt= '.png'
      then
      begin
        pngimage:= TPngImage.Create;
        try
          pngimage.Assign(Bitmap);
          pngimage.SaveToFile(SavePictureDialog.FileName);
        finally
          pngimage.Free;
        end;
      end
      else
        Bitmap.SaveToFile(SavePictureDialog.FileName);

      ShowMessage('Image saved to: '+ SavePictureDialog.FileName);
    except
      on E: Exception do
        ShowMessage('Save failed: '+ E.Message);
    end;
    Bitmap.Free;
  end;
end;

procedure TFormMain.MenuItemSaveAsImage3Click(Sender: TObject);
var
  Bitmap: TBitmap;
  FileExt: string;
  JpegImage: TJPEGImage;
  pngimage: TPngImage;
begin
  if not Assigned(Pdf3)or (Pdf3.PageCount= 0)
  then
  begin
    ShowMessage('Please open a PDF file in View 3 first');
    Exit;
  end;

  if SavePictureDialog.Execute
  then
  begin
    Bitmap:= PdfView3.RenderPage(0, 0, PdfView3.Width, PdfView3.Height, PdfView3.Rotation, PdfView3.Options);
    try
      FileExt:= LowerCase(ExtractFileExt(SavePictureDialog.FileName));

      if FileExt= '.jpg'
      then
      begin
        JpegImage:= TJPEGImage.Create;
        try
          JpegImage.Assign(Bitmap);
          JpegImage.SaveToFile(SavePictureDialog.FileName);
        finally
          JpegImage.Free;
        end;
      end
      else if FileExt= '.png'
      then
      begin
        pngimage:= TPngImage.Create;
        try
          pngimage.Assign(Bitmap);
          pngimage.SaveToFile(SavePictureDialog.FileName);
        finally
          pngimage.Free;
        end;
      end
      else
        Bitmap.SaveToFile(SavePictureDialog.FileName);

      ShowMessage('Image saved to: '+ SavePictureDialog.FileName);
    except
      on E: Exception do
        ShowMessage('Save failed: '+ E.Message);
    end;
    Bitmap.Free;
  end;
end;

function TFormMain.GetActivePdfView: TPdfView;
begin
  // Return the currently active PdfView based on our tracking field
  if Assigned(FActivePdfView)
  then
    Result:= FActivePdfView
  else
    Result:= PdfView1; // Default to PdfView1 if none is set
end;

function TFormMain.GetActivePdf: TPdf;
begin
  // Return the PDF component associated with the active PdfView
  if PdfView1.Active
  then
    Result:= Pdf1
  else if PdfView2.Active
  then
    Result:= Pdf2
  else if PdfView3.Active
  then
    Result:= Pdf3
  else
    Result:= Pdf1; // Default to Pdf1 if none is active
end;

procedure TFormMain.SetActivePdfView(PdfView: TPdfView);
begin
  // Set the active PdfView and provide visual feedback
  if Assigned(PdfView)
  then
  begin
    FActivePdfView:= PdfView;
    FAllViewsMode:= False;
    PdfView.SetFocus;

    // Update visual indicators - change background color
    PdfView1.Color:= clWindow;
    PdfView2.Color:= clWindow;
    PdfView3.Color:= clWindow;

    PdfView.Color:= clActiveCaption;

    UpdateControlsState;
  end;
end;

procedure TFormMain.UpdateControlsState;
begin
  // Update search controls based on mode
  EditSearch.Enabled:= not FAllViewsMode and Assigned(FActivePdfView)and FActivePdfView.Active;
  SpeedButtonSearch.Enabled:= EditSearch.Enabled and (EditSearch.Text<> '');

  // Other controls remain enabled for both modes
end;

procedure TFormMain.ApplyToAllViews(const Operation: string);
var
  Views: array [0.. 2] of TPdfView;
  i: Integer;
begin
  Views[0]:= PdfView1;
  Views[1]:= PdfView2;
  Views[2]:= PdfView3;

  for i:= 0 to 2 do
  begin
    if Views[i].Active
    then
    begin
      if Operation= 'NextPage'
      then
      begin
        if Views[i].PageNumber< Views[i].Pdf.PageCount
        then
          Views[i].PageNumber:= Views[i].PageNumber+ 1;
      end
      else if Operation= 'PreviousPage'
      then
      begin
        if Views[i].PageNumber> 1
        then
          Views[i].PageNumber:= Views[i].PageNumber- 1;
      end
      else if Operation= 'FirstPage'
      then
      begin
        Views[i].PageNumber:= 1;
      end
      else if Operation= 'LastPage'
      then
      begin
        Views[i].PageNumber:= Views[i].Pdf.PageCount;
      end
      else if Operation= 'RotateLeft'
      then
      begin
        Views[i].Rotation:= TRotation((Ord(Views[i].Rotation)+ 3)mod 4);
      end
      else if Operation= 'RotateRight'
      then
      begin
        Views[i].Rotation:= TRotation((Ord(Views[i].Rotation)+ 1)mod 4);
      end
      else if Operation= 'SetZoom'
      then
      begin
        // Apply zoom to specific view by temporarily setting it as active
        FActivePdfView:= Views[i];
        DoZoom1;
      end;
    end;
  end;
end;

procedure TFormMain.PdfView1Click(Sender: TObject);
begin
  // Set PdfView1 as active when clicked
  SetActivePdfView(PdfView1);
end;

procedure TFormMain.PdfView2Click(Sender: TObject);
begin
  // Set PdfView2 as active when clicked
  SetActivePdfView(PdfView2);
end;

procedure TFormMain.PdfView3Click(Sender: TObject);
begin
  // Set PdfView3 as active when clicked
  SetActivePdfView(PdfView3);
end;

procedure TFormMain.FormCreate(Sender: TObject);
begin
  Selecting:= False;
  SelectionStart:= 0;
  SelectionEnd:= 0;

  // Initialize the active PdfView to PdfView1
  FActivePdfView:= PdfView1;
  FAllViewsMode:= False;
  SetActivePdfView(PdfView1);
end;

procedure TFormMain.FormClick(Sender: TObject);
begin
  // Handle form click event - clear any active selections
  ClearAllPdfViewSelections;
end;

procedure TFormMain.PanelButtonsClick(Sender: TObject);
begin
  // Handle panel buttons click event - clear any active selections when clicking on toolbar
  ClearAllPdfViewSelections;
end;

procedure TFormMain.ClearAllPdfViewSelections;
begin
  // Clear all PdfView selections and reset visual indicators
  FActivePdfView:= nil;
  FAllViewsMode:= False;

  // Reset all PdfView colors to default
  PdfView1.Color:= clWindow;
  PdfView2.Color:= clWindow;
  PdfView3.Color:= clWindow;

  // Update controls state
  UpdateControlsState;

  // Set focus to form to remove focus from any PdfView
  if CanFocus
  then
    SetFocus;
end;

end.
