using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using foxit.pdf;
using foxit.addon.xfa;
using PDFReader_Demo_CSharp.Common;
using foxit;

namespace PDFReader_Demo_CSharp.UI
{
    public interface IConpomentViewControl
    {
        float GetScale();
        void SetScale(float scale);

        foxit.common.Rotation GetRotate();
        void SetRotate(foxit.common.Rotation rotate);

        bool IsVisiblePage(int index);
        void GoToPage(int page_index);
        void MovePage(System.Drawing.Point current_point, System.Drawing.Point goto_point);
        void UpdateControlSize();

        CReader_Page GetPage(System.Drawing.Point point);
        foxit.common.fxcrt.Matrix2D GetPageMatrix(int page_index);

        bool DocToWindow(int page_index, foxit.common.fxcrt.PointF doc_point, ref System.Drawing.Point window_point);
        bool DocToWindow(int page_index, foxit.common.fxcrt.RectF doc_rect, ref Rectangle window_rect);
        bool WindowToDoc(int page_index, System.Drawing.Point window_point, ref foxit.common.fxcrt.PointF doc_point);
        bool WindowToDoc(int page_index, Rectangle window_rect, ref foxit.common.fxcrt.RectF doc_rect);

        void DrawSelectText(List<CharRangeInfo> char_range_infor_list);
        string GetSelectText();
        void ClearSelectText();

        void DrawSearchText(int page_index, List<foxit.common.fxcrt.RectF> rect_list);
        void ClearSearchText();

        void SetFocusXFAWidget(XFAWidget xfa_widget);

        XFAWidget GetFocusXFAWidget();

        void SetHoverXFAWidget(XFAWidget xfa_widget);

        XFAWidget GetHoverXFAWidget();

        void Release();

        Rectangle GetPageRect();

        void setAlerted(bool is_alerted);
    }

    public struct PageToDisplay
    {
        public int scroll_bar_x;     //the position of horizontal scroll bar
        public int scroll_bar_y;     //the position of vertical scroll bar
        public int page_index;  //page index
    } ;

    public partial class ContinuePageViewControl : Panel, IConpomentViewControl
    {
        private WeakReference doc_weakref_ = null;

        private System.Collections.Generic.List<PageToDisplay> pagetodisplay_info_list_ = null;
        int current_page_index_;
        Dictionary<int, List<foxit.common.fxcrt.RectF>> page_select_text_rect_list_ = null;
        Dictionary<int, List<foxit.common.fxcrt.RectF>> page_search_text_rect_list_ = null;
        string select_text_string_;

        SolidBrush doc_background_brush_ = new SolidBrush(AppSetting.document_background_color);
        SolidBrush select_text_brush_ = new SolidBrush(AppSetting.select_text_color);
        SolidBrush search_text_brush_ = new SolidBrush(AppSetting.search_text_color);

        bool is_ctrl_key_down_ = false;

        private foxit.common.Rotation page_rotation_ = 0;
        private float zoom_factor_ = 1.0f;

        XFAWidget focus_xfa_widget_;
        foxit.common.fxcrt.PointF pop_point_ = new foxit.common.fxcrt.PointF();
        XFAWidget hover_xfa_widget_;

        foxit.common.fxcrt.PointF annot_focus_point_ = new foxit.common.fxcrt.PointF();

        private bool is_selecting_ = false;
        private int start_page_index_ = -1;
        private int end_page_index_ = -1;
        private int start_char_index_ = -1;
        private int end_char_index_ = -1;
        private bool is_start_select_ = false;

        private bool is_click_ = false;
        private System.Drawing.Point lbutton_down_point_;
        private bool is_lbutton_down_ = false;

        private bool has_char_ = false;
        private bool is_alerted_;

        public void setAlerted(bool is_alerted)
        {
            is_alerted_ = is_alerted;
        }

        public ContinuePageViewControl()
        {
            InitializeComponent();

            pagetodisplay_info_list_ = new List<PageToDisplay>();
            page_select_text_rect_list_ = new Dictionary<int, List<foxit.common.fxcrt.RectF>>();
            page_search_text_rect_list_ = new Dictionary<int, List<foxit.common.fxcrt.RectF>>();
        }

        public void Release()
        {
            if (focus_xfa_widget_ != null)
            {
                focus_xfa_widget_.Dispose();
                focus_xfa_widget_ = null;
            }

            if (hover_xfa_widget_ != null)
            {
                hover_xfa_widget_.Dispose();
                hover_xfa_widget_ = null;
            }
        }

        public void SetView(CPDFReaderDoc pDoc)
        {
            doc_weakref_ = new WeakReference(pDoc);
        }

        public CPDFReaderDoc GetDocument()
        {
            return doc_weakref_.IsAlive ? doc_weakref_.Target as CPDFReaderDoc : null;
        }

        public bool HasAviliableDoc()
        {
            return doc_weakref_.IsAlive;
        }

        public float GetScale()
        {
            return zoom_factor_;
        }

        public void SetScale(float scale)
        {
            if (scale != zoom_factor_)
            {
                zoom_factor_ = scale;

                UpdateControlSize();
            }
        }

        public foxit.common.Rotation GetRotate()
        {
            return page_rotation_;
        }

        public void SetRotate(foxit.common.Rotation rotate)
        {
            if (page_rotation_ != rotate)
            {
                page_rotation_ = rotate;

                UpdateControlSize();
            }
        }

        void RenderPageByGE(Graphics graphics, int index, int width, int height, int cx, int cy, bool is_for_print = false)
        {
            CPDFReaderDoc reader_doc = GetDocument();
            foxit.common.Rotation rotate = page_rotation_;
            bool is_dynamic_xfa = reader_doc.IsDynamicXFA();

            Rectangle page_rect = new Rectangle(cx, cy, width, height);
            if (!is_for_print)
            {
                Rectangle client_rect = this.ClientRectangle;
                if (page_rect.IntersectsWith(client_rect))
                    page_rect.Intersect(client_rect);
                else
                    return;
            }

            int render_left = cx < 0 ? cx : 0;
            int render_top = cy < 0 ? cy : 0;
            foxit.common.Rotation render_rotation = rotate;
            CReader_Page reader_page = reader_doc.GetPage(index);

            System.Drawing.Bitmap bitmap = reader_page.GetRenderPageBuffer(reader_doc, page_rect.Width, page_rect.Height, render_left, render_top, width, height, render_rotation, is_dynamic_xfa);
            if (bitmap != null)
            {
                graphics.DrawImage(bitmap, page_rect);
                bitmap.Dispose();
            }
        }

