2bf4f5e8103498e9e99f4986f5046b1728b2529f
[pdfium.git] / fpdfsdk / src / javascript / Document.cpp
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 #include "../../include/javascript/JavaScript.h"
8 #include "../../include/javascript/IJavaScript.h"
9 #include "../../include/javascript/JS_Define.h"
10 #include "../../include/javascript/JS_Object.h"
11 #include "../../include/javascript/JS_Value.h"
12 #include "../../include/javascript/Document.h"
13 #include "../../include/javascript/JS_EventHandler.h"
14 #include "../../include/javascript/JS_Context.h"
15 #include "../../include/javascript/JS_Runtime.h"
16 #include "../../include/javascript/app.h"
17 #include "../../include/javascript/Field.h"
18 #include "../../include/javascript/Icon.h"
19 #include "../../include/javascript/resource.h"
20
21 #include "../../../third_party/base/numerics/safe_math.h"
22
23 static v8::Isolate* GetIsolate(IFXJS_Context* cc)
24 {
25         CJS_Context* pContext = (CJS_Context *)cc;
26         ASSERT(pContext != NULL);
27
28         CJS_Runtime* pRuntime = pContext->GetJSRuntime();
29         ASSERT(pRuntime != NULL);
30
31         return pRuntime->GetIsolate();
32 }
33
34 BEGIN_JS_STATIC_CONST(CJS_PrintParamsObj)
35 END_JS_STATIC_CONST()
36
37 BEGIN_JS_STATIC_PROP(CJS_PrintParamsObj)
38 END_JS_STATIC_PROP()
39
40 BEGIN_JS_STATIC_METHOD(CJS_PrintParamsObj)
41 END_JS_STATIC_METHOD()
42
43 IMPLEMENT_JS_CLASS(CJS_PrintParamsObj, PrintParamsObj)
44
45 PrintParamsObj::PrintParamsObj(CJS_Object* pJSObject)
46 : CJS_EmbedObj(pJSObject)
47 {
48         bUI = TRUE;
49         nStart = 0;
50         nEnd = 0;
51         bSilent = FALSE;
52         bShrinkToFit = FALSE;
53         bPrintAsImage = FALSE;
54         bReverse = FALSE;
55         bAnnotations = TRUE;
56 }
57
58 /* ---------------------- Document ---------------------- */
59
60 #define MINWIDTH  5.0f
61 #define MINHEIGHT 5.0f
62
63 BEGIN_JS_STATIC_CONST(CJS_Document)
64 END_JS_STATIC_CONST()
65
66 BEGIN_JS_STATIC_PROP(CJS_Document)
67         JS_STATIC_PROP_ENTRY(ADBE)
68         JS_STATIC_PROP_ENTRY(author)
69         JS_STATIC_PROP_ENTRY(baseURL)
70         JS_STATIC_PROP_ENTRY(bookmarkRoot)
71         JS_STATIC_PROP_ENTRY(calculate)
72         JS_STATIC_PROP_ENTRY(Collab)
73         JS_STATIC_PROP_ENTRY(creationDate)
74         JS_STATIC_PROP_ENTRY(creator)
75         JS_STATIC_PROP_ENTRY(delay)
76         JS_STATIC_PROP_ENTRY(dirty)
77         JS_STATIC_PROP_ENTRY(documentFileName)
78         JS_STATIC_PROP_ENTRY(external)
79         JS_STATIC_PROP_ENTRY(filesize)
80         JS_STATIC_PROP_ENTRY(icons)
81         JS_STATIC_PROP_ENTRY(info)
82         JS_STATIC_PROP_ENTRY(keywords)
83         JS_STATIC_PROP_ENTRY(layout)
84         JS_STATIC_PROP_ENTRY(media)
85         JS_STATIC_PROP_ENTRY(modDate)
86         JS_STATIC_PROP_ENTRY(mouseX)
87         JS_STATIC_PROP_ENTRY(mouseY)
88         JS_STATIC_PROP_ENTRY(numFields)
89         JS_STATIC_PROP_ENTRY(numPages)
90         JS_STATIC_PROP_ENTRY(pageNum)
91         JS_STATIC_PROP_ENTRY(pageWindowRect)
92         JS_STATIC_PROP_ENTRY(path)
93         JS_STATIC_PROP_ENTRY(producer)
94         JS_STATIC_PROP_ENTRY(subject)
95         JS_STATIC_PROP_ENTRY(title)
96         JS_STATIC_PROP_ENTRY(zoom)
97         JS_STATIC_PROP_ENTRY(zoomType)
98 END_JS_STATIC_PROP()
99
100 BEGIN_JS_STATIC_METHOD(CJS_Document)
101         JS_STATIC_METHOD_ENTRY(addAnnot,0)
102         JS_STATIC_METHOD_ENTRY(addField, 4)
103         JS_STATIC_METHOD_ENTRY(addLink, 0)
104         JS_STATIC_METHOD_ENTRY(addIcon, 0)
105         JS_STATIC_METHOD_ENTRY(calculateNow, 0)
106         JS_STATIC_METHOD_ENTRY(closeDoc, 0)
107         JS_STATIC_METHOD_ENTRY(createDataObject, 0)
108         JS_STATIC_METHOD_ENTRY(deletePages, 2)
109         JS_STATIC_METHOD_ENTRY(exportAsText, 3)
110         JS_STATIC_METHOD_ENTRY(exportAsFDF, 6)
111         JS_STATIC_METHOD_ENTRY(exportAsXFDF, 5)
112         JS_STATIC_METHOD_ENTRY(extractPages, 3)
113         JS_STATIC_METHOD_ENTRY(getAnnot, 0)
114         JS_STATIC_METHOD_ENTRY(getAnnots, 2)
115         JS_STATIC_METHOD_ENTRY(getAnnot3D, 2)
116         JS_STATIC_METHOD_ENTRY(getAnnots3D, 1)
117         JS_STATIC_METHOD_ENTRY(getField, 1)
118         JS_STATIC_METHOD_ENTRY(getIcon, 0)
119         JS_STATIC_METHOD_ENTRY(getLinks, 0)
120         JS_STATIC_METHOD_ENTRY(getNthFieldName, 1)
121         JS_STATIC_METHOD_ENTRY(getOCGs, 0)
122         JS_STATIC_METHOD_ENTRY(getPageBox, 0)
123         JS_STATIC_METHOD_ENTRY(getPageNthWord, 3)
124         JS_STATIC_METHOD_ENTRY(getPageNthWordQuads, 2)
125         JS_STATIC_METHOD_ENTRY(getPageNumWords, 1)
126         JS_STATIC_METHOD_ENTRY(getPrintParams, 0)
127         JS_STATIC_METHOD_ENTRY(getURL, 2)
128         JS_STATIC_METHOD_ENTRY(importAnFDF, 1)
129         JS_STATIC_METHOD_ENTRY(importAnXFDF, 1)
130         JS_STATIC_METHOD_ENTRY(importTextData, 2)
131         JS_STATIC_METHOD_ENTRY(insertPages, 4)
132         JS_STATIC_METHOD_ENTRY(mailForm, 6)
133         JS_STATIC_METHOD_ENTRY(print, 9)
134         JS_STATIC_METHOD_ENTRY(removeField, 1)
135         JS_STATIC_METHOD_ENTRY(replacePages, 4)
136         JS_STATIC_METHOD_ENTRY(resetForm, 1)
137         JS_STATIC_METHOD_ENTRY(removeIcon, 0)
138         JS_STATIC_METHOD_ENTRY(saveAs, 5)
139         JS_STATIC_METHOD_ENTRY(submitForm, 23)
140         JS_STATIC_METHOD_ENTRY(mailDoc, 0)
141 END_JS_STATIC_METHOD()
142
143 IMPLEMENT_JS_CLASS(CJS_Document, Document)
144
145 FX_BOOL CJS_Document::InitInstance(IFXJS_Context* cc)
146 {
147         CJS_Context* pContext = (CJS_Context*)cc;
148         ASSERT(pContext != NULL);
149
150         Document* pDoc = (Document*)GetEmbedObject();
151         ASSERT(pDoc != NULL);
152
153         pDoc->AttachDoc(pContext->GetReaderDocument());
154         pDoc->SetIsolate(pContext->GetJSRuntime()->GetIsolate());
155         return TRUE;
156 };
157
158 /* --------------------------------- Document --------------------------------- */
159
160 Document::Document(CJS_Object* pJSObject) : CJS_EmbedObj(pJSObject),
161         m_isolate(NULL),
162         m_pIconTree(NULL),
163         m_pDocument(NULL),
164         m_cwBaseURL(L""),
165         m_bDelay(FALSE)
166 {
167 }
168
169 Document::~Document()
170 {
171         if (m_pIconTree)
172         {
173                 m_pIconTree->DeleteIconTree();
174                 delete m_pIconTree;
175                 m_pIconTree = NULL;
176         }
177         for (int i=0; i<m_DelayData.GetSize(); i++)
178         {
179                 if (CJS_DelayData* pData = m_DelayData.GetAt(i))
180                 {
181                         delete pData;
182                         pData = NULL;
183                         m_DelayData.SetAt(i, NULL);
184
185                 }
186         }
187
188         m_DelayData.RemoveAll();
189         m_DelayAnnotData.RemoveAll();
190 }
191
192 //the total number of fileds in document.
193 FX_BOOL Document::numFields(IFXJS_Context* cc, CJS_PropValue& vp, CFX_WideString& sError)
194 {
195         if (vp.IsSetting()) {
196                 CJS_Context* pContext = static_cast<CJS_Context*>(cc);
197                 sError = JSGetStringFromID(pContext, IDS_STRING_JSREADONLY);
198                 return FALSE;
199         }
200         CPDFSDK_InterForm *pInterForm = m_pDocument->GetInterForm();
201         CPDF_InterForm *pPDFForm = pInterForm->GetInterForm();
202         vp << (int)pPDFForm->CountFields();
203         return TRUE;
204 }
205
206 FX_BOOL Document::dirty(IFXJS_Context* cc, CJS_PropValue& vp, CFX_WideString& sError)
207 {
208         ASSERT(m_pDocument != NULL);
209
210         if (vp.IsGetting())
211         {
212                 if (m_pDocument->GetChangeMark())
213                         vp << true;
214                 else
215                         vp << false;
216         }
217         else
218         {
219                 bool bChanged = false;
220
221                 vp >> bChanged;
222
223                 if (bChanged)
224                         m_pDocument->SetChangeMark();
225                 else
226                         m_pDocument->ClearChangeMark();
227         }
228
229         return TRUE;
230 }
231
232 FX_BOOL Document::ADBE(IFXJS_Context* cc, CJS_PropValue& vp, CFX_WideString& sError)
233 {
234         ASSERT(m_pDocument != NULL);
235
236         if (vp.IsGetting())
237         {
238                 vp.SetNull();
239         }
240         else
241         {
242         }
243
244         return TRUE;
245 }
246
247 FX_BOOL Document::pageNum(IFXJS_Context* cc, CJS_PropValue& vp, CFX_WideString& sError)
248 {
249         ASSERT(m_pDocument != NULL);
250
251         if (vp.IsGetting())
252         {
253                 if (CPDFSDK_PageView* pPageView = m_pDocument->GetCurrentView())
254                 {
255                         vp << pPageView->GetPageIndex();
256                 }
257         }
258         else
259         {
260                 int iPageCount = m_pDocument->GetPageCount();
261                 int iPageNum = 0;
262                 vp >> iPageNum;
263
264                 CPDFDoc_Environment* pEnv = m_pDocument->GetEnv();
265                 if (iPageNum >= 0 && iPageNum < iPageCount)
266                 {
267                          pEnv->JS_docgotoPage(iPageNum);
268                 }
269                 else if (iPageNum >= iPageCount)
270                 {
271                          pEnv->JS_docgotoPage(iPageCount-1);
272                 }
273                 else if (iPageNum < 0)
274                 {
275                          pEnv->JS_docgotoPage(0);
276                 }
277         }
278
279         return TRUE;
280 }
281
282 FX_BOOL Document::ParserParams(JSObject* pObj,CJS_AnnotObj& annotobj)
283 {
284         // Not supported.
285         return TRUE;
286 }
287
288 FX_BOOL Document::addAnnot(IFXJS_Context* cc, const CJS_Parameters& params, CJS_Value& vRet, CFX_WideString& sError)
289 {
290         // Not supported.
291         return TRUE;
292 }
293
294 FX_BOOL Document::addField(IFXJS_Context* cc, const CJS_Parameters& params, CJS_Value& vRet, CFX_WideString& sError)
295 {
296         // Not supported.
297         return TRUE;
298 }
299
300 FX_BOOL Document::exportAsText(IFXJS_Context* cc, const CJS_Parameters& params, CJS_Value& vRet, CFX_WideString& sError)
301 {
302         // Unsafe, not supported.
303         return TRUE;
304 }
305
306 FX_BOOL Document::exportAsFDF(IFXJS_Context* cc, const CJS_Parameters& params, CJS_Value& vRet, CFX_WideString& sError)
307 {
308         // Unsafe, not supported.
309         return TRUE;
310 }
311
312 FX_BOOL Document::exportAsXFDF(IFXJS_Context* cc, const CJS_Parameters& params, CJS_Value& vRet, CFX_WideString& sError)
313 {
314         // Unsafe, not supported.
315         return TRUE;
316 }
317
318 //Maps a field object in PDF document to a JavaScript variable
319 //comment:
320 //note: the paremter cName, this is clue how to treat if the cName is not a valiable filed name in this document
321
322 FX_BOOL Document::getField(IFXJS_Context* cc, const CJS_Parameters& params, CJS_Value& vRet, CFX_WideString& sError)
323 {
324         v8::Isolate* isolate = GetIsolate(cc);
325         ASSERT(m_pDocument != NULL);
326
327         if (params.size() < 1) return FALSE;
328
329         CFX_WideString wideName = params[0].ToCFXWideString();
330
331         CPDFSDK_InterForm* pInterForm = m_pDocument->GetInterForm();
332         ASSERT(pInterForm != NULL);
333
334         CPDF_InterForm* pPDFForm = pInterForm->GetInterForm();
335         ASSERT(pPDFForm != NULL);
336
337         if (pPDFForm->CountFields(wideName) <= 0)
338         {
339                 vRet.SetNull();
340                 return TRUE;
341         }
342
343         CJS_Context* pContext = (CJS_Context*)cc;
344         ASSERT(pContext != NULL);
345         CJS_Runtime* pRuntime = pContext->GetJSRuntime();
346         ASSERT(pRuntime != NULL);
347
348         JSFXObject  pFieldObj = JS_NewFxDynamicObj(*pRuntime, pContext, JS_GetObjDefnID(*pRuntime, L"Field"));
349
350         CJS_Field * pJSField = (CJS_Field*)JS_GetPrivate(isolate,pFieldObj);
351         ASSERT(pJSField != NULL);
352
353         Field * pField = (Field *)pJSField->GetEmbedObject();
354         ASSERT(pField != NULL);
355
356         pField->AttachField(this, wideName);
357         vRet = pJSField;
358
359         return TRUE;
360 }
361
362 //Gets the name of the nth field in the document
363 FX_BOOL Document::getNthFieldName(IFXJS_Context* cc, const CJS_Parameters& params, CJS_Value& vRet, CFX_WideString& sError)
364 {
365         ASSERT(m_pDocument != NULL);
366
367         int nIndex = params.size() > 0 ? params[0].ToInt() : -1;
368         if (nIndex == -1) return FALSE;
369
370         CPDFSDK_InterForm* pInterForm = m_pDocument->GetInterForm();
371         ASSERT(pInterForm != NULL);
372
373         CPDF_InterForm* pPDFForm = pInterForm->GetInterForm();
374         ASSERT(pPDFForm != NULL);
375
376         CPDF_FormField* pField = pPDFForm->GetField(nIndex);
377         if (!pField)
378                 return FALSE;
379
380         vRet = pField->GetFullName();
381         return TRUE;
382 }
383
384 FX_BOOL Document::importAnFDF(IFXJS_Context* cc, const CJS_Parameters& params, CJS_Value& vRet, CFX_WideString& sError)
385 {
386         // Unsafe, not supported.
387         return TRUE;
388 }
389
390 FX_BOOL Document::importAnXFDF(IFXJS_Context* cc, const CJS_Parameters& params, CJS_Value& vRet, CFX_WideString& sError)
391 {
392         // Unsafe, not supported.
393         return TRUE;
394 }
395
396 FX_BOOL Document::importTextData(IFXJS_Context* cc, const CJS_Parameters& params, CJS_Value& vRet, CFX_WideString& sError)
397 {
398         // Unsafe, not supported.
399         return TRUE;
400 }
401
402 //exports the form data and mails the resulting fdf file as an attachment to all recipients.
403 //comment: need reader supports
404 //note:
405 //int CPDFSDK_Document::mailForm(FX_BOOL bUI,String cto,string ccc,string cbcc,string cSubject,string cms);
406
407 FX_BOOL Document::mailForm(IFXJS_Context* cc, const CJS_Parameters& params, CJS_Value& vRet, CFX_WideString& sError)
408 {
409         ASSERT(m_pDocument != NULL);
410
411         if (!m_pDocument->GetPermissions(FPDFPERM_EXTRACT_ACCESS)) return FALSE;
412
413         int iLength = params.size();
414
415         FX_BOOL bUI = iLength > 0 ? params[0].ToBool() : TRUE;
416         CFX_WideString cTo = iLength > 1 ? params[1].ToCFXWideString() : L"";
417         CFX_WideString cCc = iLength > 2 ? params[2].ToCFXWideString() : L"";
418         CFX_WideString cBcc = iLength > 3 ? params[3].ToCFXWideString() : L"";
419         CFX_WideString cSubject = iLength > 4 ? params[4].ToCFXWideString() : L"";
420         CFX_WideString cMsg = iLength > 5 ? params[5].ToCFXWideString() : L"";
421
422         CPDFSDK_InterForm* pInterForm = (CPDFSDK_InterForm*)m_pDocument->GetInterForm();
423         ASSERT(pInterForm != NULL);
424
425         CFX_ByteTextBuf textBuf;
426         if (!pInterForm->ExportFormToFDFTextBuf(textBuf))
427                 return FALSE;
428
429         CJS_Context* pContext = (CJS_Context*)cc;
430         ASSERT(pContext != NULL);
431         CPDFDoc_Environment* pEnv = pContext->GetReaderApp();
432         ASSERT(pEnv != NULL);
433         CJS_Runtime* pRuntime = pContext->GetJSRuntime();
434         ASSERT(pRuntime != NULL);
435
436         pRuntime->BeginBlock();
437         pEnv->JS_docmailForm(textBuf.GetBuffer(), textBuf.GetLength(), bUI, cTo.c_str(), cSubject.c_str(), cCc.c_str(), cBcc.c_str(), cMsg.c_str());
438         pRuntime->EndBlock();
439         return TRUE;
440 }
441
442 FX_BOOL Document::print(IFXJS_Context* cc, const CJS_Parameters& params, CJS_Value& vRet, CFX_WideString& sError)
443 {
444         CJS_Context* pContext = (CJS_Context*)cc;
445         ASSERT(pContext != NULL);
446         CJS_Runtime* pRuntime = pContext->GetJSRuntime();
447         ASSERT(pRuntime != NULL);
448
449         FX_BOOL bUI = TRUE;
450         int nStart = 0;
451         int nEnd = 0;
452         FX_BOOL bSilent = FALSE;
453         FX_BOOL bShrinkToFit = FALSE;
454         FX_BOOL bPrintAsImage = FALSE;
455         FX_BOOL bReverse = FALSE;
456         FX_BOOL bAnnotations = FALSE;
457
458         int nlength = params.size();
459         if(nlength ==9)
460         {
461                 if (params[8].GetType() == VT_fxobject)
462                 {
463                         JSFXObject pObj = params[8].ToV8Object();
464                         {
465                                 if (JS_GetObjDefnID(pObj) == JS_GetObjDefnID(*pRuntime, L"PrintParamsObj"))
466                                 {
467                                         if (CJS_Object* pJSObj = params[8].ToCJSObject())
468                                         {
469                                                         if (PrintParamsObj* pprintparamsObj = (PrintParamsObj*)pJSObj->GetEmbedObject())
470                                                         {
471                                                                 bUI = pprintparamsObj->bUI;
472                                                                 nStart = pprintparamsObj->nStart;
473                                                                 nEnd = pprintparamsObj->nEnd;
474                                                                 bSilent = pprintparamsObj->bSilent;
475                                                                 bShrinkToFit = pprintparamsObj->bShrinkToFit;
476                                                                 bPrintAsImage = pprintparamsObj->bPrintAsImage;
477                                                                 bReverse = pprintparamsObj->bReverse;
478                                                                 bAnnotations = pprintparamsObj->bAnnotations;
479                                                         }
480                                         }
481                                 }
482                         }
483                 }
484         }
485         else
486         {
487                 if(nlength >= 1)
488                         bUI = params[0].ToBool();
489                 if(nlength >= 2)
490                         nStart = params[1].ToInt();
491                 if(nlength >= 3)
492                         nEnd = params[2].ToInt();
493                 if(nlength >= 4)
494                         bSilent = params[3].ToBool();
495                 if(nlength >= 5)
496                         bShrinkToFit = params[4].ToBool();
497                 if(nlength >= 6)
498                         bPrintAsImage = params[5].ToBool();
499                 if(nlength >= 7)
500                         bReverse = params[6].ToBool();
501                 if(nlength >= 8)
502                         bAnnotations = params[7].ToBool();
503         }
504
505         ASSERT(m_pDocument != NULL);
506
507         if (CPDFDoc_Environment* pEnv = m_pDocument->GetEnv())
508         {
509                 pEnv->JS_docprint(bUI, nStart, nEnd, bSilent, bShrinkToFit, bPrintAsImage, bReverse, bAnnotations);
510                 return TRUE;
511         }
512         return FALSE;
513 }
514
515 //removes the specified field from the document.
516 //comment:
517 //note: if the filed name is not retional, adobe is dumb for it.
518
519 FX_BOOL Document::removeField(IFXJS_Context* cc, const CJS_Parameters& params, CJS_Value& vRet, CFX_WideString& sError)
520 {
521         ASSERT(m_pDocument != NULL);
522
523         if (!(m_pDocument->GetPermissions(FPDFPERM_MODIFY) ||
524                 m_pDocument->GetPermissions(FPDFPERM_ANNOT_FORM))) return FALSE;
525
526         if (params.size() < 1)
527                 return TRUE;
528
529         CFX_WideString sFieldName = params[0].ToCFXWideString();
530
531         CPDFSDK_InterForm* pInterForm = (CPDFSDK_InterForm*)m_pDocument->GetInterForm();
532         ASSERT(pInterForm != NULL);
533
534         CFX_PtrArray widgets;
535         pInterForm->GetWidgets(sFieldName, widgets);
536
537         int nSize = widgets.GetSize();
538
539         if (nSize > 0)
540         {
541                 for (int i=0; i<nSize; i++)
542                 {
543                         CPDFSDK_Widget* pWidget = (CPDFSDK_Widget*)widgets[i];
544                         ASSERT(pWidget != NULL);
545
546                         CPDF_Rect rcAnnot = pWidget->GetRect();
547                         rcAnnot.left -= 1;
548                         rcAnnot.bottom -= 1;
549                         rcAnnot.right += 1;
550                         rcAnnot.top += 1;
551
552                         CFX_RectArray aRefresh;
553                         aRefresh.Add(rcAnnot);
554
555                         CPDFXFA_Page* pPage = pWidget->GetPDFXFAPage();
556                         ASSERT(pPage != NULL);
557
558                         CPDFSDK_PageView* pPageView = m_pDocument->GetPageView(pPage);
559                         pPageView->DeleteAnnot(pWidget);
560
561                         pPageView->UpdateRects(aRefresh);
562                 }
563                 m_pDocument->SetChangeMark();
564         }
565
566         return TRUE;
567 }
568
569 //reset filed values within a document.
570 //comment:
571 //note: if the fields names r not rational, aodbe is dumb for it.
572
573 FX_BOOL Document::resetForm(IFXJS_Context* cc, const CJS_Parameters& params, CJS_Value& vRet, CFX_WideString& sError)
574 {
575         ASSERT(m_pDocument != NULL);
576
577         if (!(m_pDocument->GetPermissions(FPDFPERM_MODIFY) ||
578                 m_pDocument->GetPermissions(FPDFPERM_ANNOT_FORM) ||
579                 m_pDocument->GetPermissions(FPDFPERM_FILL_FORM))) return FALSE;
580
581         CPDFSDK_InterForm* pInterForm = (CPDFSDK_InterForm*)m_pDocument->GetInterForm();
582         ASSERT(pInterForm != NULL);
583
584         CPDF_InterForm* pPDFForm = pInterForm->GetInterForm();
585         ASSERT(pPDFForm != NULL);
586
587         v8::Isolate* isolate = GetIsolate(cc);
588         CJS_Array aName(isolate);
589
590         if (params.size() > 0)
591         {
592                 switch (params[0].GetType())
593                 {
594                 default:
595                         aName.Attach(params[0].ToV8Array());
596                         break;
597                 case VT_string:
598                         aName.SetElement(0,params[0]);
599                         break;
600                 }
601
602                 CFX_PtrArray aFields;
603
604                 for (int i=0,isz=aName.GetLength(); i<isz; i++)
605                 {
606                         CJS_Value valElement(isolate);
607                         aName.GetElement(i,valElement);
608                         CFX_WideString swVal = valElement.ToCFXWideString();
609
610                         for (int j=0,jsz=pPDFForm->CountFields(swVal); j<jsz; j++)
611                         {
612                                 aFields.Add((void*)pPDFForm->GetField(j,swVal));
613                         }
614                 }
615
616                 if (aFields.GetSize() > 0)
617                 {
618                         pPDFForm->ResetForm(aFields, TRUE, TRUE);
619                         m_pDocument->SetChangeMark();
620
621                 }
622         }
623         else
624         {
625                 pPDFForm->ResetForm(TRUE);
626                 m_pDocument->SetChangeMark();
627
628         }
629
630         return TRUE;
631 }
632
633
634 FX_BOOL Document::saveAs(IFXJS_Context* cc, const CJS_Parameters& params, CJS_Value& vRet, CFX_WideString& sError)
635 {
636   // Unsafe, not supported.
637   return TRUE;
638 }
639
640
641 FX_BOOL Document::submitForm(IFXJS_Context* cc, const CJS_Parameters& params, CJS_Value& vRet, CFX_WideString& sError)
642 {
643         ASSERT(m_pDocument != NULL);
644
645 //      if (!m_pDocument->GetPermissions(FPDFPERM_EXTRACT_ACCESS)) return FALSE;
646
647         int nSize = params.size();
648         if (nSize < 1) return FALSE;
649
650         CFX_WideString strURL;
651         FX_BOOL bFDF = TRUE;
652         FX_BOOL bEmpty = FALSE;
653         v8::Isolate* isolate = GetIsolate(cc);
654         CJS_Array aFields(isolate);
655
656         CJS_Value v = params[0];
657         if (v.GetType() == VT_string)
658         {
659                 strURL = params[0].ToCFXWideString();
660                 if (nSize > 1)
661                         bFDF = params[1].ToBool();
662                 if (nSize > 2)
663                         bEmpty = params[2].ToBool();
664                 if (nSize > 3)
665                         aFields.Attach(params[3].ToV8Array());
666         }
667         else if (v.GetType() == VT_object)
668         {
669                 JSObject pObj = params[0].ToV8Object();
670                 v8::Handle<v8::Value> pValue = JS_GetObjectElement(isolate, pObj, L"cURL");
671                 if (!pValue.IsEmpty())
672                         strURL = CJS_Value(isolate, pValue, GET_VALUE_TYPE(pValue)).ToCFXWideString();
673                 pValue = JS_GetObjectElement(isolate, pObj, L"bFDF");
674                 bFDF = CJS_Value(isolate, pValue, GET_VALUE_TYPE(pValue)).ToBool();
675                 pValue = JS_GetObjectElement(isolate, pObj, L"bEmpty");
676                 bEmpty = CJS_Value(isolate, pValue, GET_VALUE_TYPE(pValue)).ToBool();
677                 pValue = JS_GetObjectElement(isolate, pObj,L"aFields");
678                 aFields.Attach(CJS_Value(isolate, pValue, GET_VALUE_TYPE(pValue)).ToV8Array());
679         }
680
681         CPDFSDK_InterForm* pInterForm = (CPDFSDK_InterForm*)m_pDocument->GetInterForm();
682         ASSERT(pInterForm != NULL);
683         CPDF_InterForm* pPDFInterForm = pInterForm->GetInterForm();
684         ASSERT(pPDFInterForm != NULL);
685
686         FX_BOOL bAll = (aFields.GetLength() == 0);
687
688         if (bAll && bEmpty)
689         {
690                 CJS_Context* pContext = (CJS_Context*)cc;
691                 ASSERT(pContext != NULL);
692                 CJS_Runtime* pRuntime = pContext->GetJSRuntime();
693                 ASSERT(pRuntime != NULL);
694
695
696                 if (pPDFInterForm->CheckRequiredFields())
697                 {
698                         pRuntime->BeginBlock();
699                         pInterForm->SubmitForm(strURL, FALSE);
700                         pRuntime->EndBlock();
701                 }
702
703                 return TRUE;
704         }
705         else
706         {
707                 CFX_PtrArray fieldObjects;
708
709                 for (int i=0,sz=aFields.GetLength(); i<sz; i++)
710                 {
711                         CJS_Value valName(isolate);
712                         aFields.GetElement(i, valName);
713                         CFX_WideString sName = valName.ToCFXWideString();
714
715                         CPDF_InterForm* pPDFForm = pInterForm->GetInterForm();
716                         ASSERT(pPDFForm != NULL);
717
718                         for (int j=0, jsz=pPDFForm->CountFields(sName); j<jsz; j++)
719                         {
720                                 CPDF_FormField* pField = pPDFForm->GetField(j, sName);
721                                 if (!bEmpty && pField->GetValue().IsEmpty())
722                                         continue;
723
724                                 fieldObjects.Add(pField);
725                         }
726                 }
727
728                 CJS_Context* pContext = (CJS_Context*)cc;
729                 ASSERT(pContext != NULL);
730                 CJS_Runtime* pRuntime = pContext->GetJSRuntime();
731                 ASSERT(pRuntime != NULL);
732
733
734                 if (pPDFInterForm->CheckRequiredFields(&fieldObjects, TRUE))
735                 {
736                         pRuntime->BeginBlock();
737                         pInterForm->SubmitFields(strURL, fieldObjects, TRUE, !bFDF);
738                         pRuntime->EndBlock();
739                 }
740
741                 return TRUE;
742         }
743
744 }
745
746 //////////////////////////////////////////////////////////////////////////////////////////////
747
748 void Document::AttachDoc(CPDFSDK_Document *pDoc)
749 {
750         m_pDocument = pDoc;
751 }
752
753 CPDFSDK_Document * Document::GetReaderDoc()
754 {
755         return m_pDocument;
756 }
757
758 FX_BOOL Document::ExtractFileName(CPDFSDK_Document *pDoc,CFX_ByteString &strFileName)
759 {
760         return FALSE;
761 }
762
763 FX_BOOL Document::ExtractFolderName(CPDFSDK_Document *pDoc,CFX_ByteString &strFolderName)
764 {
765         return FALSE;
766 }
767
768 FX_BOOL Document::bookmarkRoot(IFXJS_Context* cc, CJS_PropValue& vp, CFX_WideString& sError)
769 {
770         return TRUE;
771 }
772
773 FX_BOOL Document::mailDoc(IFXJS_Context* cc, const CJS_Parameters& params, CJS_Value& vRet, CFX_WideString& sError)
774 {
775         ASSERT(m_pDocument != NULL);
776
777         FX_BOOL bUI = TRUE;
778         CFX_WideString cTo = L"";
779         CFX_WideString cCc = L"";
780         CFX_WideString cBcc = L"";
781         CFX_WideString cSubject = L"";
782         CFX_WideString cMsg = L"";
783
784         if (params.size() >= 1)
785                 bUI = params[0].ToBool();
786         if (params.size() >= 2)
787                 cTo = params[1].ToCFXWideString();
788         if (params.size() >= 3)
789                 cCc = params[2].ToCFXWideString();
790         if (params.size() >= 4)
791                 cBcc = params[3].ToCFXWideString();
792         if (params.size() >= 5)
793                 cSubject = params[4].ToCFXWideString();
794         if (params.size() >= 6)
795                 cMsg = params[5].ToCFXWideString();
796
797         v8::Isolate* isolate = GetIsolate(cc);
798
799         if(params.size() >= 1 && params[0].GetType() == VT_object)
800         {
801                 JSObject pObj = params[0].ToV8Object();
802
803                 v8::Handle<v8::Value> pValue = JS_GetObjectElement(isolate,pObj, L"bUI");
804                 bUI = CJS_Value(isolate,pValue,GET_VALUE_TYPE(pValue)).ToInt();
805
806                 pValue = JS_GetObjectElement(isolate,pObj, L"cTo");
807                 cTo = CJS_Value(isolate,pValue,GET_VALUE_TYPE(pValue)).ToCFXWideString();
808
809                 pValue = JS_GetObjectElement(isolate,pObj, L"cCc");
810                 cCc = CJS_Value(isolate,pValue,GET_VALUE_TYPE(pValue)).ToCFXWideString();
811
812                 pValue = JS_GetObjectElement(isolate,pObj, L"cBcc");
813                 cBcc = CJS_Value(isolate,pValue,GET_VALUE_TYPE(pValue)).ToCFXWideString();
814
815                 pValue = JS_GetObjectElement(isolate,pObj, L"cSubject");
816                 cSubject = CJS_Value(isolate,pValue,GET_VALUE_TYPE(pValue)).ToCFXWideString();
817
818                 pValue = JS_GetObjectElement(isolate,pObj, L"cMsg");
819                 cMsg = CJS_Value(isolate,pValue,GET_VALUE_TYPE(pValue)).ToCFXWideString();
820
821         }
822
823         CJS_Context* pContext = (CJS_Context*)cc;
824         ASSERT(pContext != NULL);
825         CJS_Runtime* pRuntime = pContext->GetJSRuntime();
826         ASSERT(pRuntime != NULL);
827
828         pRuntime->BeginBlock();
829         CPDFDoc_Environment* pEnv = pRuntime->GetReaderApp();
830         pEnv->JS_docmailForm(NULL, 0, bUI, cTo.c_str(), cSubject.c_str(), cCc.c_str(), cBcc.c_str(), cMsg.c_str());
831         pRuntime->EndBlock();
832
833         return TRUE;
834 }
835
836 FX_BOOL Document::author(IFXJS_Context* cc, CJS_PropValue& vp, CFX_WideString& sError)
837 {
838         ASSERT(m_pDocument != NULL);
839
840         CPDF_Dictionary* pDictionary = m_pDocument->GetDocument()->GetPDFDoc()->GetInfo();
841         if (!pDictionary)return FALSE;
842
843         if (vp.IsGetting())
844         {
845                 vp << pDictionary->GetUnicodeText("Author");
846                 return TRUE;
847         }
848         else
849         {
850                 if (!m_pDocument->GetPermissions(FPDFPERM_MODIFY)) return FALSE;
851
852                 CFX_WideString csAuthor;
853                 vp >> csAuthor;
854                 pDictionary->SetAtString("Author", PDF_EncodeText(csAuthor));
855                 m_pDocument->SetChangeMark();
856                 return TRUE;
857         }
858 }
859
860 FX_BOOL Document::info(IFXJS_Context* cc, CJS_PropValue& vp, CFX_WideString& sError)
861 {
862         ASSERT(m_pDocument != NULL);
863
864         CPDF_Dictionary* pDictionary = m_pDocument->GetDocument()->GetPDFDoc()->GetInfo();
865         if (!pDictionary)return FALSE;
866
867         CFX_WideString cwAuthor                 = pDictionary->GetUnicodeText("Author");
868         CFX_WideString cwTitle                  = pDictionary->GetUnicodeText("Title");
869         CFX_WideString cwSubject                = pDictionary->GetUnicodeText("Subject");
870         CFX_WideString cwKeywords               = pDictionary->GetUnicodeText("Keywords");
871         CFX_WideString cwCreator                = pDictionary->GetUnicodeText("Creator");
872         CFX_WideString cwProducer               = pDictionary->GetUnicodeText("Producer");
873         CFX_WideString cwCreationDate   = pDictionary->GetUnicodeText("CreationDate");
874         CFX_WideString cwModDate                = pDictionary->GetUnicodeText("ModDate");
875         CFX_WideString cwTrapped                = pDictionary->GetUnicodeText("Trapped");
876
877         v8::Isolate* isolate = GetIsolate(cc);
878         if (vp.IsGetting())
879         {
880                 CJS_Context* pContext = (CJS_Context *)cc;
881                 CJS_Runtime* pRuntime = pContext->GetJSRuntime();
882
883                 JSFXObject  pObj = JS_NewFxDynamicObj(*pRuntime, pContext, -1);
884
885                 JS_PutObjectString(isolate,pObj, L"Author", cwAuthor);
886                 JS_PutObjectString(isolate,pObj, L"Title", cwTitle);
887                 JS_PutObjectString(isolate,pObj, L"Subject", cwSubject);
888                 JS_PutObjectString(isolate,pObj, L"Keywords", cwKeywords);
889                 JS_PutObjectString(isolate,pObj, L"Creator", cwCreator);
890                 JS_PutObjectString(isolate,pObj, L"Producer", cwProducer);
891                 JS_PutObjectString(isolate,pObj, L"CreationDate", cwCreationDate);
892                 JS_PutObjectString(isolate,pObj, L"ModDate", cwModDate);
893                 JS_PutObjectString(isolate,pObj, L"Trapped", cwTrapped);
894
895 // It's to be compatible to non-standard info dictionary.
896                 FX_POSITION pos = pDictionary->GetStartPos();
897                 while(pos)
898                 {
899                         CFX_ByteString bsKey;
900                         CPDF_Object* pValueObj = pDictionary->GetNextElement(pos, bsKey);
901                         CFX_WideString wsKey  = CFX_WideString::FromUTF8(bsKey, bsKey.GetLength());
902                         if((pValueObj->GetType()==PDFOBJ_STRING) || (pValueObj->GetType()==PDFOBJ_NAME) )
903                                         JS_PutObjectString(isolate,pObj, wsKey, pValueObj->GetUnicodeText());
904                         if(pValueObj->GetType()==PDFOBJ_NUMBER)
905                                 JS_PutObjectNumber(isolate,pObj, wsKey, (float)pValueObj->GetNumber());
906                         if(pValueObj->GetType()==PDFOBJ_BOOLEAN)
907                                 JS_PutObjectBoolean(isolate,pObj, wsKey, (bool)pValueObj->GetInteger());
908                 }
909
910                 vp << pObj;
911                 return TRUE;
912         }
913         else
914         {
915                 return TRUE;
916         }
917 }
918
919 FX_BOOL Document::creationDate(IFXJS_Context* cc, CJS_PropValue& vp, CFX_WideString& sError)
920 {
921         ASSERT(m_pDocument != NULL);
922
923         CPDF_Dictionary* pDictionary = m_pDocument->GetDocument()->GetPDFDoc()->GetInfo();
924         if (!pDictionary)return FALSE;
925
926         if (vp.IsGetting())
927         {
928                 vp << pDictionary->GetUnicodeText("CreationDate");
929                 return TRUE;
930         }
931         else
932         {
933                 if (!m_pDocument->GetPermissions(FPDFPERM_MODIFY)) return FALSE;
934
935                 CFX_WideString csCreationDate;
936                 vp >> csCreationDate;
937                 pDictionary->SetAtString("CreationDate", PDF_EncodeText(csCreationDate));
938                 m_pDocument->SetChangeMark();
939
940                 return TRUE;
941         }
942 }
943
944 FX_BOOL Document::creator(IFXJS_Context* cc, CJS_PropValue& vp, CFX_WideString& sError)
945 {
946         ASSERT(m_pDocument != NULL);
947
948         CPDF_Dictionary* pDictionary = m_pDocument->GetDocument()->GetPDFDoc()->GetInfo();
949         if (!pDictionary)return FALSE;
950
951         if (vp.IsGetting())
952         {
953                 vp << pDictionary->GetUnicodeText("Creator");
954                 return TRUE;
955         }
956         else
957         {
958                 if (!m_pDocument->GetPermissions(FPDFPERM_MODIFY)) return FALSE;
959
960                 CFX_WideString csCreator;
961                 vp >> csCreator;
962                 pDictionary->SetAtString("Creator", PDF_EncodeText(csCreator));
963                 m_pDocument->SetChangeMark();
964                 return TRUE;
965         }
966 }
967
968 FX_BOOL Document::delay(IFXJS_Context* cc, CJS_PropValue& vp, CFX_WideString& sError)
969 {
970         if (vp.IsGetting())
971         {
972                 vp << m_bDelay;
973                 return TRUE;
974         }
975         else
976         {
977                 ASSERT(m_pDocument != NULL);
978
979                 if (!m_pDocument->GetPermissions(FPDFPERM_MODIFY)) return FALSE;
980
981                 bool b;
982                 vp >> b;
983
984                 m_bDelay = b;
985
986                 if (m_bDelay)
987                 {
988                         for (int i=0,sz=m_DelayData.GetSize(); i<sz; i++)
989                                 delete m_DelayData.GetAt(i);
990
991                         m_DelayData.RemoveAll();
992                 }
993                 else
994                 {
995                         for (int i=0,sz=m_DelayData.GetSize(); i<sz; i++)
996                         {
997                                 if (CJS_DelayData* pData = m_DelayData.GetAt(i))
998                                 {
999                                         Field::DoDelay(m_pDocument, pData);
1000                                         delete m_DelayData.GetAt(i);
1001                                 }
1002                         }
1003                         m_DelayData.RemoveAll();
1004                 }
1005
1006                 return TRUE;
1007         }
1008 }
1009
1010 FX_BOOL Document::keywords(IFXJS_Context* cc, CJS_PropValue& vp, CFX_WideString& sError)
1011 {
1012         ASSERT(m_pDocument != NULL);
1013
1014         CPDF_Dictionary* pDictionary = m_pDocument->GetDocument()->GetPDFDoc()->GetInfo();
1015         if (!pDictionary)return FALSE;
1016
1017         if (vp.IsGetting())
1018         {
1019                 vp << pDictionary->GetUnicodeText("Keywords");
1020                 return TRUE;
1021         }
1022         else
1023         {
1024                 if (!m_pDocument->GetPermissions(FPDFPERM_MODIFY)) return FALSE;
1025
1026                 CFX_WideString csKeywords;
1027                 vp >> csKeywords;
1028                 pDictionary->SetAtString("Keywords", PDF_EncodeText(csKeywords));
1029                 m_pDocument->SetChangeMark();
1030                 return TRUE;
1031         }
1032 }
1033
1034 FX_BOOL Document::modDate(IFXJS_Context* cc, CJS_PropValue& vp, CFX_WideString& sError)
1035 {
1036         ASSERT(m_pDocument != NULL);
1037
1038         CPDF_Dictionary* pDictionary = m_pDocument->GetDocument()->GetPDFDoc()->GetInfo();
1039         if (!pDictionary)return FALSE;
1040
1041         if (vp.IsGetting())
1042         {
1043                 vp << pDictionary->GetUnicodeText("ModDate");
1044                 return TRUE;
1045         }
1046         else
1047         {
1048                 if (!m_pDocument->GetPermissions(FPDFPERM_MODIFY)) return FALSE;
1049
1050                 CFX_WideString csmodDate;
1051                 vp >> csmodDate;
1052                 pDictionary->SetAtString("ModDate", PDF_EncodeText(csmodDate));
1053                 m_pDocument->SetChangeMark();
1054                 return TRUE;
1055         }
1056 }
1057
1058 FX_BOOL Document::producer(IFXJS_Context* cc, CJS_PropValue& vp, CFX_WideString& sError)
1059 {
1060         ASSERT(m_pDocument != NULL);
1061
1062         CPDF_Dictionary* pDictionary = m_pDocument->GetDocument()->GetPDFDoc()->GetInfo();
1063         if (!pDictionary)return FALSE;
1064
1065         if (vp.IsGetting())
1066         {
1067                 vp << pDictionary->GetUnicodeText("Producer");
1068                 return TRUE;
1069         }
1070         else
1071         {
1072                 if (!m_pDocument->GetPermissions(FPDFPERM_MODIFY)) return FALSE;
1073
1074                 CFX_WideString csproducer;
1075                 vp >> csproducer;
1076                 pDictionary->SetAtString("Producer", PDF_EncodeText(csproducer));
1077                 m_pDocument->SetChangeMark();
1078                 return TRUE;
1079         }
1080 }
1081
1082 FX_BOOL Document::subject(IFXJS_Context* cc, CJS_PropValue& vp, CFX_WideString& sError)
1083 {
1084         ASSERT(m_pDocument != NULL);
1085
1086         CPDF_Dictionary* pDictionary = m_pDocument->GetDocument()->GetPDFDoc()->GetInfo();
1087         if (!pDictionary)return FALSE;
1088
1089         if (vp.IsGetting())
1090         {
1091                 vp << pDictionary->GetUnicodeText("Subject");
1092                 return TRUE;
1093         }
1094         else
1095         {
1096                 if (!m_pDocument->GetPermissions(FPDFPERM_MODIFY)) return FALSE;
1097
1098                 CFX_WideString cssubject;
1099                 vp >> cssubject;
1100                 pDictionary->SetAtString("Subject", PDF_EncodeText(cssubject));
1101                 m_pDocument->SetChangeMark();
1102                 return TRUE;
1103         }
1104 }
1105
1106 FX_BOOL Document::title(IFXJS_Context* cc, CJS_PropValue& vp, CFX_WideString& sError)
1107 {
1108         ASSERT(m_pDocument != NULL);
1109
1110         if (m_pDocument == NULL || m_pDocument->GetDocument() == NULL)
1111                 return FALSE;
1112
1113         CPDF_Dictionary* pDictionary = m_pDocument->GetDocument()->GetPDFDoc()->GetInfo();
1114         if (!pDictionary)return FALSE;
1115
1116         if (vp.IsGetting())
1117         {
1118                 vp << pDictionary->GetUnicodeText("Title");
1119                 return TRUE;
1120         }
1121         else
1122         {
1123                 if (!m_pDocument->GetPermissions(FPDFPERM_MODIFY)) return FALSE;
1124
1125                 CFX_WideString cstitle;
1126                 vp >> cstitle;
1127                 pDictionary->SetAtString("Title", PDF_EncodeText(cstitle));
1128                 m_pDocument->SetChangeMark();
1129                 return TRUE;
1130         }
1131 }
1132
1133 FX_BOOL Document::numPages(IFXJS_Context* cc, CJS_PropValue& vp, CFX_WideString& sError)
1134 {
1135         if (vp.IsSetting()) {
1136                 CJS_Context* pContext = static_cast<CJS_Context*>(cc);
1137                 sError = JSGetStringFromID(pContext, IDS_STRING_JSREADONLY);
1138                 return FALSE;
1139         }
1140         vp << m_pDocument->GetPageCount();
1141         return TRUE;
1142 }
1143
1144 FX_BOOL Document::external(IFXJS_Context* cc, CJS_PropValue& vp, CFX_WideString& sError)
1145 {
1146         //In Chrome case,should always return true.
1147         if (vp.IsGetting()) {
1148                 vp << TRUE;
1149         }
1150         return TRUE;
1151 }
1152
1153 FX_BOOL Document::filesize(IFXJS_Context* cc, CJS_PropValue& vp, CFX_WideString& sError)
1154 {
1155         if (vp.IsSetting()) {
1156                 CJS_Context* pContext = static_cast<CJS_Context*>(cc);
1157                 sError = JSGetStringFromID(pContext, IDS_STRING_JSREADONLY);
1158                 return FALSE;
1159         }
1160         vp << 0;
1161         return TRUE;
1162 }
1163
1164 FX_BOOL Document::mouseX(IFXJS_Context* cc, CJS_PropValue& vp, CFX_WideString& sError)
1165 {
1166         return TRUE;
1167 }
1168
1169 FX_BOOL Document::mouseY(IFXJS_Context* cc, CJS_PropValue& vp, CFX_WideString& sError)
1170 {
1171         return TRUE;
1172 }
1173
1174 FX_BOOL Document::baseURL(IFXJS_Context* cc, CJS_PropValue& vp, CFX_WideString& sError)
1175 {
1176         if (vp.IsGetting())
1177         {
1178                 vp << m_cwBaseURL;
1179         }
1180         else
1181         {
1182                 vp >> m_cwBaseURL;
1183         }
1184         return TRUE;
1185 }
1186
1187 FX_BOOL Document::calculate(IFXJS_Context* cc, CJS_PropValue& vp, CFX_WideString& sError)
1188 {
1189         ASSERT(m_pDocument != NULL);
1190
1191         CPDFSDK_InterForm* pInterForm = (CPDFSDK_InterForm*)m_pDocument->GetInterForm();
1192         ASSERT(pInterForm != NULL);
1193
1194         if (vp.IsGetting())
1195         {
1196                 if (pInterForm->IsCalculateEnabled())
1197                         vp << true;
1198                 else
1199                         vp << false;
1200         }
1201         else
1202         {
1203                 bool bCalculate;
1204                 vp >> bCalculate;
1205
1206                 pInterForm->EnableCalculate(bCalculate);
1207         }
1208
1209         return TRUE;
1210 }
1211
1212 FX_BOOL Document::documentFileName(IFXJS_Context* cc, CJS_PropValue& vp, CFX_WideString& sError)
1213 {
1214         if (vp.IsSetting()) {
1215                 CJS_Context* pContext = static_cast<CJS_Context*>(cc);
1216                 sError = JSGetStringFromID(pContext, IDS_STRING_JSREADONLY);
1217                 return FALSE;
1218         }
1219         CFX_WideString wsFilePath = m_pDocument->GetPath();
1220         FX_INT32 i = wsFilePath.GetLength() - 1;
1221         for ( ; i >= 0; i-- )
1222         {
1223                 if ( wsFilePath.GetAt( i ) == L'\\' || wsFilePath.GetAt( i ) == L'/' )
1224                         break;
1225         }
1226         if ( i >= 0 && i < wsFilePath.GetLength() - 1 )
1227         {
1228                 vp << ( wsFilePath.GetBuffer( wsFilePath.GetLength() ) + i + 1 );
1229         }else{
1230                 vp << L"";
1231         }
1232         return TRUE;
1233 }
1234
1235 CFX_WideString Document::ReversalStr(CFX_WideString cbFrom)
1236 {
1237         size_t iLength = cbFrom.GetLength();
1238         pdfium::base::CheckedNumeric<size_t> iSize = sizeof(wchar_t);
1239         iSize *= (iLength + 1);
1240         wchar_t* pResult = (wchar_t*)malloc(iSize.ValueOrDie());
1241         wchar_t* pFrom = (wchar_t*)cbFrom.GetBuffer(iLength);
1242
1243         for (size_t i = 0; i < iLength; i++)
1244         {
1245                 pResult[i] = *(pFrom + iLength - i - 1);
1246         }
1247         pResult[iLength] = L'\0';
1248
1249         cbFrom.ReleaseBuffer();
1250         CFX_WideString cbRet = CFX_WideString(pResult);
1251         free(pResult);
1252         pResult = NULL;
1253         return cbRet;
1254 }
1255
1256 CFX_WideString Document::CutString(CFX_WideString cbFrom)
1257 {
1258         size_t iLength = cbFrom.GetLength();
1259         pdfium::base::CheckedNumeric<size_t> iSize = sizeof(wchar_t);
1260         iSize *= (iLength + 1);
1261         wchar_t* pResult = (wchar_t*)malloc(iSize.ValueOrDie());
1262         wchar_t* pFrom = (wchar_t*)cbFrom.GetBuffer(iLength);
1263
1264         for (int i = 0; i < iLength; i++)
1265         {
1266                 if (pFrom[i] == L'\\' || pFrom[i] == L'/')
1267                 {
1268                         pResult[i] = L'\0';
1269                         break;
1270                 }
1271                 pResult[i] = pFrom[i];
1272         }
1273         pResult[iLength] = L'\0';
1274
1275         cbFrom.ReleaseBuffer();
1276         CFX_WideString cbRet = CFX_WideString(pResult);
1277         free(pResult);
1278         pResult = NULL;
1279         return cbRet;
1280 }
1281
1282 FX_BOOL Document::path(IFXJS_Context* cc, CJS_PropValue& vp, CFX_WideString& sError)
1283 {
1284         if (vp.IsSetting()) {
1285                 CJS_Context* pContext = static_cast<CJS_Context*>(cc);
1286                 sError = JSGetStringFromID(pContext, IDS_STRING_JSREADONLY);
1287                 return FALSE;
1288         }
1289         vp << app::SysPathToPDFPath(m_pDocument->GetPath());
1290         return TRUE;
1291 }
1292
1293 FX_BOOL Document::pageWindowRect(IFXJS_Context* cc, CJS_PropValue& vp, CFX_WideString& sError)
1294 {
1295         return TRUE;
1296 }
1297
1298 FX_BOOL Document::layout(IFXJS_Context* cc, CJS_PropValue& vp, CFX_WideString& sError)
1299 {
1300         return TRUE;
1301 }
1302
1303 FX_BOOL Document::addLink(IFXJS_Context* cc, const CJS_Parameters& params, CJS_Value& vRet, CFX_WideString& sError)
1304 {
1305         return TRUE;
1306 }
1307
1308 FX_BOOL Document::closeDoc(IFXJS_Context* cc, const CJS_Parameters& params, CJS_Value& vRet, CFX_WideString& sError)
1309 {
1310         ASSERT(m_pDocument != NULL);
1311         return TRUE;
1312 }
1313
1314 FX_BOOL Document::getPageBox(IFXJS_Context* cc, const CJS_Parameters& params, CJS_Value& vRet, CFX_WideString& sError)
1315 {
1316         return TRUE;
1317 }
1318
1319 FX_BOOL Document::getAnnot(IFXJS_Context* cc, const CJS_Parameters& params, CJS_Value& vRet, CFX_WideString& sError)
1320 {
1321         return TRUE;
1322 }
1323
1324 FX_BOOL Document::getAnnots(IFXJS_Context* cc, const CJS_Parameters& params, CJS_Value& vRet, CFX_WideString& sError)
1325 {
1326         vRet.SetNull();
1327         return TRUE;
1328 }
1329
1330 FX_BOOL Document::getAnnot3D(IFXJS_Context* cc, const CJS_Parameters& params, CJS_Value& vRet, CFX_WideString& sError)
1331 {
1332         vRet.SetNull();
1333         return TRUE;
1334 }
1335
1336 FX_BOOL Document::getAnnots3D(IFXJS_Context* cc, const CJS_Parameters& params, CJS_Value& vRet, CFX_WideString& sError)
1337 {
1338         vRet = VT_undefined;
1339         return TRUE;
1340 }
1341
1342 FX_BOOL Document::getOCGs(IFXJS_Context* cc, const CJS_Parameters& params, CJS_Value& vRet, CFX_WideString& sError)
1343 {
1344         return TRUE;
1345 }
1346
1347 FX_BOOL Document::getLinks(IFXJS_Context* cc, const CJS_Parameters& params, CJS_Value& vRet, CFX_WideString& sError)
1348 {
1349         return TRUE;
1350 }
1351
1352 bool Document::IsEnclosedInRect(CFX_FloatRect rect, CFX_FloatRect LinkRect)
1353 {
1354         if (rect.left <= LinkRect.left
1355           && rect.top <= LinkRect.top
1356           && rect.right >= LinkRect.right
1357           && rect.bottom >= LinkRect.bottom)
1358                 return true;
1359         else
1360                 return false;
1361 }
1362
1363 void IconTree::InsertIconElement(IconElement* pNewIcon)
1364 {
1365         if (!pNewIcon)return;
1366
1367         if (m_pHead == NULL && m_pEnd == NULL)
1368         {
1369                 m_pHead = m_pEnd = pNewIcon;
1370                 m_iLength++;
1371         }
1372         else
1373         {
1374                 m_pEnd->NextIcon = pNewIcon;
1375                 m_pEnd = pNewIcon;
1376                 m_iLength++;
1377         }
1378 }
1379
1380 void IconTree::DeleteIconTree()
1381 {
1382         if (!m_pHead || !m_pEnd)return;
1383
1384         IconElement* pTemp = NULL;
1385         while(m_pEnd != m_pHead)
1386         {
1387                 pTemp = m_pHead;
1388                 m_pHead = m_pHead->NextIcon;
1389                 delete pTemp;
1390         }
1391
1392         delete m_pEnd;
1393         m_pHead = NULL;
1394         m_pEnd = NULL;
1395 }
1396
1397 int IconTree::GetLength()
1398 {
1399         return m_iLength;
1400 }
1401
1402 IconElement* IconTree::operator [](int iIndex)
1403 {
1404         if (iIndex >= 0 && iIndex <= m_iLength)
1405         {
1406                 IconElement* pTemp = m_pHead;
1407                 for (int i = 0; i < iIndex; i++)
1408                 {
1409                         pTemp = pTemp->NextIcon;
1410                 }
1411                 return pTemp;
1412         }
1413         else
1414                 return NULL;
1415 }
1416
1417 void IconTree::DeleteIconElement(CFX_WideString swIconName)
1418 {
1419         IconElement* pTemp = m_pHead;
1420         int iLoopCount = m_iLength;
1421         for (int i = 0; i < iLoopCount - 1; i++)
1422         {
1423                 if (pTemp == m_pEnd)
1424                         break;
1425
1426                 if (m_pHead->IconName == swIconName)
1427                 {
1428                         m_pHead = m_pHead->NextIcon;
1429                         delete pTemp;
1430                         m_iLength--;
1431                         pTemp = m_pHead;
1432                 }
1433                 if (pTemp->NextIcon->IconName == swIconName)
1434                 {
1435                         if (pTemp->NextIcon == m_pEnd)
1436                         {
1437                                 m_pEnd = pTemp;
1438                                 delete pTemp->NextIcon;
1439                                 m_iLength--;
1440                                 pTemp->NextIcon = NULL;
1441                         }
1442                         else
1443                         {
1444                                 IconElement* pElement = pTemp->NextIcon;
1445                                 pTemp->NextIcon = pTemp->NextIcon->NextIcon;
1446                                 delete pElement;
1447                                 m_iLength--;
1448                                 pElement = NULL;
1449                         }
1450
1451                         continue;
1452                 }
1453
1454                 pTemp = pTemp->NextIcon;
1455         }
1456 }
1457
1458 FX_BOOL Document::addIcon(IFXJS_Context* cc, const CJS_Parameters& params, CJS_Value& vRet, CFX_WideString& sError)
1459 {
1460         if (params.size() != 2)return FALSE;
1461
1462         CJS_Context* pContext = (CJS_Context*)cc;
1463         ASSERT(pContext != NULL);
1464         CJS_Runtime* pRuntime = pContext->GetJSRuntime();
1465         ASSERT(pRuntime != NULL);
1466
1467         CFX_WideString swIconName = params[0].ToCFXWideString();
1468
1469         JSFXObject pJSIcon = params[1].ToV8Object();
1470         if (JS_GetObjDefnID(pJSIcon) != JS_GetObjDefnID(*pRuntime, L"Icon")) return FALSE;
1471
1472         CJS_EmbedObj* pEmbedObj = params[1].ToCJSObject()->GetEmbedObject();
1473         if (!pEmbedObj)return FALSE;
1474         Icon* pIcon = (Icon*)pEmbedObj;
1475
1476         if (!m_pIconTree)
1477                 m_pIconTree = new IconTree();
1478
1479         IconElement* pNewIcon = new IconElement();
1480         pNewIcon->IconName = swIconName;
1481         pNewIcon->NextIcon = NULL;
1482         pNewIcon->IconStream = pIcon;
1483         m_pIconTree->InsertIconElement(pNewIcon);
1484         return TRUE;
1485 }
1486
1487 FX_BOOL Document::icons(IFXJS_Context* cc, CJS_PropValue& vp, CFX_WideString& sError)
1488 {
1489         if (vp.IsSetting()) {
1490                 CJS_Context* pContext = static_cast<CJS_Context*>(cc);
1491                 sError = JSGetStringFromID(pContext, IDS_STRING_JSREADONLY);
1492                 return FALSE;
1493         }
1494
1495         if (!m_pIconTree)
1496         {
1497                 vp.SetNull();
1498                 return TRUE;
1499         }
1500
1501         CJS_Array Icons(m_isolate);
1502         IconElement* pIconElement = NULL;
1503         int iIconTreeLength = m_pIconTree->GetLength();
1504
1505         CJS_Context* pContext = (CJS_Context *)cc;
1506         CJS_Runtime* pRuntime = pContext->GetJSRuntime();
1507
1508         for (int i = 0; i < iIconTreeLength; i++)
1509         {
1510                 pIconElement = (*m_pIconTree)[i];
1511
1512                 JSFXObject  pObj = JS_NewFxDynamicObj(*pRuntime, pContext, JS_GetObjDefnID(*pRuntime, L"Icon"));
1513                 if (pObj.IsEmpty()) return FALSE;
1514
1515                 CJS_Icon * pJS_Icon = (CJS_Icon *)JS_GetPrivate(pObj);
1516                 if (!pJS_Icon) return FALSE;
1517
1518                 Icon* pIcon = (Icon*)pJS_Icon->GetEmbedObject();
1519                 if (!pIcon)return FALSE;
1520
1521                 pIcon->SetStream(pIconElement->IconStream->GetStream());
1522                 pIcon->SetIconName(pIconElement->IconName);
1523                 Icons.SetElement(i, CJS_Value(m_isolate,pJS_Icon));
1524         }
1525
1526         vp << Icons;
1527         return TRUE;
1528 }
1529
1530 FX_BOOL Document::getIcon(IFXJS_Context* cc, const CJS_Parameters& params, CJS_Value& vRet, CFX_WideString& sError)
1531 {
1532         if (params.size() != 1)return FALSE;
1533         if(!m_pIconTree)
1534                 return FALSE;
1535         CFX_WideString swIconName = params[0].ToCFXWideString();
1536         int iIconCounts = m_pIconTree->GetLength();
1537
1538         CJS_Context* pContext = (CJS_Context *)cc;
1539         CJS_Runtime* pRuntime = pContext->GetJSRuntime();
1540
1541         for (int i = 0; i < iIconCounts; i++)
1542         {
1543                 if ((*m_pIconTree)[i]->IconName == swIconName)
1544                 {
1545                         Icon* pRetIcon = (*m_pIconTree)[i]->IconStream;
1546
1547                         JSFXObject  pObj = JS_NewFxDynamicObj(*pRuntime, pContext, JS_GetObjDefnID(*pRuntime, L"Icon"));
1548                         if (pObj.IsEmpty()) return FALSE;
1549
1550                         CJS_Icon * pJS_Icon = (CJS_Icon *)JS_GetPrivate(pObj);
1551                         if (!pJS_Icon) return FALSE;
1552
1553                         Icon* pIcon = (Icon*)pJS_Icon->GetEmbedObject();
1554                         if (!pIcon)return FALSE;
1555
1556                         pIcon->SetIconName(swIconName);
1557                         pIcon->SetStream(pRetIcon->GetStream());
1558                         vRet = pJS_Icon;
1559                         return TRUE;
1560                 }
1561         }
1562
1563         return FALSE;
1564 }
1565
1566 FX_BOOL Document::removeIcon(IFXJS_Context* cc, const CJS_Parameters& params, CJS_Value& vRet, CFX_WideString& sError)
1567 {
1568         if (params.size() != 1)return FALSE;
1569         if(!m_pIconTree)
1570                 return FALSE;
1571         CFX_WideString swIconName = params[0].ToCFXWideString();
1572         return TRUE;
1573 }
1574
1575 FX_BOOL Document::createDataObject(IFXJS_Context* cc, const CJS_Parameters& params, CJS_Value& vRet, CFX_WideString& sError)
1576 {
1577   // Unsafe, not implemented.
1578   return TRUE;
1579 }
1580
1581 FX_BOOL Document::media(IFXJS_Context* cc, CJS_PropValue& vp, CFX_WideString& sError)
1582 {
1583         return TRUE;
1584 }
1585
1586 FX_BOOL Document::calculateNow(IFXJS_Context* cc, const CJS_Parameters& params, CJS_Value& vRet, CFX_WideString& sError)
1587 {
1588         ASSERT(m_pDocument != NULL);
1589
1590         if (!(m_pDocument->GetPermissions(FPDFPERM_MODIFY) ||
1591                 m_pDocument->GetPermissions(FPDFPERM_ANNOT_FORM) ||
1592                 m_pDocument->GetPermissions(FPDFPERM_FILL_FORM))) return FALSE;
1593
1594         CPDFSDK_InterForm* pInterForm = (CPDFSDK_InterForm*)m_pDocument->GetInterForm();
1595         ASSERT(pInterForm != NULL);
1596         pInterForm->OnCalculate();
1597         return TRUE;
1598 }
1599
1600 FX_BOOL Document::Collab(IFXJS_Context* cc, CJS_PropValue& vp, CFX_WideString& sError)
1601 {
1602         return TRUE;
1603 }
1604
1605 FX_BOOL Document::getPageNthWord(IFXJS_Context* cc, const CJS_Parameters& params, CJS_Value& vRet, CFX_WideString& sError)
1606 {
1607         ASSERT(m_pDocument != NULL);
1608
1609         if (!m_pDocument->GetPermissions(FPDFPERM_EXTRACT_ACCESS)) return FALSE;
1610
1611         int nPageNo = params.GetSize() > 0 ? params[0].ToInt() : 0;
1612         int nWordNo = params.GetSize() > 1 ? params[1].ToInt() : 0;
1613         bool bStrip = params.GetSize() > 2 ? params[2].ToBool() : true;
1614
1615         CPDF_Document* pDocument = m_pDocument->GetDocument()->GetPDFDoc();
1616         if (!pDocument) return FALSE;
1617
1618         if (nPageNo < 0 || nPageNo >= pDocument->GetPageCount())
1619         {
1620                 CJS_Context* pContext = static_cast<CJS_Context*>(cc);
1621                 sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
1622                 return FALSE;
1623         }
1624
1625         CPDF_Dictionary* pPageDict = pDocument->GetPage(nPageNo);
1626         if (!pPageDict) return FALSE;
1627
1628         CPDF_Page page;
1629         page.Load(pDocument, pPageDict);
1630         page.StartParse();
1631         page.ParseContent();
1632
1633         FX_POSITION pos = page.GetFirstObjectPosition();
1634
1635         int nWords = 0;
1636
1637         CFX_WideString swRet;
1638
1639         while (pos)
1640         {
1641                 if (CPDF_PageObject* pPageObj = page.GetNextObject(pos))
1642                 {
1643                         if (pPageObj->m_Type == PDFPAGE_TEXT)
1644                         {
1645                                 int nObjWords = CountWords((CPDF_TextObject*)pPageObj);
1646
1647                                 if (nWords + nObjWords >= nWordNo)
1648                                 {
1649                                         swRet = GetObjWordStr((CPDF_TextObject*)pPageObj, nWordNo - nWords);
1650                                         break;
1651                                 }
1652
1653                                 nWords += nObjWords;
1654                         }
1655                 }
1656         }
1657
1658         if (bStrip)
1659         {
1660                 swRet.TrimLeft();
1661                 swRet.TrimRight();
1662         }
1663
1664         vRet = swRet;
1665         return TRUE;
1666 }
1667
1668 FX_BOOL Document::getPageNthWordQuads(IFXJS_Context* cc, const CJS_Parameters& params, CJS_Value& vRet, CFX_WideString& sError)
1669 {
1670         ASSERT(m_pDocument != NULL);
1671
1672         if (!m_pDocument->GetPermissions(FPDFPERM_EXTRACT_ACCESS)) return FALSE;
1673
1674         return FALSE;
1675 }
1676
1677 FX_BOOL Document::getPageNumWords(IFXJS_Context* cc, const CJS_Parameters& params, CJS_Value& vRet, CFX_WideString& sError)
1678 {
1679         ASSERT(m_pDocument != NULL);
1680
1681         if (!m_pDocument->GetPermissions(FPDFPERM_EXTRACT_ACCESS)) return FALSE;
1682
1683         int nPageNo = params.GetSize() > 0 ? params[0].ToInt() : 0;
1684
1685         CPDF_Document* pDocument = m_pDocument->GetDocument()->GetPDFDoc();
1686         ASSERT(pDocument != NULL);
1687
1688         if (nPageNo < 0 || nPageNo >= pDocument->GetPageCount())
1689         {
1690                 CJS_Context* pContext = static_cast<CJS_Context*>(cc);
1691                 sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
1692                 return FALSE;
1693         }
1694
1695         CPDF_Dictionary* pPageDict = pDocument->GetPage(nPageNo);
1696         if (!pPageDict) return FALSE;
1697
1698         CPDF_Page page;
1699         page.Load(pDocument, pPageDict);
1700         page.StartParse();
1701         page.ParseContent();
1702
1703         FX_POSITION pos = page.GetFirstObjectPosition();
1704
1705         int nWords = 0;
1706
1707         while (pos)
1708         {
1709                 if (CPDF_PageObject* pPageObj = page.GetNextObject(pos))
1710                 {
1711                         if (pPageObj->m_Type == PDFPAGE_TEXT)
1712                         {
1713                                 CPDF_TextObject* pTextObj = (CPDF_TextObject*)pPageObj;
1714                                 nWords += CountWords(pTextObj);
1715                         }
1716                 }
1717         }
1718
1719         vRet = nWords;
1720
1721         return TRUE;
1722 }
1723
1724 FX_BOOL Document::getPrintParams(IFXJS_Context* cc, const CJS_Parameters& params, CJS_Value& vRet, CFX_WideString& sError)
1725 {
1726         CJS_Context* pContext = (CJS_Context*)cc;
1727         ASSERT(pContext != NULL);
1728         CJS_Runtime* pRuntime = pContext->GetJSRuntime();
1729         ASSERT(pRuntime != NULL);
1730         JSFXObject pRetObj = JS_NewFxDynamicObj(*pRuntime, pContext, JS_GetObjDefnID(*pRuntime, L"PrintParamsObj"));
1731         //not implemented yet.
1732         vRet = pRetObj;
1733
1734         return TRUE;
1735 }
1736
1737 #define ISLATINWORD(u)  (u != 0x20 && u <= 0x28FF)
1738
1739 int     Document::CountWords(CPDF_TextObject* pTextObj)
1740 {
1741         if (!pTextObj) return 0;
1742
1743         int nWords = 0;
1744
1745         CPDF_Font* pFont = pTextObj->GetFont();
1746         if (!pFont) return 0;
1747
1748         FX_BOOL bIsLatin = FALSE;
1749
1750         for (int i=0, sz=pTextObj->CountChars(); i<sz; i++)
1751         {
1752                 FX_DWORD charcode = -1;
1753                 FX_FLOAT kerning;
1754
1755                 pTextObj->GetCharInfo(i, charcode, kerning);
1756                 CFX_WideString swUnicode = pFont->UnicodeFromCharCode(charcode);
1757
1758                 FX_WORD unicode = 0;
1759                 if (swUnicode.GetLength() > 0)
1760                         unicode = swUnicode[0];
1761
1762                 if (ISLATINWORD(unicode) && bIsLatin)
1763                         continue;
1764
1765                 bIsLatin = ISLATINWORD(unicode);
1766                 if (unicode != 0x20)
1767                         nWords++;
1768         }
1769
1770         return nWords;
1771 }
1772
1773 CFX_WideString Document::GetObjWordStr(CPDF_TextObject* pTextObj, int nWordIndex)
1774 {
1775         ASSERT(pTextObj != NULL);
1776
1777         CFX_WideString swRet;
1778
1779         CPDF_Font* pFont = pTextObj->GetFont();
1780         if (!pFont) return L"";
1781
1782         int nWords = 0;
1783         FX_BOOL bIsLatin = FALSE;
1784
1785         for (int i=0, sz=pTextObj->CountChars(); i<sz; i++)
1786         {
1787                 FX_DWORD charcode = -1;
1788                 FX_FLOAT kerning;
1789
1790                 pTextObj->GetCharInfo(i, charcode, kerning);
1791                 CFX_WideString swUnicode = pFont->UnicodeFromCharCode(charcode);
1792
1793                 FX_WORD unicode = 0;
1794                 if (swUnicode.GetLength() > 0)
1795                         unicode = swUnicode[0];
1796
1797                 if (ISLATINWORD(unicode) && bIsLatin)
1798                 {
1799                 }
1800                 else
1801                 {
1802                         bIsLatin = ISLATINWORD(unicode);
1803                         if (unicode != 0x20)
1804                                 nWords++;
1805                 }
1806
1807                 if (nWords-1 == nWordIndex)
1808                         swRet += unicode;
1809         }
1810
1811         return swRet;
1812 }
1813
1814 FX_BOOL Document::zoom(IFXJS_Context* cc, CJS_PropValue& vp, CFX_WideString& sError)
1815 {
1816
1817         return TRUE;
1818 }
1819
1820 /**
1821 (none,  NoVary)
1822 (fitP,  FitPage)
1823 (fitW,  FitWidth)
1824 (fitH,  FitHeight)
1825 (fitV,  FitVisibleWidth)
1826 (pref,  Preferred)
1827 (refW,  ReflowWidth)
1828 */
1829
1830 FX_BOOL Document::zoomType(IFXJS_Context* cc, CJS_PropValue& vp, CFX_WideString& sError)
1831 {
1832         return TRUE;
1833 }
1834
1835 FX_BOOL Document::deletePages(IFXJS_Context* cc, const CJS_Parameters& params, CJS_Value& vRet, CFX_WideString& sError)
1836 {
1837         v8::Isolate* isolate = GetIsolate(cc);
1838         ASSERT(m_pDocument != NULL);
1839
1840         if (!(m_pDocument->GetPermissions(FPDFPERM_MODIFY) ||
1841                 m_pDocument->GetPermissions(FPDFPERM_ASSEMBLE))) return FALSE;
1842
1843         int iSize = params.size();
1844
1845         int nStart = 0;
1846         int nEnd = 0;
1847
1848         if (iSize < 1)
1849         {
1850         }
1851         else if (iSize == 1)
1852         {
1853                 if (params[0].GetType() == VT_object)
1854                 {
1855                         JSObject pObj = params[0].ToV8Object();
1856                         v8::Handle<v8::Value> pValue = JS_GetObjectElement(isolate, pObj, L"nStart");
1857             nStart = CJS_Value(m_isolate, pValue, GET_VALUE_TYPE(pValue)).ToInt();
1858
1859                         pValue = JS_GetObjectElement(isolate, pObj, L"nEnd");
1860                         nEnd = CJS_Value(m_isolate, pValue, GET_VALUE_TYPE(pValue)).ToInt();
1861                 }
1862                 else
1863                 {
1864                         nStart = params[0].ToInt();
1865                 }
1866         }
1867         else
1868         {
1869                 nStart = params[0].ToInt();
1870                 nEnd = params[1].ToInt();
1871         }
1872
1873         int nTotal = m_pDocument->GetPageCount();
1874
1875         if (nStart < 0) nStart = 0;
1876         if (nStart >= nTotal) nStart = nTotal - 1;
1877
1878         if (nEnd < 0) nEnd = 0;
1879         if (nEnd >= nTotal) nEnd = nTotal - 1;
1880
1881         if (nEnd < nStart) nEnd = nStart;
1882
1883
1884
1885         return TRUE;
1886 }
1887
1888 FX_BOOL Document::extractPages(IFXJS_Context* cc, const CJS_Parameters& params, CJS_Value& vRet, CFX_WideString& sError)
1889 {
1890   // Unsafe, not supported.
1891   return TRUE;
1892 }
1893
1894 FX_BOOL Document::insertPages(IFXJS_Context* cc, const CJS_Parameters& params, CJS_Value& vRet, CFX_WideString& sError)
1895 {
1896   // Unsafe, not supported.
1897   return TRUE;
1898 }
1899
1900 FX_BOOL Document::replacePages(IFXJS_Context* cc, const CJS_Parameters& params, CJS_Value& vRet, CFX_WideString& sError)
1901 {
1902   // Unsafe, not supported.
1903   return TRUE;
1904 }
1905
1906 FX_BOOL Document::getURL(IFXJS_Context* cc, const CJS_Parameters& params, CJS_Value& vRet, CFX_WideString& sError)
1907 {
1908   // Unsafe, not supported.
1909   return TRUE;
1910 }
1911
1912 void Document::AddDelayData(CJS_DelayData* pData)
1913 {
1914         m_DelayData.Add(pData);
1915 }
1916
1917 void Document::DoFieldDelay(const CFX_WideString& sFieldName, int nControlIndex)
1918 {
1919         CFX_DWordArray DelArray;
1920
1921         for (int i=0,sz=m_DelayData.GetSize(); i<sz; i++)
1922         {
1923                 if (CJS_DelayData* pData = m_DelayData.GetAt(i))
1924                 {
1925                         if (pData->sFieldName == sFieldName && pData->nControlIndex == nControlIndex)
1926                         {
1927                                 Field::DoDelay(m_pDocument, pData);
1928                                 delete pData;
1929                                 m_DelayData.SetAt(i, NULL);
1930                                 DelArray.Add(i);
1931                         }
1932                 }
1933         }
1934
1935         for (int j=DelArray.GetSize()-1; j>=0; j--)
1936         {
1937                 m_DelayData.RemoveAt(DelArray[j]);
1938         }
1939 }
1940
1941 void Document::AddDelayAnnotData(CJS_AnnotObj *pData)
1942 {
1943         m_DelayAnnotData.Add(pData);
1944 }
1945
1946 void Document::DoAnnotDelay()
1947 {
1948         CFX_DWordArray DelArray;
1949
1950         for (int j=DelArray.GetSize()-1; j>=0; j--)
1951         {
1952                 m_DelayData.RemoveAt(DelArray[j]);
1953         }
1954 }
1955
1956 CJS_Document* Document::GetCJSDoc() const 
1957 {
1958         return static_cast<CJS_Document*>(m_pJSObject);
1959 }
1960