1// Copyright 2014 PDFium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
7#ifndef FPDFSDK_INCLUDE_FSDK_MGR_H_
8#define FPDFSDK_INCLUDE_FSDK_MGR_H_
9
10#include "../../public/fpdf_formfill.h"
11#include "../../public/fpdf_fwlevent.h" // cross platform keycode and events define.
12#include "fsdk_common.h"
13#include "fsdk_define.h"
14#include "fx_systemhandler.h"
15#include "fsdk_baseannot.h"
16#include "fsdk_baseform.h"
17#include "fsdk_annothandler.h"
18#include "fsdk_actionhandler.h"
19
20class CPDFSDK_Document;
21class CPDFSDK_PageView;
22class CPDFSDK_Annot;
23class CFFL_IFormFiller;
24class CPDFSDK_Widget;
25class IFX_SystemHandler;
26class CPDFSDK_ActionHandler;
27class CJS_RuntimeFactory;
28
29#include "javascript/IJavaScript.h"
30
31class CPDFDoc_Environment FX_FINAL
32{
33public:
34	CPDFDoc_Environment(CPDF_Document * pDoc);
35	~CPDFDoc_Environment();
36
37	int RegAppHandle(FPDF_FORMFILLINFO* pFFinfo);
38
39	void FFI_Invalidate(FPDF_PAGE page, double left, double top, double right, double bottom)
40	{
41		if (m_pInfo && m_pInfo->FFI_Invalidate)
42		{
43			m_pInfo->FFI_Invalidate(m_pInfo, page, left, top, right, bottom);
44		}
45	}
46	void FFI_OutputSelectedRect(FPDF_PAGE page, double left, double top, double right, double bottom)
47	{
48		if (m_pInfo && m_pInfo->FFI_OutputSelectedRect)
49		{
50			m_pInfo->FFI_OutputSelectedRect(m_pInfo, page, left, top, right, bottom);
51		}
52	}
53
54	void FFI_SetCursor(int nCursorType)
55	{
56		if (m_pInfo && m_pInfo->FFI_SetCursor)
57		{
58			m_pInfo->FFI_SetCursor(m_pInfo, nCursorType);
59		}
60	}
61
62	int  FFI_SetTimer(int uElapse, TimerCallback lpTimerFunc)
63	{
64		if (m_pInfo && m_pInfo->FFI_SetTimer)
65		{
66			return m_pInfo->FFI_SetTimer(m_pInfo, uElapse, lpTimerFunc);
67		}
68		return -1;
69	}
70
71	void FFI_KillTimer(int nTimerID)
72	{
73		if (m_pInfo && m_pInfo->FFI_KillTimer)
74		{
75			m_pInfo->FFI_KillTimer(m_pInfo, nTimerID);
76		}
77	}
78	FX_SYSTEMTIME FFI_GetLocalTime()
79	{
80		FX_SYSTEMTIME fxtime;
81		if(m_pInfo && m_pInfo->FFI_GetLocalTime)
82		{
83			FPDF_SYSTEMTIME systime = m_pInfo->FFI_GetLocalTime(m_pInfo);
84			fxtime.wDay = systime.wDay;
85			fxtime.wDayOfWeek = systime.wDayOfWeek;
86			fxtime.wHour = systime.wHour;
87			fxtime.wMilliseconds = systime.wMilliseconds;
88			fxtime.wMinute = systime.wMinute;
89			fxtime.wMonth = systime.wMonth;
90			fxtime.wSecond = systime.wSecond;
91			fxtime.wYear = systime.wYear;
92		}
93		return fxtime;
94	}
95
96	void FFI_OnChange()
97	{
98		if(m_pInfo && m_pInfo->FFI_OnChange)
99		{
100			m_pInfo->FFI_OnChange(m_pInfo);
101		}
102	}
103
104	FX_BOOL	FFI_IsSHIFTKeyDown(FX_DWORD nFlag)
105	{
106
107		return (nFlag & FWL_EVENTFLAG_ShiftKey) != 0;
108	}
109	FX_BOOL	FFI_IsCTRLKeyDown(FX_DWORD nFlag)
110	{
111
112		return (nFlag & FWL_EVENTFLAG_ControlKey) != 0;
113	}
114	FX_BOOL	FFI_IsALTKeyDown(FX_DWORD nFlag)
115	{
116
117		return (nFlag & FWL_EVENTFLAG_AltKey) != 0;
118	}
119	FX_BOOL	FFI_IsINSERTKeyDown(FX_DWORD nFlag)
120	{
121		return FALSE;
122	}
123
124	int JS_appAlert(FX_LPCWSTR Msg, FX_LPCWSTR Title, FX_UINT Type, FX_UINT Icon)
125	{
126		if(m_pInfo && m_pInfo->m_pJsPlatform && m_pInfo->m_pJsPlatform->app_alert)
127		{
128			CFX_ByteString bsMsg = CFX_WideString(Msg).UTF16LE_Encode();
129			CFX_ByteString bsTitle = CFX_WideString(Title).UTF16LE_Encode();
130			FPDF_WIDESTRING pMsg = (FPDF_WIDESTRING)bsMsg.GetBuffer(bsMsg.GetLength());
131			FPDF_WIDESTRING pTitle = (FPDF_WIDESTRING)bsTitle.GetBuffer(bsTitle.GetLength());
132			int ret = m_pInfo->m_pJsPlatform->app_alert(m_pInfo->m_pJsPlatform, pMsg, pTitle, Type, Icon);
133			bsMsg.ReleaseBuffer();
134			bsTitle.ReleaseBuffer();
135			return ret;
136		}
137		return -1;
138	}
139
140	int JS_appResponse(FX_LPCWSTR Question, FX_LPCWSTR Title, FX_LPCWSTR Default, FX_LPCWSTR cLabel, FPDF_BOOL bPassword, void* response, int length)
141	{
142		if (m_pInfo && m_pInfo->m_pJsPlatform && m_pInfo->m_pJsPlatform->app_response)
143		{
144			CFX_ByteString bsQuestion = CFX_WideString(Question).UTF16LE_Encode();
145			CFX_ByteString bsTitle = CFX_WideString(Title).UTF16LE_Encode();
146			CFX_ByteString bsDefault = CFX_WideString(Default).UTF16LE_Encode();
147			CFX_ByteString bsLabel = CFX_WideString(cLabel).UTF16LE_Encode();
148			FPDF_WIDESTRING pQuestion = (FPDF_WIDESTRING)bsQuestion.GetBuffer(bsQuestion.GetLength());
149			FPDF_WIDESTRING pTitle = (FPDF_WIDESTRING)bsTitle.GetBuffer(bsTitle.GetLength());
150			FPDF_WIDESTRING pDefault = (FPDF_WIDESTRING)bsDefault.GetBuffer(bsDefault.GetLength());
151			FPDF_WIDESTRING pLabel = (FPDF_WIDESTRING)bsLabel.GetBuffer(bsLabel.GetLength());
152			int ret = m_pInfo->m_pJsPlatform->app_response(m_pInfo->m_pJsPlatform, pQuestion, pTitle,
153				pDefault, pLabel, bPassword, response, length);
154			bsQuestion.ReleaseBuffer();
155			bsTitle.ReleaseBuffer();
156			bsDefault.ReleaseBuffer();
157			bsLabel.ReleaseBuffer();
158			return ret;
159		}
160		return -1;
161	}
162
163	void JS_appBeep(int nType)
164	{
165		if(m_pInfo && m_pInfo->m_pJsPlatform && m_pInfo->m_pJsPlatform->app_beep)
166		{
167			m_pInfo->m_pJsPlatform->app_beep(m_pInfo->m_pJsPlatform, nType);
168		}
169	}
170
171	CFX_WideString JS_fieldBrowse()
172	{
173		if (m_pInfo && m_pInfo->m_pJsPlatform && m_pInfo->m_pJsPlatform->Field_browse)
174		{
175			int nRequiredLen = m_pInfo->m_pJsPlatform->Field_browse(m_pInfo->m_pJsPlatform, NULL, 0);
176			if (nRequiredLen <= 0)
177				return L"";
178
179			char* pbuff = new char[nRequiredLen];
180			if (!pbuff)
181				return L"";
182
183			memset(pbuff, 0, nRequiredLen);
184			int nActualLen = m_pInfo->m_pJsPlatform->Field_browse(m_pInfo->m_pJsPlatform, pbuff, nRequiredLen);
185			if (nActualLen <= 0 || nActualLen > nRequiredLen)
186			{
187				delete[] pbuff;
188				return L"";
189			}
190			CFX_ByteString bsRet = CFX_ByteString(pbuff, nActualLen);
191			CFX_WideString wsRet = CFX_WideString::FromLocal(bsRet);
192			delete[] pbuff;
193			return wsRet;
194		}
195		return L"";
196	}
197
198	CFX_WideString JS_docGetFilePath()
199	{
200		if (m_pInfo && m_pInfo->m_pJsPlatform && m_pInfo->m_pJsPlatform->Doc_getFilePath)
201		{
202			int nRequiredLen = m_pInfo->m_pJsPlatform->Doc_getFilePath(m_pInfo->m_pJsPlatform, NULL, 0);
203			if (nRequiredLen <= 0)
204				return L"";
205
206			char* pbuff = new char[nRequiredLen];
207			if (!pbuff)
208				return L"";
209
210			memset(pbuff, 0, nRequiredLen);
211			int nActualLen = m_pInfo->m_pJsPlatform->Doc_getFilePath(m_pInfo->m_pJsPlatform, pbuff, nRequiredLen);
212			if (nActualLen <= 0 || nActualLen > nRequiredLen)
213			{
214				delete[] pbuff;
215				return L"";
216			}
217			CFX_ByteString bsRet = CFX_ByteString(pbuff, nActualLen);
218			CFX_WideString wsRet = CFX_WideString::FromLocal(bsRet);
219			delete[] pbuff;
220			return wsRet;
221		}
222		return L"";
223	}
224
225	void JS_docSubmitForm(void* formData, int length, FX_LPCWSTR URL)
226	{
227		if(m_pInfo && m_pInfo->m_pJsPlatform && m_pInfo->m_pJsPlatform->Doc_submitForm)
228		{
229			CFX_ByteString bsDestination = CFX_WideString(URL).UTF16LE_Encode();
230			FPDF_WIDESTRING pDestination = (FPDF_WIDESTRING)bsDestination.GetBuffer(bsDestination.GetLength());
231			m_pInfo->m_pJsPlatform->Doc_submitForm(m_pInfo->m_pJsPlatform, formData, length, pDestination);
232			bsDestination.ReleaseBuffer();
233		}
234	}
235
236	void JS_docmailForm(void* mailData, int length, FPDF_BOOL bUI,FX_LPCWSTR To, FX_LPCWSTR Subject, FX_LPCWSTR CC, FX_LPCWSTR BCC, FX_LPCWSTR Msg)
237	{
238		if(m_pInfo && m_pInfo->m_pJsPlatform && m_pInfo->m_pJsPlatform->Doc_mail)
239		{
240			CFX_ByteString bsTo = CFX_WideString(To).UTF16LE_Encode();
241			CFX_ByteString bsCC = CFX_WideString(Subject).UTF16LE_Encode();
242			CFX_ByteString bsBcc = CFX_WideString(BCC).UTF16LE_Encode();
243			CFX_ByteString bsSubject = CFX_WideString(Subject).UTF16LE_Encode();
244			CFX_ByteString bsMsg = CFX_WideString(Msg).UTF16LE_Encode();
245			FPDF_WIDESTRING pTo = (FPDF_WIDESTRING)bsTo.GetBuffer(bsTo.GetLength());
246			FPDF_WIDESTRING pCC = (FPDF_WIDESTRING)bsCC.GetBuffer(bsCC.GetLength());
247			FPDF_WIDESTRING pBcc = (FPDF_WIDESTRING)bsBcc.GetBuffer(bsBcc.GetLength());
248			FPDF_WIDESTRING pSubject = (FPDF_WIDESTRING)bsSubject.GetBuffer(bsSubject.GetLength());
249			FPDF_WIDESTRING pMsg = (FPDF_WIDESTRING)bsMsg.GetBuffer(bsMsg.GetLength());
250			m_pInfo->m_pJsPlatform->Doc_mail(m_pInfo->m_pJsPlatform, mailData, length, bUI, pTo, pSubject,
251				pCC, pBcc, pMsg);
252			bsTo.ReleaseBuffer();
253			bsCC.ReleaseBuffer();
254			bsBcc.ReleaseBuffer();
255			bsSubject.ReleaseBuffer();
256			bsMsg.ReleaseBuffer();
257		}
258	}
259
260	void JS_docprint(FPDF_BOOL bUI , int nStart, int nEnd, FPDF_BOOL bSilent ,FPDF_BOOL bShrinkToFit,FPDF_BOOL bPrintAsImage ,FPDF_BOOL bReverse ,FPDF_BOOL bAnnotations)
261	{
262		if(m_pInfo && m_pInfo->m_pJsPlatform && m_pInfo->m_pJsPlatform->Doc_print)
263		{
264			m_pInfo->m_pJsPlatform->Doc_print(m_pInfo->m_pJsPlatform, bUI, nStart, nEnd, bSilent, bShrinkToFit, bPrintAsImage, bReverse, bAnnotations);
265		}
266	}
267	void JS_docgotoPage(int nPageNum)
268	{
269		if(m_pInfo && m_pInfo->m_pJsPlatform && m_pInfo->m_pJsPlatform->Doc_gotoPage)
270		{
271			m_pInfo->m_pJsPlatform->Doc_gotoPage(m_pInfo->m_pJsPlatform, nPageNum);
272		}
273	}
274
275	FPDF_PAGE	FFI_GetPage(FPDF_DOCUMENT document,int nPageIndex)
276	{
277		if(m_pInfo && m_pInfo->FFI_GetPage)
278		{
279			return m_pInfo->FFI_GetPage(m_pInfo, document, nPageIndex);
280		}
281		return NULL;
282	}
283
284	FPDF_PAGE FFI_GetCurrentPage(FPDF_DOCUMENT document)
285	{
286		if(m_pInfo && m_pInfo->FFI_GetCurrentPage)
287		{
288			return m_pInfo->FFI_GetCurrentPage(m_pInfo, document);
289		}
290		return NULL;
291	}
292
293	int 	FFI_GetRotation(FPDF_PAGE page)
294	{
295		if(m_pInfo && m_pInfo->FFI_GetRotation)
296		{
297			return m_pInfo->FFI_GetRotation(m_pInfo, page);
298		}
299		return 0;
300	}
301	void	FFI_ExecuteNamedAction(FX_LPCSTR namedAction)
302	{
303		if(m_pInfo && m_pInfo->FFI_ExecuteNamedAction)
304		{
305			m_pInfo->FFI_ExecuteNamedAction(m_pInfo, namedAction);
306		}
307	}
308	void	FFI_OnSetFieldInputFocus(void* field,FPDF_WIDESTRING focusText, FPDF_DWORD nTextLen, FX_BOOL bFocus)
309	{
310		if(m_pInfo && m_pInfo->FFI_SetTextFieldFocus)
311		{
312			m_pInfo->FFI_SetTextFieldFocus(m_pInfo, focusText, nTextLen, bFocus);
313		}
314	}
315
316	void	FFI_DoURIAction(FX_LPCSTR bsURI)
317	{
318		if(m_pInfo && m_pInfo->FFI_DoURIAction)
319		{
320			m_pInfo->FFI_DoURIAction(m_pInfo, bsURI);
321		}
322	}
323
324	void	FFI_DoGoToAction(int nPageIndex, int zoomMode, float* fPosArray, int sizeOfArray)
325	{
326		if(m_pInfo && m_pInfo->FFI_DoGoToAction)
327		{
328			m_pInfo->FFI_DoGoToAction(m_pInfo, nPageIndex, zoomMode, fPosArray, sizeOfArray);
329		}
330	}
331
332	FX_BOOL				IsJSInitiated();
333
334	void				SetCurrentDoc(CPDFSDK_Document* pFXDoc) {m_pSDKDoc = pFXDoc;}
335	CPDFSDK_Document*	GetCurrentDoc();
336	CPDF_Document*		GetPDFDocument() {return m_pPDFDoc;}
337
338	CFX_ByteString		GetAppName() {return "";}
339
340	CFFL_IFormFiller*	GetIFormFiller();
341	IFX_SystemHandler*	GetSysHandler() {return m_pSysHandler;}
342
343	CPDFSDK_AnnotHandlerMgr* GetAnnotHandlerMgr();
344	IFXJS_Runtime*	GetJSRuntime();
345	CPDFSDK_ActionHandler* GetActionHander();
346	FPDF_FORMFILLINFO* GetFormFillInfo() {return m_pInfo;}
347
348private:
349	CPDFSDK_AnnotHandlerMgr* m_pAnnotHandlerMgr;
350	CPDFSDK_ActionHandler*	m_pActionHandler;
351	IFXJS_Runtime*	m_pJSRuntime;
352	FPDF_FORMFILLINFO*	m_pInfo;
353	CPDFSDK_Document* m_pSDKDoc;
354	CPDF_Document* m_pPDFDoc;
355
356	CFFL_IFormFiller* m_pIFormFiller;
357	IFX_SystemHandler* m_pSysHandler;
358
359public:
360	CJS_RuntimeFactory*  m_pJSRuntimeFactory;
361};
362
363
364
365class CPDFSDK_InterForm;
366class CPDFSDK_Document
367{
368public:
369	CPDFSDK_Document(CPDF_Document* pDoc, CPDFDoc_Environment* pEnv);
370	~CPDFSDK_Document();
371
372	CPDFSDK_InterForm*		GetInterForm() ;
373	CPDF_Document*			GetDocument() {return m_pDoc;}
374
375	void					InitPageView();
376	void					AddPageView(CPDF_Page* pPDFPage, CPDFSDK_PageView* pPageView);
377	CPDFSDK_PageView*		GetPageView(CPDF_Page* pPDFPage, FX_BOOL ReNew = TRUE);
378	CPDFSDK_PageView*		GetPageView(int nIndex);
379	CPDFSDK_PageView*		GetCurrentView();
380	void					ReMovePageView(CPDF_Page* pPDFPage);
381	void					UpdateAllViews(CPDFSDK_PageView* pSender, CPDFSDK_Annot* pAnnot);
382
383	CPDFSDK_Annot*			GetFocusAnnot();
384
385	IFXJS_Runtime *			GetJsRuntime();
386
387	FX_BOOL					SetFocusAnnot(CPDFSDK_Annot* pAnnot, FX_UINT nFlag = 0);
388	FX_BOOL					KillFocusAnnot(FX_UINT nFlag = 0);
389
390	FX_BOOL					ExtractPages(const CFX_WordArray &arrExtraPages, CPDF_Document* pDstDoc);
391	FX_BOOL					InsertPages(int nInsertAt, const CPDF_Document* pSrcDoc, const CFX_WordArray &arrSrcPages);
392	FX_BOOL					DeletePages(int nStart, int nCount);
393	FX_BOOL					ReplacePages(int nPage, const CPDF_Document* pSrcDoc, const CFX_WordArray &arrSrcPages);
394
395	void					OnCloseDocument();
396
397	int						GetPageCount() {return m_pDoc->GetPageCount();}
398	FX_BOOL					GetPermissions(int nFlag);
399	FX_BOOL					GetChangeMark() {return m_bChangeMask;}
400	void					SetChangeMark() {m_bChangeMask = TRUE;}
401	void					ClearChangeMark() {m_bChangeMask= FALSE;}
402	CFX_WideString			GetPath() ;
403	CPDF_Page*				GetPage(int nIndex);
404	CPDFDoc_Environment *	GetEnv() {return m_pEnv; }
405	void				    ProcJavascriptFun();
406	FX_BOOL					ProcOpenAction();
407	CPDF_OCContext*			GetOCContext();
408private:
409	CFX_MapPtrTemplate<CPDF_Page*, CPDFSDK_PageView*> m_pageMap;
410	CPDF_Document*			m_pDoc;
411	CPDFSDK_InterForm*		m_pInterForm;
412	CPDFSDK_Annot*			m_pFocusAnnot;
413	CPDFDoc_Environment *	m_pEnv;
414	CPDF_OCContext *		m_pOccontent;
415	FX_BOOL					m_bChangeMask;
416};
417class CPDFSDK_PageView FX_FINAL
418{
419public:
420	CPDFSDK_PageView(CPDFSDK_Document* pSDKDoc,CPDF_Page* page);
421	~CPDFSDK_PageView();
422	void PageView_OnDraw(CFX_RenderDevice* pDevice, CPDF_Matrix* pUser2Device,CPDF_RenderOptions* pOptions) ;
423	CPDF_Annot*						GetPDFAnnotAtPoint(FX_FLOAT pageX, FX_FLOAT pageY);
424	CPDFSDK_Annot*					GetFXAnnotAtPoint(FX_FLOAT pageX, FX_FLOAT pageY);
425	CPDF_Annot*						GetPDFWidgetAtPoint(FX_FLOAT pageX, FX_FLOAT pageY);
426	CPDFSDK_Annot*					GetFXWidgetAtPoint(FX_FLOAT pageX, FX_FLOAT pageY);
427	CPDFSDK_Annot*					GetFocusAnnot() ;
428	void							SetFocusAnnot(CPDFSDK_Annot* pSDKAnnot,FX_UINT nFlag = 0) {m_pSDKDoc->SetFocusAnnot(pSDKAnnot, nFlag);}
429	FX_BOOL							KillFocusAnnot(FX_UINT nFlag = 0) {return m_pSDKDoc->KillFocusAnnot(nFlag);}
430	FX_BOOL							Annot_HasAppearance(CPDF_Annot* pAnnot);
431
432	CPDFSDK_Annot*					AddAnnot(CPDF_Dictionary * pDict);
433	CPDFSDK_Annot*					AddAnnot(FX_LPCSTR lpSubType,CPDF_Dictionary * pDict);
434	CPDFSDK_Annot*					AddAnnot(CPDF_Annot * pPDFAnnot);
435        FX_BOOL						DeleteAnnot(CPDFSDK_Annot* pAnnot);
436	int								CountAnnots();
437	CPDFSDK_Annot*					GetAnnot(int nIndex);
438	CPDFSDK_Annot*				    GetAnnotByDict(CPDF_Dictionary * pDict);
439	CPDF_Page*						GetPDFPage(){return m_page;}
440	CPDF_Document*					GetPDFDocument();
441	CPDFSDK_Document*				GetSDKDocument() {return m_pSDKDoc;}
442	FX_BOOL					OnLButtonDown(const CPDF_Point & point, FX_UINT nFlag);
443	FX_BOOL					OnLButtonUp(const CPDF_Point & point, FX_UINT nFlag);
444	FX_BOOL					OnChar(int nChar, FX_UINT nFlag);
445	FX_BOOL					OnKeyDown(int nKeyCode, int nFlag);
446	FX_BOOL					OnKeyUp(int nKeyCode, int nFlag);
447
448	FX_BOOL					OnMouseMove(const CPDF_Point & point, int nFlag);
449	FX_BOOL					OnMouseWheel(double deltaX, double deltaY,const CPDF_Point& point, int nFlag);
450	FX_BOOL					IsValidAnnot(FX_LPVOID p);
451	void					GetCurrentMatrix(CPDF_Matrix& matrix) {matrix = m_curMatrix;}
452	void					UpdateRects(CFX_RectArray& rects);
453	void							UpdateView(CPDFSDK_Annot* pAnnot);
454	CFX_PtrArray*					GetAnnotList(){ return &m_fxAnnotArray; }
455
456	int						GetPageIndex();
457	void							LoadFXAnnots();
458
459        void SetValid(FX_BOOL bValid) {m_bValid = bValid;}
460        FX_BOOL IsValid() {return m_bValid;}
461        void SetLock(FX_BOOL bLocked) {m_bLocked= bLocked;}
462        FX_BOOL IsLocked() {return m_bLocked;}
463        void TakeOverPage() {m_bTakeOverPage = TRUE;}
464private:
465	void PageView_OnHighlightFormFields(CFX_RenderDevice* pDevice, CPDFSDK_Widget* pWidget);
466        CPDF_Matrix m_curMatrix;
467	CPDF_Page* m_page;
468	CPDF_AnnotList* m_pAnnotList;
469	//CPDFSDK_Annot* m_pFocusAnnot;
470	CFX_PtrArray  m_fxAnnotArray;
471	CPDFSDK_Document* m_pSDKDoc;
472	CPDFSDK_Widget* m_CaptureWidget;
473	FX_BOOL m_bEnterWidget;
474	FX_BOOL m_bExitWidget;
475	FX_BOOL m_bOnWidget;
476	FX_BOOL m_bValid;
477        FX_BOOL m_bLocked;
478        FX_BOOL m_bTakeOverPage;
479};
480
481
482template<class TYPE>
483class CGW_ArrayTemplate : public CFX_ArrayTemplate<TYPE>
484{
485public:
486	CGW_ArrayTemplate(){}
487	virtual ~CGW_ArrayTemplate(){}
488
489	typedef int (*LP_COMPARE)(TYPE p1, TYPE p2);
490
491	void Sort(LP_COMPARE pCompare, FX_BOOL bAscent = TRUE)
492	{
493		int nSize = this->GetSize();
494		QuickSort(0, nSize -1, bAscent, pCompare);
495	}
496
497private:
498	void QuickSort(FX_UINT nStartPos, FX_UINT nStopPos, FX_BOOL bAscend, LP_COMPARE pCompare)
499	{
500		if (nStartPos >= nStopPos) return;
501
502		if ((nStopPos - nStartPos) == 1)
503		{
504			TYPE Value1 = this->GetAt(nStartPos);
505			TYPE Value2 = this->GetAt(nStopPos);
506
507			int iGreate = (*pCompare)(Value1, Value2);
508			if ((bAscend && iGreate > 0) || (!bAscend && iGreate < 0))
509			{
510				this->SetAt(nStartPos, Value2);
511				this->SetAt(nStopPos, Value1);
512			}
513			return;
514		}
515
516		FX_UINT m = nStartPos + (nStopPos - nStartPos) / 2;
517		FX_UINT i = nStartPos;
518
519		TYPE Value = this->GetAt(m);
520
521		while (i < m)
522		{
523			TYPE temp = this->GetAt(i);
524
525			int iGreate = (*pCompare)(temp, Value);
526			if ((bAscend && iGreate > 0) || (!bAscend && iGreate < 0))
527			{
528				this->InsertAt(m+1, temp);
529				this->RemoveAt(i);
530				m--;
531			}
532			else
533			{
534				i++;
535			}
536		}
537
538		FX_UINT j = nStopPos;
539
540		while (j > m)
541		{
542			TYPE temp = this->GetAt(j);
543
544			int iGreate = (*pCompare)(temp, Value);
545			if ((bAscend && iGreate < 0) || (!bAscend && iGreate > 0))
546			{
547				this->RemoveAt(j);
548				this->InsertAt(m, temp);
549				m++;
550			}
551			else
552			{
553				j--;
554			}
555		}
556
557		if (nStartPos < m) QuickSort(nStartPos, m, bAscend, pCompare);
558		if (nStopPos > m) QuickSort(m, nStopPos, bAscend, pCompare);
559	}
560};
561
562#endif  // FPDFSDK_INCLUDE_FSDK_MGR_H_
563