        public Rectangle GetPageRect()
        {
            CPDFReaderDoc reader_doc = GetDocument();
            foxit.common.Rotation rotate = page_rotation_;
            float scale = zoom_factor_;
            foreach (PageToDisplay item in pagetodisplay_info_list_)
            {
                CReader_Page reader_page = reader_doc.GetPage(item.page_index);
                float width = 0, height = 0;
                if (rotate == foxit.common.Rotation.e_Rotation0 || rotate == foxit.common.Rotation.e_Rotation180)
                {
                    height = reader_page.GetPageHeight() * scale;
                    width = reader_page.GetPageWidth() * scale;
                }
                else
                {
                    height = reader_page.GetPageWidth() * scale;
                    width = reader_page.GetPageHeight() * scale;
                }
                Rectangle page_rect = new Rectangle(item.scroll_bar_x, item.scroll_bar_y, (int)width, (int)height);
                Rectangle client_rect = this.ClientRectangle;
                if (page_rect.IntersectsWith(client_rect))
                    page_rect.Intersect(client_rect);
                return page_rect;
            }
            return new Rectangle(0, 0, 0, 0);
        }

        protected override void OnPaintBackground(PaintEventArgs e)
        {
        }
        protected override void OnPaint(PaintEventArgs pe)
        {
            base.OnPaint(pe);

            if (!HasAviliableDoc())
                return;

            CPDFReaderDoc reader_doc = GetDocument();
            foxit.common.Rotation rotate = page_rotation_;
            float scale = zoom_factor_;

            SetVisiblePageByScrollPos(-1);

            Rectangle client_rect = this.ClientRectangle;
            Bitmap bitmap = new Bitmap(client_rect.Width, client_rect.Height);
            Graphics bitmap_graphics = Graphics.FromImage(bitmap);
            bitmap_graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
            bitmap_graphics.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighSpeed;
            bitmap_graphics.Clear(AppSetting.document_background_color);

            foreach (PageToDisplay item in pagetodisplay_info_list_)
            {
                CReader_Page reader_page = reader_doc.GetPage(item.page_index);
                float width = 0, height = 0;
                if (rotate == foxit.common.Rotation.e_Rotation0 || rotate == foxit.common.Rotation.e_Rotation180)
                {
                    height = reader_page.GetPageHeight() * scale;
                    width = reader_page.GetPageWidth() * scale;
                }
                else
                {
                    height = reader_page.GetPageWidth() * scale;
                    width = reader_page.GetPageHeight() * scale;
                }

                RenderPageByGE(bitmap_graphics, (int)item.page_index, (int)width, (int)height, item.scroll_bar_x, item.scroll_bar_y);
            }

            foreach (var item in page_search_text_rect_list_)
            {
                int page_index = item.Key;
                CReader_Page reader_page = reader_doc.GetPage(page_index);
                var value_list = item.Value;
                int value_list_count = value_list.Count;
                for (int i = 0; i < value_list_count; i++)
                {
                    Rectangle temp_rect = new Rectangle();
                    DocToWindow(page_index, value_list[i], ref temp_rect);

                    bitmap_graphics.FillRectangle(search_text_brush_, temp_rect);
                }
            }

            foreach (var item in page_select_text_rect_list_)
            {
                int page_index = item.Key;
                CReader_Page reader_page = reader_doc.GetPage(page_index);
                var value_list = item.Value;
                int value_list_count = value_list.Count;
                for (int i = 0; i < value_list_count; i++)
                {
                    Rectangle temp_rect = new Rectangle();
                    DocToWindow(page_index, value_list[i], ref temp_rect);

                    bitmap_graphics.FillRectangle(select_text_brush_, temp_rect);
                }
            }

            pe.Graphics.DrawImage(bitmap, 0, 0);
            bitmap.Dispose();
            bitmap_graphics.Dispose();
        }

        public bool IsVisiblePage(int index)
        {
            return pagetodisplay_info_list_.FindIndex(a => a.page_index == index) >= 0 ? true : false;
        }

        int GetPageSpace()
        {
            return HasAviliableDoc() ? GetDocument().GetPageSpace() : 0;
        }

        float GetStartXPosWithMargin(int page_index)
        {
            if (!HasAviliableDoc())
                return 0;

            CPDFReaderDoc reader_doc = GetDocument();
            CReader_Page reader_page = reader_doc.GetPage(page_index);

            float width = 0.0f;
            Rectangle client_rect = this.ClientRectangle;
            foxit.common.Rotation rotate = page_rotation_;
            float scale = zoom_factor_;

            if (rotate == foxit.common.Rotation.e_Rotation90 || rotate == foxit.common.Rotation.e_Rotation270)
                width = reader_page.GetPageHeight() * scale;
            else
                width = reader_page.GetPageWidth() * scale;

            return client_rect.Width / 2 - width / 2 - GetPageSpace();
        }

        void SetVisiblePageByScrollPos(int vPos = -1)
        {
            if (!HasAviliableDoc())
                return;

            CPDFReaderDoc reader_doc = GetDocument();
            float scale = zoom_factor_;
            foxit.common.Rotation rotate = page_rotation_;
            float start_pos = 0, end_pos = 0;
            int start_page_index = 0;
            int end_page_index = 0;
            Rectangle client_rect = this.ClientRectangle;

            if (vPos == -1)
            {
                start_pos = this.VerticalScroll.Value;
            }
            else
            {
                start_pos = (float)vPos;
                this.AutoScrollPosition = new Point(this.HorizontalScroll.Value, (int)start_pos);
            }

            end_pos = client_rect.Height + start_pos;
            float previous_pos = start_pos;

            reader_doc.FindVisiblePage(start_pos, end_pos, ref start_page_index, ref end_page_index, scale);

            CReader_Page start_reader_page = reader_doc.GetPage(start_page_index);

            pagetodisplay_info_list_.Clear();

            float cy = 0, cx = 0;
            float offset_y = Math.Max((client_rect.Height - reader_doc.GetRealHeight(scale)) / 2, 0);
            int current_page_cy = 0;
            for (int i = start_page_index; i <= end_page_index; i++)
            {
                CReader_Page reader_page = reader_doc.GetPage(i);

                float doc_real_width = reader_doc.GetRealWidth(scale);
                if (doc_real_width < (client_rect.Right - client_rect.Left))
                {
                    cx = GetStartXPosWithMargin(i) + GetPageSpace();
                }
                else
                {
                    float width = (rotate == foxit.common.Rotation.e_Rotation90 || rotate == foxit.common.Rotation.e_Rotation270) ? reader_page.GetPageHeight() : reader_page.GetPageWidth();
                    cx = -this.HorizontalScroll.Value + (doc_real_width - width * scale) / 2;
                }
                cy = reader_page.GetPageTotalHeightWithSpace(scale) - ((rotate == foxit.common.Rotation.e_Rotation90 || rotate == foxit.common.Rotation.e_Rotation270) ? reader_page.GetPageWidth() : reader_page.GetPageHeight()) * scale + offset_y;
                PageToDisplay page_to_display_info;
                page_to_display_info.scroll_bar_x = (int)(cx + 0.5f);
                page_to_display_info.scroll_bar_y = (int)(cy - previous_pos + 0.5f);
                int client_rect_half_height = client_rect.Height / 2;
                if (i == start_page_index)
                {
                    current_page_cy = page_to_display_info.scroll_bar_y;
                    current_page_index_ = start_page_index;
                }
                else
                {
                    if (page_to_display_info.scroll_bar_y < client_rect_half_height && page_to_display_info.scroll_bar_y > current_page_cy)
                    {
                        current_page_cy = page_to_display_info.scroll_bar_y;
                        current_page_index_ = i;
                    }
                }
                page_to_display_info.page_index = i;
                pagetodisplay_info_list_.Add(page_to_display_info);
            }

            ResetCurrentPageIndex();
        }

