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