        public void SetVisiblePageByIndex(int page_index)
        {
            if (!HasAviliableDoc())
                return;

            CPDFReaderDoc reader_doc = GetDocument();
            float scale = zoom_factor_;

            // Get the whole height of all pages.
            float current_all_pages_height = reader_doc.GetRealHeight(scale);

            // Get the total height from first page to the previous page of next visible page.
            float next_visible_page_top_height = 0;
            CReader_Page reader_page = reader_doc.GetPage(page_index - 1);
            if (reader_page != null)
            {
                next_visible_page_top_height = reader_page.GetPageTotalHeightWithSpace(scale);
            }

            int next_pos = (int)next_visible_page_top_height;

            SetVisiblePageByScrollPos(next_pos);
        }

        bool ResetCurrentPageIndex()
        {
            if (HasAviliableDoc())
            {
                CPDFReaderDoc reader_doc = GetDocument();
                reader_doc.UpdateCurPage(current_page_index_);
            }

            return true;
        }

        public bool DocToWindow(int page_index, foxit.common.fxcrt.PointF doc_point, ref System.Drawing.Point window_point)
        {
            if (pagetodisplay_info_list_.Count > 0)
            {
                CPDFReaderDoc reader_doc = GetDocument();
                float scale = zoom_factor_;
                foxit.common.Rotation rotate = page_rotation_;

                foreach (PageToDisplay i in pagetodisplay_info_list_)
                {
                    CReader_Page reader_page = GetDocument().GetPage(i.page_index);
                    if (reader_page.GetPageIndex() == page_index)
                    {
                        float width = 0, height = 0;
                        if (rotate == foxit.common.Rotation.e_Rotation0 || rotate == foxit.common.Rotation.e_Rotation180)
                        {
                            height = reader_page.GetPageHeight() * scale;
                            width = reader_page.GetPageWidth() * scale;
                        }
                        else
                        {
                            height = reader_page.GetPageWidth() * scale;
                            width = reader_page.GetPageHeight() * scale;
                        }

                        foxit.common.fxcrt.Matrix2D matrix = new foxit.common.fxcrt.Matrix2D();
                        if (reader_doc.IsDynamicXFA())
                            matrix = reader_page.GetXFAPage().GetDisplayMatrix(i.scroll_bar_x, (int)i.scroll_bar_y, (int)width, (int)height, rotate);
                        else
                            matrix = reader_page.GetPDFPage().GetDisplayMatrix(i.scroll_bar_x, (int)i.scroll_bar_y, (int)width, (int)height, rotate);

                        float pos_x = doc_point.x;
                        float pos_y = doc_point.y;
                        matrix.TransformPoint(ref pos_x, ref pos_y);
                        window_point.X = (int)(pos_x + 0.5);
                        window_point.Y = (int)(pos_y + 0.5);

                        return true;
                    }
                }
            }
            return false;
        }

        public bool DocToWindow(int page_index, foxit.common.fxcrt.RectF doc_rect, ref Rectangle window_rect)
        {
            if (pagetodisplay_info_list_.Count > 0)
            {
                CPDFReaderDoc reader_doc = GetDocument();
                float scale = zoom_factor_;
                foxit.common.Rotation rotate = page_rotation_;

                foreach (PageToDisplay i in pagetodisplay_info_list_)
                {
                    CReader_Page reader_page = GetDocument().GetPage(i.page_index);
                    if (reader_page.GetPageIndex() == page_index)
                    {
                        float width = 0, height = 0;
                        if (rotate == foxit.common.Rotation.e_Rotation0 || rotate == foxit.common.Rotation.e_Rotation180)
                        {
                            height = reader_page.GetPageHeight() * scale;
                            width = reader_page.GetPageWidth() * scale;
                        }
                        else
                        {
                            height = reader_page.GetPageWidth() * scale;
                            width = reader_page.GetPageHeight() * scale;
                        }

                        foxit.common.fxcrt.Matrix2D matrix = new foxit.common.fxcrt.Matrix2D();
                        if (GetDocument().IsDynamicXFA())
                            matrix = reader_page.GetXFAPage().GetDisplayMatrix(i.scroll_bar_x, (int)i.scroll_bar_y, (int)width, (int)height, rotate);
                        else
                            matrix = reader_page.GetPDFPage().GetDisplayMatrix(i.scroll_bar_x, (int)i.scroll_bar_y, (int)width, (int)height, rotate);
                        foxit.common.fxcrt.RectF transformed_rect = new foxit.common.fxcrt.RectF(doc_rect.left, doc_rect.bottom, doc_rect.right, doc_rect.top);

                        matrix.TransformRect(transformed_rect);
                        transformed_rect.Normalize();
                        if (transformed_rect.bottom < transformed_rect.top)
                        {
                            float temp = transformed_rect.bottom;
                            transformed_rect.bottom = transformed_rect.top;
                            transformed_rect.top = temp;
                        }

                        window_rect.X = (int)(transformed_rect.left + 0.5);
                        window_rect.Y = (int)(transformed_rect.top + 0.5);
                        window_rect.Width = (int)(transformed_rect.right - transformed_rect.left + 0.5);
                        window_rect.Height = (int)(transformed_rect.bottom - transformed_rect.top + 0.5);
                        return true;
                    }
                }
            }
            return false;
        }

        public bool WindowToDoc(int page_index, System.Drawing.Point window_point, ref foxit.common.fxcrt.PointF doc_point)
        {
            if (pagetodisplay_info_list_.Count > 0)
            {
                CPDFReaderDoc reader_doc = GetDocument();
                float scale = zoom_factor_;
                foxit.common.Rotation rotate = page_rotation_;

                foreach (PageToDisplay i in pagetodisplay_info_list_)
                {
                    CReader_Page reader_page = GetDocument().GetPage(i.page_index);
                    if (reader_page.GetPageIndex() == page_index)
                    {
                        float width = 0, height = 0;
                        if (rotate == foxit.common.Rotation.e_Rotation0 || rotate == foxit.common.Rotation.e_Rotation180)
                        {
                            height = reader_page.GetPageHeight() * scale;
                            width = reader_page.GetPageWidth() * scale;
                        }
                        else
                        {
                            height = reader_page.GetPageWidth() * scale;
                            width = reader_page.GetPageHeight() * scale;
                        }

                        foxit.common.fxcrt.Matrix2D matrix = new foxit.common.fxcrt.Matrix2D();
                        if (reader_doc.IsDynamicXFA())
                            matrix = reader_page.GetXFAPage().GetDisplayMatrix(i.scroll_bar_x, (int)i.scroll_bar_y, (int)width, (int)height, rotate);
                        else
                        {
                            if (reader_page.GetPDFPage().IsEmpty() == false)
                                matrix = reader_page.GetPDFPage().GetDisplayMatrix(i.scroll_bar_x, (int)i.scroll_bar_y, (int)width, (int)height, rotate);
                        }
                        float pos_x = window_point.X;
                        float pos_y = window_point.Y;

                        foxit.common.fxcrt.Matrix2D dest_matrix = new foxit.common.fxcrt.Matrix2D();
                        dest_matrix.SetReverse(matrix);
                        dest_matrix.TransformPoint(ref pos_x, ref pos_y);
                        doc_point.Set(pos_x, pos_y);

                        return true;
                    }
                }
            }
            return false;
        }

        public bool WindowToDoc(int page_index, Rectangle window_rect, ref foxit.common.fxcrt.RectF doc_rect)
        {
            if (pagetodisplay_info_list_.Count > 0)
            {
                CPDFReaderDoc reader_doc = GetDocument();
                float scale = zoom_factor_;
                foxit.common.Rotation rotate = page_rotation_;

                foreach (PageToDisplay i in pagetodisplay_info_list_)
                {
                    CReader_Page reader_page = GetDocument().GetPage(i.page_index);
                    if (reader_page.GetPageIndex() == page_index)
                    {
                        float width = 0, height = 0;
                        if (rotate == foxit.common.Rotation.e_Rotation0 || rotate == foxit.common.Rotation.e_Rotation180)
                        {
                            height = reader_page.GetPageHeight() * scale;
                            width = reader_page.GetPageWidth() * scale;
                        }
                        else
                        {
                            height = reader_page.GetPageWidth() * scale;
                            width = reader_page.GetPageHeight() * scale;
                        }

                        foxit.common.fxcrt.Matrix2D matrix = new foxit.common.fxcrt.Matrix2D();
                        if (reader_doc.IsDynamicXFA())
                            matrix = reader_page.GetXFAPage().GetDisplayMatrix(i.scroll_bar_x, (int)i.scroll_bar_y, (int)width, (int)height, rotate);
                        else
                            matrix = reader_page.GetPDFPage().GetDisplayMatrix(i.scroll_bar_x, (int)i.scroll_bar_y, (int)width, (int)height, rotate);

                        foxit.common.fxcrt.Matrix2D dest_matrix = new foxit.common.fxcrt.Matrix2D();
                        dest_matrix.SetReverse(matrix);
                        doc_rect = new foxit.common.fxcrt.RectF((float)(window_rect.Left), (float)(window_rect.Bottom), (float)(window_rect.Right), (float)(window_rect.Top));
                        doc_rect.Transform(dest_matrix);

                        return true;
                    }
                }
            }
            return false;
        }

        public CReader_Page GetPage(System.Drawing.Point point)
        {
            if (pagetodisplay_info_list_.Count > 0)
            {
                CPDFReaderDoc reader_doc = GetDocument();
                float scale = zoom_factor_;
                foxit.common.Rotation rotate = page_rotation_;

                foreach (PageToDisplay i in pagetodisplay_info_list_)
                {
                    CReader_Page reader_page = reader_doc.GetPage(i.page_index);
                    if (reader_page == null) continue;
                    float width = 0, height = 0;
                    if (rotate == foxit.common.Rotation.e_Rotation0 || rotate == foxit.common.Rotation.e_Rotation180)
                    {
                        height = reader_page.GetPageHeight() * scale;
                        width = reader_page.GetPageWidth() * scale;
                    }
                    else
                    {
                        height = reader_page.GetPageWidth() * scale;
                        width = reader_page.GetPageHeight() * scale;
                    }

                    Rectangle temp_rect = new Rectangle(i.scroll_bar_x, i.scroll_bar_y, (int)(width), (int)(height));
                    if (temp_rect.Contains(point))
                        return reader_page;

                }
            }

            return null;
        }

        public foxit.common.fxcrt.Matrix2D GetPageMatrix(int page_index)
        {
            foxit.common.fxcrt.Matrix2D matrix = new foxit.common.fxcrt.Matrix2D();

            if (pagetodisplay_info_list_.Count > 0)
            {
                CPDFReaderDoc reader_doc = GetDocument();
                float scale = zoom_factor_;
                foxit.common.Rotation rotate = page_rotation_;

                foreach (PageToDisplay i in pagetodisplay_info_list_)
                {
                    CReader_Page reader_page = GetDocument().GetPage(i.page_index);
                    if (reader_page == null) continue;
                    if (reader_page.GetPageIndex() == page_index)
                    {
                        float width = 0, height = 0;
                        if (rotate == foxit.common.Rotation.e_Rotation0 || rotate == foxit.common.Rotation.e_Rotation180)
                        {
                            height = reader_page.GetPageHeight() * scale;
                            width = reader_page.GetPageWidth() * scale;
                        }
                        else
                        {
                            height = reader_page.GetPageWidth() * scale;
                            width = reader_page.GetPageHeight() * scale;
                        }

                        if (reader_doc.IsDynamicXFA())
                            matrix = reader_page.GetXFAPage().GetDisplayMatrix(i.scroll_bar_x, (int)i.scroll_bar_y, (int)width, (int)height, rotate);
                        else
                            matrix = reader_page.GetPDFPage().GetDisplayMatrix(i.scroll_bar_x, (int)i.scroll_bar_y, (int)width, (int)height, rotate);

                        return matrix;
                    }
                }
            }
            return matrix;
        }

        protected override Point ScrollToControl(Control activeControl)
        {
            return this.AutoScrollPosition;
        }

        protected override void OnMouseWheel(MouseEventArgs e)
        {
            if (is_ctrl_key_down_)
            {
                if (e.Delta < 0)
                    zoomOut();
                else
                    zoomIn();
            }
            else
            {
                System.Drawing.Point mouse_point = new System.Drawing.Point(e.X, e.Y);
                mouse_point.Offset(this.Location.X, this.Location.Y);
                if (this.ClientRectangle.Contains(mouse_point))
                {
                    MovePage(e.Delta);
                }
            }

            base.OnMouseWheel(e);
        }

        protected override void OnMouseMove(MouseEventArgs e)
        {
            base.OnMouseMove(e);

            CPDFReaderDoc reader_doc = GetDocument();
            if (reader_doc == null)
                return;

            MainForm main_form = reader_doc.GetView();
            CReader_Page reader_page = GetPage(e.Location);
            if (reader_page == null)
                return;

            int page_index = reader_page.GetPageIndex();

            if (is_lbutton_down_ && main_form.IsHandTool())
            {

                using (foxit.pdf.annots.Annot annot_focus = reader_page.GetAnnotAtPoint(annot_focus_point_))
                {
                    if (annot_focus.IsEmpty() == true || annot_focus.GetType() != foxit.pdf.annots.Annot.Type.e_Widget)
                    {
                        MovePage(lbutton_down_point_, e.Location);
                    }
                }

                lbutton_down_point_ = e.Location;
            }

            if (is_selecting_ && e.Button == MouseButtons.Left)
            {
                if (Math.Abs(lbutton_down_point_.X - e.Location.X) >= 1 && Math.Abs(lbutton_down_point_.Y - e.Location.Y) >= 1)
                {
                    is_click_ = true;
                }

                if (has_char_ && is_start_select_)
                {
                    int char_index = -1;
                    int temp_page_index = -1;
                    foxit.common.fxcrt.PointF pointF = new foxit.common.fxcrt.PointF();

                    temp_page_index = reader_page.GetPageIndex();
                    WindowToDoc(temp_page_index, e.Location, ref pointF);
                    if (!reader_doc.GetCharIndexByPoint(pointF, temp_page_index, ref char_index))
                        return;
                    if (start_page_index_ == temp_page_index && char_index == start_char_index_)
                        return;

                    end_char_index_ = char_index;

                    GetSelectRect(start_page_index_, start_char_index_, temp_page_index, end_char_index_);
                    end_page_index_ = temp_page_index;
                    main_form.ShowTextPopup(this);
                }
            }


            if (reader_doc.IsDynamicXFA())
            {
                WindowToDoc(page_index, e.Location, ref pop_point_);

                XFAWidget xfa_widget = null;
                //System.Console.WriteLine("OnMouseMove---START: focus: {0},  new: {1}, {2}", focus_xfa_widget_ != null ? focus_xfa_widget_.GetHashCode() : 0, xfa_widget_ != null ? xfa_widget_.GetHashCode() : 0, xfa_widget_ != null ? xfa_widget_.IsEmpty() : false);
                if (focus_xfa_widget_ != null && !focus_xfa_widget_.IsEmpty())
                {
                    if (XFAWidget.HitTestArea.e_HitTestAreaClient != focus_xfa_widget_.OnHitTest(pop_point_))
                        xfa_widget = reader_page.GetXFAPage().GetWidgetAtDevicePoint(GetPageMatrix(page_index), new foxit.common.fxcrt.PointF((float)(e.Location.X), (float)(e.Location.Y)), 10);
                    else
                        xfa_widget = focus_xfa_widget_;
                }
                else
                    xfa_widget = reader_page.GetXFAPage().GetWidgetAtDevicePoint(GetPageMatrix(page_index), new foxit.common.fxcrt.PointF((float)(e.Location.X), (float)(e.Location.Y)), 10);


                //System.Console.WriteLine("OnMouseMove: focus: {0},  new: {1}, {2}", focus_xfa_widget_ != null ? focus_xfa_widget_.GetHashCode() : 0, xfa_widget_ != null ? xfa_widget_.GetHashCode() : 0, xfa_widget_ != null ? xfa_widget_.IsEmpty() : false);
                if (xfa_widget == null)
                    return;
                if (xfa_widget.IsEmpty())
                {
                    xfa_widget = null;
                    return;
                }
                if (hover_xfa_widget_ == null)
                    hover_xfa_widget_ = xfa_widget;

                xfa_widget.OnMouseMove(pop_point_, FWL_WinKeyFlag2FWL());
                if (hover_xfa_widget_ != null && xfa_widget.GetIndex() != hover_xfa_widget_.GetIndex())
                {
                    hover_xfa_widget_.OnMouseExit();
                    XFAWidget old_hover_xfawidget = hover_xfa_widget_;
                    hover_xfa_widget_ = xfa_widget;
                    if (xfa_widget != old_hover_xfawidget && !xfa_widget.IsEmpty())
                    {
                        xfa_widget.OnMouseEnter();
                    }
                }
            }
            else
            {
                if (is_lbutton_down_)
                {
                    WindowToDoc(page_index, e.Location, ref pop_point_);
                    foxit.pdf.interform.Filler formfiller = GetDocument().GetFormFiller();
                    if (formfiller == null) return;
                    if (formfiller.IsEmpty()) return;
                    formfiller.OnMouseMove(reader_page.GetPDFPage(), pop_point_, FWL_WinKeyFlag2FWL());
                }

            }
        }

        protected override void OnMouseDown(MouseEventArgs e)
        {
            base.OnMouseDown(e);
            is_alerted_ = false;

            CPDFReaderDoc reader_doc = GetDocument();
            if (reader_doc == null)
                return;

            MainForm main_form = reader_doc.GetView();
            CReader_Page reader_page = GetPage(e.Location);
            if (reader_page == null)
                return;

            int page_index = reader_page.GetPageIndex();

            if (e.Button == MouseButtons.Left)
            {
                is_lbutton_down_ = true;

                ClearSelectText();

                is_click_ = false;
                lbutton_down_point_ = e.Location;

                if (main_form.IsTextTool() && !is_click_)
                {
                    foxit.common.fxcrt.PointF pointF = new foxit.common.fxcrt.PointF();

                    is_start_select_ = true;
                    is_selecting_ = true;

                    start_page_index_ = page_index;
                    WindowToDoc(start_page_index_, e.Location, ref pointF);
                    annot_focus_point_ = new foxit.common.fxcrt.PointF(pointF);
                    int index = -1;
                    if (reader_doc.GetCharIndexByPoint(pointF, start_page_index_, ref index))
                    {
                        has_char_ = true;
                        start_char_index_ = index;
                    }
                }
            }


            if (reader_doc.IsDynamicXFA())
            {
                WindowToDoc(page_index, e.Location, ref pop_point_);

                if (focus_xfa_widget_ != null && !focus_xfa_widget_.IsEmpty())
                {
                    XFAWidget new_focus_xfa_widget = null;
                    bool not_in_areaclinent = true;
                    if (XFAWidget.HitTestArea.e_HitTestAreaClient != focus_xfa_widget_.OnHitTest(pop_point_))
                    {
                        new_focus_xfa_widget = reader_page.GetXFAPage().GetWidgetAtDevicePoint(GetPageMatrix(page_index), new foxit.common.fxcrt.PointF((float)(e.Location.X), (float)(e.Location.Y)), 10);
                        not_in_areaclinent = false;
                    }

                    if (not_in_areaclinent && new_focus_xfa_widget != null && !new_focus_xfa_widget.IsEmpty())
                    {
                        focus_xfa_widget_ = null;
                        focus_xfa_widget_ = new_focus_xfa_widget;
                    } 
                    else if (not_in_areaclinent == false)
                    {
                        reader_doc.GetXFADoc().KillFocus();
                        focus_xfa_widget_ = null;
                        this.Invalidate();
                        if (is_alerted_)
                        {
                            OnMouseUp(e);
                        }
                        return;
                    }
                }
                else
                    focus_xfa_widget_ = reader_page.GetXFAPage().GetWidgetAtDevicePoint(GetPageMatrix(page_index), new foxit.common.fxcrt.PointF((float)(e.Location.X), (float)(e.Location.Y)), 10);

                if (!focus_xfa_widget_.IsEmpty())
                {
                    if (e.Button == System.Windows.Forms.MouseButtons.Left)
                        focus_xfa_widget_.OnLButtonDown(pop_point_, FWL_WinKeyFlag2FWL());
                    else if (e.Button == System.Windows.Forms.MouseButtons.Right)
                        focus_xfa_widget_.OnRButtonDown(pop_point_, FWL_WinKeyFlag2FWL());
                }
                else
                {
                    reader_doc.GetXFADoc().KillFocus();
                    this.Invalidate();
                }
            }
            else
            {
                WindowToDoc(page_index, e.Location, ref pop_point_);
                annot_focus_point_ = new foxit.common.fxcrt.PointF(pop_point_);
                foxit.pdf.interform.Filler formfiller = GetDocument().GetFormFiller();
                if (formfiller == null) return;
                if (formfiller.IsEmpty()) return;
                if (e.Button == System.Windows.Forms.MouseButtons.Left)
                    formfiller.OnLButtonDown(reader_page.GetPDFPage(), pop_point_, FWL_WinKeyFlag2FWL());
                else if (e.Button == System.Windows.Forms.MouseButtons.Right)
                    formfiller.OnRButtonDown(reader_page.GetPDFPage(), pop_point_, FWL_WinKeyFlag2FWL());
            }
            if (is_alerted_)
            {
                OnMouseUp(e);
            }
        }

        protected override void OnMouseUp(MouseEventArgs e)
        {
            base.OnMouseUp(e);

            CPDFReaderDoc reader_doc = GetDocument();
            if (reader_doc == null)
                return;

            CReader_Page reader_page = GetPage(e.Location);
            if (reader_page == null)
                return;

            MainForm main_form = reader_doc.GetView();

            int page_index = reader_page.GetPageIndex();

            if (e.Button == MouseButtons.Left)
            {
                is_start_select_ = false;
            }

            is_lbutton_down_ = false;

            if (reader_doc.IsDynamicXFA())
            {
                WindowToDoc(page_index, e.Location, ref pop_point_);

                if (focus_xfa_widget_ != null && !focus_xfa_widget_.IsEmpty())
                {
                    XFAWidget new_focus_xfa_widget_ = null;

                    if (XFAWidget.HitTestArea.e_HitTestAreaClient != focus_xfa_widget_.OnHitTest(pop_point_))
                        new_focus_xfa_widget_ = reader_page.GetXFAPage().GetWidgetAtDevicePoint(GetPageMatrix(page_index), new foxit.common.fxcrt.PointF((float)(e.Location.X), (float)(e.Location.Y)), 10);
                    if (new_focus_xfa_widget_ != null && !new_focus_xfa_widget_.IsEmpty())
                    {
                        focus_xfa_widget_.Dispose();
                        focus_xfa_widget_ = null;
                        focus_xfa_widget_ = new_focus_xfa_widget_;
                    }
                }
                else
                    focus_xfa_widget_ = reader_page.GetXFAPage().GetWidgetAtDevicePoint(GetPageMatrix(page_index), new foxit.common.fxcrt.PointF((float)(e.Location.X), (float)(e.Location.Y)), 10);

                //System.Console.WriteLine("OnMouseUp: focus: {0}", focus_xfa_widget_ != null ? focus_xfa_widget_.GetHashCode() : 0);
                if (!focus_xfa_widget_.IsEmpty())
                {
                    if (e.Button == System.Windows.Forms.MouseButtons.Left)
                        focus_xfa_widget_.OnLButtonUp(pop_point_, FWL_WinKeyFlag2FWL());
                    else if (e.Button == System.Windows.Forms.MouseButtons.Right)
                        focus_xfa_widget_.OnRButtonUp(pop_point_, FWL_WinKeyFlag2FWL());
                }
                else
                {
                    reader_doc.GetXFADoc().KillFocus();
                }
            }
            else
            {
                WindowToDoc(page_index, e.Location, ref pop_point_);
                annot_focus_point_ = new foxit.common.fxcrt.PointF(pop_point_);
                foxit.pdf.interform.Filler formfiller = GetDocument().GetFormFiller();
                if (formfiller == null) return;
                if (formfiller.IsEmpty()) return;
                if (e.Button == System.Windows.Forms.MouseButtons.Left)
                    formfiller.OnLButtonUp(reader_page.GetPDFPage(), pop_point_, FWL_WinKeyFlag2FWL());
                else if (e.Button == System.Windows.Forms.MouseButtons.Right)
                    formfiller.OnRButtonUp(reader_page.GetPDFPage(), pop_point_, FWL_WinKeyFlag2FWL());

                if (is_alerted_)
                {
                    formfiller.KillFocus();
                    is_alerted_ = false;
                }
                this.Invalidate();
            }
        }

        public override bool Focused
        {
            get
            {
                return true;
            }
        }

        protected override bool IsInputKey(Keys keyData)
        {
            return true;
        }

        protected override void OnKeyDown(KeyEventArgs e)
        {
            base.OnKeyDown(e);

            if (e.Control)
                is_ctrl_key_down_ = true;

            CPDFReaderDoc reader_doc = GetDocument();
            if (reader_doc == null)
                return;

            if (reader_doc.IsDynamicXFA())
            {
                if (focus_xfa_widget_ != null && !focus_xfa_widget_.IsEmpty())
                {
                    focus_xfa_widget_.OnKeyDown((int)e.KeyCode, FWL_WinKeyFlag2FWL());
                }
            }
            else
            {
                foxit.pdf.interform.Filler formfiller = GetDocument().GetFormFiller();
                if (formfiller == null) return;
                if (formfiller.IsEmpty()) return;
                formfiller.OnKeyDown((int)e.KeyCode, FWL_WinKeyFlag2FWL());
            }
        }

        protected override void OnKeyPress(KeyPressEventArgs e)
        {
            if (e.Handled) return;

            e.Handled = true;
            base.OnKeyPress(e);

            CPDFReaderDoc reader_doc = GetDocument();
            if (reader_doc == null)
                return;

            if (reader_doc.IsDynamicXFA())
            {
                if (!focus_xfa_widget_.IsEmpty())
                {
                    focus_xfa_widget_.OnChar((int)e.KeyChar, FWL_WinKeyFlag2FWL());
                }
            }
            else
            {
                foxit.pdf.interform.Filler formfiller = GetDocument().GetFormFiller();
                if (formfiller == null) return;
                if (formfiller.IsEmpty()) return;
                formfiller.OnChar((int)e.KeyChar, FWL_WinKeyFlag2FWL());
            }
        }

        protected override void OnKeyUp(KeyEventArgs e)
        {
            base.OnKeyUp(e);

            is_ctrl_key_down_ = false;

            CPDFReaderDoc reader_doc = GetDocument();
            if (reader_doc == null)
                return;

            if (reader_doc.IsDynamicXFA())
            {
                if (focus_xfa_widget_ != null && !focus_xfa_widget_.IsEmpty())
                {
                    focus_xfa_widget_.OnKeyUp((int)e.KeyCode, FWL_WinKeyFlag2FWL());
                }
            }
            else
            {
                foxit.pdf.interform.Filler formfiller = GetDocument().GetFormFiller();
                if (formfiller == null) return;
                if (formfiller.IsEmpty()) return;
                formfiller.OnKeyUp((int)e.KeyCode, FWL_WinKeyFlag2FWL());
            }
        }

        protected override void OnDoubleClick(EventArgs e)
        {
            base.OnDoubleClick(e);

            CPDFReaderDoc reader_doc = GetDocument();
            if (reader_doc == null)
                return;

            if (reader_doc.IsDynamicXFA())
            {
                if (focus_xfa_widget_ != null && !focus_xfa_widget_.IsEmpty())
                {
                    focus_xfa_widget_.OnLButtonDoubleClick(pop_point_, FWL_WinKeyFlag2FWL());
                }
            }
            else
            {
                foxit.pdf.interform.Filler formfiller = GetDocument().GetFormFiller();
                if (formfiller == null) return;
                if (formfiller.IsEmpty()) return;
                CReader_Page reader_page = GetPage(lbutton_down_point_);
                if (reader_page == null)
                    return;
                int page_index = reader_page.GetPageIndex();
                formfiller.OnLButtonDoubleClick(reader_page.GetPDFPage(), pop_point_, FWL_WinKeyFlag2FWL());
            }
        }

        protected override void OnScroll(ScrollEventArgs se)
        {
            base.OnScroll(se);
        }

        public void DrawSelectText(int page_index, int start_char_index, int end_char_index)
        {
            CPDFReaderDoc reader_doc = GetDocument();
            float scale = zoom_factor_;
            foxit.common.Rotation rotate = page_rotation_;
            CReader_Page reader_page = reader_doc.GetPage(page_index);

            using (TextPage text_page = new TextPage(reader_page.GetPDFPage(), (int)TextPage.TextParseFlags.e_ParseTextNormal))
            {
                if (end_char_index == -1)
                    end_char_index = text_page.GetCharCount() - 1;

                int rect_count = text_page.GetTextRectCount(start_char_index, end_char_index - start_char_index + 1);
                if (rect_count == 0)
                    return;

                var node = page_select_text_rect_list_.FirstOrDefault(x => x.Key == page_index);
                List<foxit.common.fxcrt.RectF> rect_list = (node.Value != null) ? node.Value : new List<foxit.common.fxcrt.RectF>();
                if (rect_list.Count > 0)
                    rect_list.Clear();

                for (int i = 0; i < rect_count; i++)
                {
                    foxit.common.fxcrt.RectF rectF = text_page.GetTextRect(i);
                    rect_list.Add(rectF);
                }

                page_select_text_rect_list_[page_index] = rect_list;
            }
        }

        public void DrawSelectText(List<CharRangeInfo> char_range_info_list)
        {
            CPDFReaderDoc reader_doc = GetDocument();
            float scale = zoom_factor_;
            foxit.common.Rotation rotate = page_rotation_;
            ClearSelectText();

            if (char_range_info_list.Count > 0)
                select_text_string_ = "";

            foreach (var item in char_range_info_list)
            {
                int page_index = item.page_index;
                int start_char_index = item.start_char_index;
                int end_char_index = item.end_char_index;
                CReader_Page reader_page = reader_doc.GetPage(page_index);

                using (TextPage text_page = new TextPage(reader_page.GetPDFPage(), (int)TextPage.TextParseFlags.e_ParseTextNormal))
                {

                    if (end_char_index == -1)
                        end_char_index = text_page.GetCharCount() - 1;

                    int rect_count = text_page.GetTextRectCount(start_char_index, end_char_index - start_char_index + 1);
                    if (rect_count == 0)
                        return;

                    select_text_string_ += reader_page.GetChars(start_char_index, end_char_index - start_char_index + 1);

                    var node = page_select_text_rect_list_.FirstOrDefault(x => x.Key == page_index);
                    List<foxit.common.fxcrt.RectF> rect_list = (node.Value != null) ? node.Value : new List<foxit.common.fxcrt.RectF>();
                    if (rect_list.Count > 0)
                        rect_list.Clear();

                    for (int i = 0; i < rect_count; i++)
                    {
                        foxit.common.fxcrt.RectF rectF = text_page.GetTextRect(i);
                        rect_list.Add(rectF);
                    }

                    page_select_text_rect_list_[page_index] = rect_list;
                }
            }

            if (page_select_text_rect_list_.Count > 0)
            {
                this.Invalidate();
            }
        }

        public void ClearSelectText()
        {
            if (page_select_text_rect_list_.Count > 0)
            {
                page_select_text_rect_list_.Clear();
                this.Invalidate();
            }
        }

        public string GetSelectText()
        {
            return select_text_string_;
        }

        public void DrawSearchText(int page_index, List<foxit.common.fxcrt.RectF> rect_list)
        {
            page_search_text_rect_list_[page_index] = rect_list;

            if (page_search_text_rect_list_.Count > 0)
            {
                this.Invalidate();
            }
        }

        public void ClearSearchText()
        {
            if (page_search_text_rect_list_.Count > 0)
            {
                page_search_text_rect_list_.Clear();
                this.Invalidate();
            }
        }

        public void GoToPage(int page_index)
        {
            current_page_index_ = page_index;

            SetVisiblePageByIndex(page_index);

            ResetCurrentPageIndex();
        }

        public void UpdateControlSize()
        {
            if (!HasAviliableDoc())
                return;

            CPDFReaderDoc reader_doc = GetDocument();
            float scale = zoom_factor_;

            int reader_doc_real_width = (int)reader_doc.GetRealWidth(scale);
            int reader_doc_real_height = (int)reader_doc.GetRealHeight(scale);

            Rectangle client_rect = this.Parent.ClientRectangle;
            this.ClientSize = client_rect.Size;
            this.AutoScroll = true;
            this.AutoScrollMinSize = new System.Drawing.Size(reader_doc_real_width, Math.Max(reader_doc_real_height, client_rect.Height));
            Invalidate();
        }

        public void MovePage(System.Drawing.Point current_point, System.Drawing.Point goto_point)
        {
            int x = this.HorizontalScroll.Value - goto_point.X + current_point.X;
            int y = this.VerticalScroll.Value - goto_point.Y + current_point.Y;
            if (x < 0)
                x = 0;
            if (x > this.HorizontalScroll.Maximum)
                x = this.HorizontalScroll.Maximum;
            if (y < 0)
                y = 0;
            if (y > this.VerticalScroll.Maximum)
                y = this.VerticalScroll.Maximum;

            this.AutoScrollPosition = new System.Drawing.Point(x, y);
        }

        public void MovePage(int iDelta)
        {
            int x = this.HorizontalScroll.Value;
            int y = this.VerticalScroll.Value - iDelta;
            if (y < 0)
                y = 0;
            if (y > this.VerticalScroll.Maximum)
                y = this.VerticalScroll.Maximum;

            this.AutoScrollPosition = new System.Drawing.Point(x, y);
        }

        private void zoomOut()
        {
            float previous_zoom_factor = zoom_factor_;
            zoom_factor_ -= 0.1f;
            if (zoom_factor_ < 0.3f)
            {
                zoom_factor_ = 0.3f;
                if (zoom_factor_ == previous_zoom_factor)
                    return;
            }

            UpdateControlSize();
        }

        private void zoomIn()
        {
            float previous_zoom_factor = zoom_factor_;
            zoom_factor_ += 0.1f;
            if (zoom_factor_ >= 7.0f)
            {
                zoom_factor_ = 7.0f;
                if (zoom_factor_ == previous_zoom_factor)
                    return;
            }

            UpdateControlSize();
        }

        int FWL_WinKeyFlag2FWL()
        {
            foxit.pdf.interform.Filler.EventFlags filler_event_flags = (foxit.pdf.interform.Filler.EventFlags)0;

            if ((Control.ModifierKeys & Keys.Alt) == Keys.Alt)
                filler_event_flags |= foxit.pdf.interform.Filler.EventFlags.e_EventFlagAltKey;
            if ((Control.ModifierKeys & Keys.Control) == Keys.Control)
                filler_event_flags |= foxit.pdf.interform.Filler.EventFlags.e_EventFlagControlKey;
            if ((Control.ModifierKeys & Keys.Shift) == Keys.Shift)
                filler_event_flags |= foxit.pdf.interform.Filler.EventFlags.e_EventFlagShiftKey;

            if (Control.MouseButtons == System.Windows.Forms.MouseButtons.Left)
                filler_event_flags |= foxit.pdf.interform.Filler.EventFlags.e_EventFlagLeftButtonDown;

            if (Control.MouseButtons == System.Windows.Forms.MouseButtons.Middle)
                filler_event_flags |= foxit.pdf.interform.Filler.EventFlags.e_EventFlagMiddleButtonDown;

            if (Control.MouseButtons == System.Windows.Forms.MouseButtons.Right)
                filler_event_flags |= foxit.pdf.interform.Filler.EventFlags.e_EventFlagRightButtonDown;


            return (int)filler_event_flags;
        }

        void GetSelectRect(int start_page_index, int start_char_index, int end_page_index, int end_char_index)
        {
            select_text_string_ = "";
            int actual_start_page_index = start_page_index <= end_page_index ? start_page_index : end_page_index;
            int actual_end_page_index = start_page_index <= end_page_index ? end_page_index : start_page_index;
            bool is_reverse = start_page_index > end_page_index || (start_page_index == end_page_index && start_char_index > end_char_index) ? true : false;
            List<CharRangeInfo> char_range_info_list = new List<CharRangeInfo>();
            for (int i = actual_start_page_index; i <= actual_end_page_index; i++)
            {
                int temp_start_char_index = -1;
                int temp_end_char_index = -1;
                if (i == actual_start_page_index)
                {
                    temp_start_char_index = is_reverse ? end_char_index : start_char_index;
                }
                else
                {
                    temp_start_char_index = 0;
                }

                if (i == actual_end_page_index)
                {
                    temp_end_char_index = is_reverse ? start_char_index - 1 : end_char_index;
                }
                else
                {
                    temp_end_char_index = -1;
                }

                CharRangeInfo char_range_info = new CharRangeInfo();
                char_range_info.page_index = i;
                char_range_info.start_char_index = temp_start_char_index;
                char_range_info.end_char_index = temp_end_char_index;
                char_range_info_list.Add(char_range_info);
            }

            DrawSelectText(char_range_info_list);
        }

        public void SetFocusXFAWidget(XFAWidget xfa_widget)
        {
            if (xfa_widget.IsEmpty() || null == xfa_widget) return;

            string fullname = xfa_widget.GetName(XFAWidget.WidgetNameType.e_WidgetNameTypeFullName);
            string fullname_focus = focus_xfa_widget_.GetName(XFAWidget.WidgetNameType.e_WidgetNameTypeFullName);
            if (fullname == fullname_focus) return;

            if (focus_xfa_widget_ != null)
            {
                focus_xfa_widget_.Dispose();
                focus_xfa_widget_ = null;
            }
            
            if (xfa_widget == null || !xfa_widget.IsEmpty())
                focus_xfa_widget_ = xfa_widget;
        }

        public XFAWidget GetFocusXFAWidget()
        {
            return focus_xfa_widget_;
        }

        public void SetHoverXFAWidget(XFAWidget xfa_widget)
        {
            if (hover_xfa_widget_ != null)
            {
                hover_xfa_widget_.Dispose();
                hover_xfa_widget_ = null;
            }

            if (xfa_widget == null || !xfa_widget.IsEmpty())
                hover_xfa_widget_ = xfa_widget;
        }

        public XFAWidget GetHoverXFAWidget()
        {
            return hover_xfa_widget_;
        }
    }
}
