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 "fpdfsdk/include/fsdk_actionhandler.h" 8 #include "fpdfsdk/include/fsdk_define.h" 9 #include "fpdfsdk/include/fsdk_mgr.h" 10 #include "fpdfsdk/include/javascript/IJavaScript.h" 11 12 CPDFSDK_ActionHandler::CPDFSDK_ActionHandler() 13 : m_pFormActionHandler(new CPDFSDK_FormActionHandler) { 14 } 15 16 FX_BOOL CPDFSDK_ActionHandler::DoAction_DocOpen(const CPDF_Action& action, 17 CPDFSDK_Document* pDocument) { 18 CFX_PtrList list; 19 return ExecuteDocumentOpenAction(action, pDocument, list); 20 } 21 22 FX_BOOL CPDFSDK_ActionHandler::DoAction_JavaScript( 23 const CPDF_Action& JsAction, 24 CFX_WideString csJSName, 25 CPDFSDK_Document* pDocument) { 26 if (JsAction.GetType() == CPDF_Action::JavaScript) { 27 CFX_WideString swJS = JsAction.GetJavaScript(); 28 if (!swJS.IsEmpty()) { 29 RunDocumentOpenJavaScript(pDocument, csJSName, swJS); 30 return TRUE; 31 } 32 } 33 34 return FALSE; 35 } 36 37 FX_BOOL CPDFSDK_ActionHandler::DoAction_FieldJavaScript( 38 const CPDF_Action& JsAction, 39 CPDF_AAction::AActionType type, 40 CPDFSDK_Document* pDocument, 41 CPDF_FormField* pFormField, 42 PDFSDK_FieldAction& data) { 43 CPDFDoc_Environment* pEnv = pDocument->GetEnv(); 44 ASSERT(pEnv); 45 if (pEnv->IsJSInitiated() && JsAction.GetType() == CPDF_Action::JavaScript) { 46 CFX_WideString swJS = JsAction.GetJavaScript(); 47 if (!swJS.IsEmpty()) { 48 RunFieldJavaScript(pDocument, pFormField, type, data, swJS); 49 return TRUE; 50 } 51 } 52 return FALSE; 53 } 54 55 FX_BOOL CPDFSDK_ActionHandler::DoAction_Page( 56 const CPDF_Action& action, 57 enum CPDF_AAction::AActionType eType, 58 CPDFSDK_Document* pDocument) { 59 CFX_PtrList list; 60 return ExecuteDocumentPageAction(action, eType, pDocument, list); 61 } 62 63 FX_BOOL CPDFSDK_ActionHandler::DoAction_Document( 64 const CPDF_Action& action, 65 enum CPDF_AAction::AActionType eType, 66 CPDFSDK_Document* pDocument) { 67 CFX_PtrList list; 68 return ExecuteDocumentPageAction(action, eType, pDocument, list); 69 } 70 71 FX_BOOL CPDFSDK_ActionHandler::DoAction_BookMark(CPDF_Bookmark* pBookMark, 72 const CPDF_Action& action, 73 CPDF_AAction::AActionType type, 74 CPDFSDK_Document* pDocument) { 75 CFX_PtrList list; 76 return ExecuteBookMark(action, pDocument, pBookMark, list); 77 } 78 79 FX_BOOL CPDFSDK_ActionHandler::DoAction_Screen(const CPDF_Action& action, 80 CPDF_AAction::AActionType type, 81 CPDFSDK_Document* pDocument, 82 CPDFSDK_Annot* pScreen) { 83 CFX_PtrList list; 84 return ExecuteScreenAction(action, type, pDocument, pScreen, list); 85 } 86 87 FX_BOOL CPDFSDK_ActionHandler::DoAction_Link(const CPDF_Action& action, 88 CPDFSDK_Document* pDocument) { 89 CFX_PtrList list; 90 return ExecuteLinkAction(action, pDocument, list); 91 } 92 93 FX_BOOL CPDFSDK_ActionHandler::DoAction_Field(const CPDF_Action& action, 94 CPDF_AAction::AActionType type, 95 CPDFSDK_Document* pDocument, 96 CPDF_FormField* pFormField, 97 PDFSDK_FieldAction& data) { 98 CFX_PtrList list; 99 return ExecuteFieldAction(action, type, pDocument, pFormField, data, list); 100 } 101 102 FX_BOOL CPDFSDK_ActionHandler::ExecuteDocumentOpenAction( 103 const CPDF_Action& action, 104 CPDFSDK_Document* pDocument, 105 CFX_PtrList& list) { 106 CPDF_Dictionary* pDict = action.GetDict(); 107 if (list.Find(pDict)) 108 return FALSE; 109 110 list.AddTail(pDict); 111 112 CPDFDoc_Environment* pEnv = pDocument->GetEnv(); 113 ASSERT(pEnv); 114 if (action.GetType() == CPDF_Action::JavaScript) { 115 if (pEnv->IsJSInitiated()) { 116 CFX_WideString swJS = action.GetJavaScript(); 117 if (!swJS.IsEmpty()) { 118 RunDocumentOpenJavaScript(pDocument, L"", swJS); 119 } 120 } 121 } else { 122 DoAction_NoJs(action, pDocument); 123 } 124 125 for (int32_t i = 0, sz = action.GetSubActionsCount(); i < sz; i++) { 126 CPDF_Action subaction = action.GetSubAction(i); 127 if (!ExecuteDocumentOpenAction(subaction, pDocument, list)) 128 return FALSE; 129 } 130 131 return TRUE; 132 } 133 134 FX_BOOL CPDFSDK_ActionHandler::ExecuteLinkAction(const CPDF_Action& action, 135 CPDFSDK_Document* pDocument, 136 CFX_PtrList& list) { 137 CPDF_Dictionary* pDict = action.GetDict(); 138 if (list.Find(pDict)) 139 return FALSE; 140 141 list.AddTail(pDict); 142 143 CPDFDoc_Environment* pEnv = pDocument->GetEnv(); 144 ASSERT(pEnv); 145 if (action.GetType() == CPDF_Action::JavaScript) { 146 if (pEnv->IsJSInitiated()) { 147 CFX_WideString swJS = action.GetJavaScript(); 148 if (!swJS.IsEmpty()) { 149 IJS_Runtime* pRuntime = pDocument->GetJsRuntime(); 150 pRuntime->SetReaderDocument(pDocument); 151 152 IJS_Context* pContext = pRuntime->NewContext(); 153 pContext->OnLink_MouseUp(pDocument); 154 155 CFX_WideString csInfo; 156 FX_BOOL bRet = pContext->RunScript(swJS, &csInfo); 157 if (!bRet) { 158 // FIXME: return error. 159 } 160 161 pRuntime->ReleaseContext(pContext); 162 } 163 } 164 } else { 165 DoAction_NoJs(action, pDocument); 166 } 167 168 for (int32_t i = 0, sz = action.GetSubActionsCount(); i < sz; i++) { 169 CPDF_Action subaction = action.GetSubAction(i); 170 if (!ExecuteLinkAction(subaction, pDocument, list)) 171 return FALSE; 172 } 173 174 return TRUE; 175 } 176 177 FX_BOOL CPDFSDK_ActionHandler::ExecuteDocumentPageAction( 178 const CPDF_Action& action, 179 CPDF_AAction::AActionType type, 180 CPDFSDK_Document* pDocument, 181 CFX_PtrList& list) { 182 CPDF_Dictionary* pDict = action.GetDict(); 183 if (list.Find(pDict)) 184 return FALSE; 185 186 list.AddTail(pDict); 187 188 CPDFDoc_Environment* pEnv = pDocument->GetEnv(); 189 ASSERT(pEnv); 190 if (action.GetType() == CPDF_Action::JavaScript) { 191 if (pEnv->IsJSInitiated()) { 192 CFX_WideString swJS = action.GetJavaScript(); 193 if (!swJS.IsEmpty()) { 194 RunDocumentPageJavaScript(pDocument, type, swJS); 195 } 196 } 197 } else { 198 DoAction_NoJs(action, pDocument); 199 } 200 201 if (!IsValidDocView(pDocument)) 202 return FALSE; 203 204 for (int32_t i = 0, sz = action.GetSubActionsCount(); i < sz; i++) { 205 CPDF_Action subaction = action.GetSubAction(i); 206 if (!ExecuteDocumentPageAction(subaction, type, pDocument, list)) 207 return FALSE; 208 } 209 210 return TRUE; 211 } 212 213 FX_BOOL CPDFSDK_ActionHandler::IsValidField(CPDFSDK_Document* pDocument, 214 CPDF_Dictionary* pFieldDict) { 215 ASSERT(pFieldDict); 216 217 CPDFSDK_InterForm* pInterForm = pDocument->GetInterForm(); 218 CPDF_InterForm* pPDFInterForm = pInterForm->GetInterForm(); 219 return pPDFInterForm->GetFieldByDict(pFieldDict) != NULL; 220 } 221 222 FX_BOOL CPDFSDK_ActionHandler::ExecuteFieldAction( 223 const CPDF_Action& action, 224 CPDF_AAction::AActionType type, 225 CPDFSDK_Document* pDocument, 226 CPDF_FormField* pFormField, 227 PDFSDK_FieldAction& data, 228 CFX_PtrList& list) { 229 CPDF_Dictionary* pDict = action.GetDict(); 230 if (list.Find(pDict)) 231 return FALSE; 232 233 list.AddTail(pDict); 234 235 CPDFDoc_Environment* pEnv = pDocument->GetEnv(); 236 ASSERT(pEnv); 237 if (action.GetType() == CPDF_Action::JavaScript) { 238 if (pEnv->IsJSInitiated()) { 239 CFX_WideString swJS = action.GetJavaScript(); 240 if (!swJS.IsEmpty()) { 241 RunFieldJavaScript(pDocument, pFormField, type, data, swJS); 242 if (!IsValidField(pDocument, pFormField->GetFieldDict())) 243 return FALSE; 244 } 245 } 246 } else { 247 DoAction_NoJs(action, pDocument); 248 } 249 250 for (int32_t i = 0, sz = action.GetSubActionsCount(); i < sz; i++) { 251 CPDF_Action subaction = action.GetSubAction(i); 252 if (!ExecuteFieldAction(subaction, type, pDocument, pFormField, data, list)) 253 return FALSE; 254 } 255 256 return TRUE; 257 } 258 259 FX_BOOL CPDFSDK_ActionHandler::ExecuteScreenAction( 260 const CPDF_Action& action, 261 CPDF_AAction::AActionType type, 262 CPDFSDK_Document* pDocument, 263 CPDFSDK_Annot* pScreen, 264 CFX_PtrList& list) { 265 CPDF_Dictionary* pDict = action.GetDict(); 266 if (list.Find(pDict)) 267 return FALSE; 268 269 list.AddTail(pDict); 270 271 CPDFDoc_Environment* pEnv = pDocument->GetEnv(); 272 ASSERT(pEnv); 273 if (action.GetType() == CPDF_Action::JavaScript) { 274 if (pEnv->IsJSInitiated()) { 275 CFX_WideString swJS = action.GetJavaScript(); 276 if (!swJS.IsEmpty()) { 277 IJS_Runtime* pRuntime = pDocument->GetJsRuntime(); 278 pRuntime->SetReaderDocument(pDocument); 279 280 IJS_Context* pContext = pRuntime->NewContext(); 281 CFX_WideString csInfo; 282 FX_BOOL bRet = pContext->RunScript(swJS, &csInfo); 283 if (!bRet) { 284 // FIXME: return error. 285 } 286 287 pRuntime->ReleaseContext(pContext); 288 } 289 } 290 } else { 291 DoAction_NoJs(action, pDocument); 292 } 293 294 for (int32_t i = 0, sz = action.GetSubActionsCount(); i < sz; i++) { 295 CPDF_Action subaction = action.GetSubAction(i); 296 if (!ExecuteScreenAction(subaction, type, pDocument, pScreen, list)) 297 return FALSE; 298 } 299 300 return TRUE; 301 } 302 303 FX_BOOL CPDFSDK_ActionHandler::ExecuteBookMark(const CPDF_Action& action, 304 CPDFSDK_Document* pDocument, 305 CPDF_Bookmark* pBookmark, 306 CFX_PtrList& list) { 307 CPDF_Dictionary* pDict = action.GetDict(); 308 if (list.Find(pDict)) 309 return FALSE; 310 311 list.AddTail(pDict); 312 313 CPDFDoc_Environment* pEnv = pDocument->GetEnv(); 314 ASSERT(pEnv); 315 if (action.GetType() == CPDF_Action::JavaScript) { 316 if (pEnv->IsJSInitiated()) { 317 CFX_WideString swJS = action.GetJavaScript(); 318 if (!swJS.IsEmpty()) { 319 IJS_Runtime* pRuntime = pDocument->GetJsRuntime(); 320 pRuntime->SetReaderDocument(pDocument); 321 322 IJS_Context* pContext = pRuntime->NewContext(); 323 pContext->OnBookmark_MouseUp(pBookmark); 324 325 CFX_WideString csInfo; 326 FX_BOOL bRet = pContext->RunScript(swJS, &csInfo); 327 if (!bRet) { 328 // FIXME: return error. 329 } 330 331 pRuntime->ReleaseContext(pContext); 332 } 333 } 334 } else { 335 DoAction_NoJs(action, pDocument); 336 } 337 338 for (int32_t i = 0, sz = action.GetSubActionsCount(); i < sz; i++) { 339 CPDF_Action subaction = action.GetSubAction(i); 340 if (!ExecuteBookMark(subaction, pDocument, pBookmark, list)) 341 return FALSE; 342 } 343 344 return TRUE; 345 } 346 347 void CPDFSDK_ActionHandler::DoAction_NoJs(const CPDF_Action& action, 348 CPDFSDK_Document* pDocument) { 349 ASSERT(pDocument); 350 351 switch (action.GetType()) { 352 case CPDF_Action::GoTo: 353 DoAction_GoTo(pDocument, action); 354 break; 355 case CPDF_Action::GoToR: 356 DoAction_GoToR(pDocument, action); 357 break; 358 case CPDF_Action::GoToE: 359 break; 360 case CPDF_Action::Launch: 361 DoAction_Launch(pDocument, action); 362 break; 363 case CPDF_Action::Thread: 364 break; 365 case CPDF_Action::URI: 366 DoAction_URI(pDocument, action); 367 break; 368 case CPDF_Action::Sound: 369 break; 370 case CPDF_Action::Movie: 371 break; 372 case CPDF_Action::Hide: 373 if (m_pFormActionHandler) { 374 m_pFormActionHandler->DoAction_Hide(action, pDocument); 375 } 376 break; 377 case CPDF_Action::Named: 378 DoAction_Named(pDocument, action); 379 break; 380 case CPDF_Action::SubmitForm: 381 if (m_pFormActionHandler) { 382 m_pFormActionHandler->DoAction_SubmitForm(action, pDocument); 383 } 384 break; 385 case CPDF_Action::ResetForm: 386 if (m_pFormActionHandler) { 387 m_pFormActionHandler->DoAction_ResetForm(action, pDocument); 388 } 389 break; 390 case CPDF_Action::ImportData: 391 if (m_pFormActionHandler) { 392 m_pFormActionHandler->DoAction_ImportData(action, pDocument); 393 } 394 break; 395 case CPDF_Action::JavaScript: 396 ASSERT(FALSE); 397 break; 398 case CPDF_Action::SetOCGState: 399 DoAction_SetOCGState(pDocument, action); 400 break; 401 case CPDF_Action::Rendition: 402 break; 403 case CPDF_Action::Trans: 404 break; 405 case CPDF_Action::GoTo3DView: 406 break; 407 default: 408 break; 409 } 410 } 411 412 FX_BOOL CPDFSDK_ActionHandler::IsValidDocView(CPDFSDK_Document* pDocument) { 413 ASSERT(pDocument); 414 return TRUE; 415 } 416 417 void CPDFSDK_ActionHandler::DoAction_GoTo(CPDFSDK_Document* pDocument, 418 const CPDF_Action& action) { 419 ASSERT(action); 420 421 CPDF_Document* pPDFDocument = pDocument->GetPDFDocument(); 422 ASSERT(pPDFDocument); 423 424 CPDF_Dest MyDest = action.GetDest(pPDFDocument); 425 int nPageIndex = MyDest.GetPageIndex(pPDFDocument); 426 int nFitType = MyDest.GetZoomMode(); 427 const CPDF_Array* pMyArray = ToArray(MyDest.GetObject()); 428 float* pPosAry = nullptr; 429 int sizeOfAry = 0; 430 if (pMyArray) { 431 pPosAry = new float[pMyArray->GetCount()]; 432 int j = 0; 433 for (int i = 2; i < (int)pMyArray->GetCount(); i++) { 434 pPosAry[j++] = pMyArray->GetFloat(i); 435 } 436 sizeOfAry = j; 437 } 438 439 CPDFDoc_Environment* pApp = pDocument->GetEnv(); 440 pApp->FFI_DoGoToAction(nPageIndex, nFitType, pPosAry, sizeOfAry); 441 delete[] pPosAry; 442 } 443 444 void CPDFSDK_ActionHandler::DoAction_GoToR(CPDFSDK_Document* pDocument, 445 const CPDF_Action& action) {} 446 447 void CPDFSDK_ActionHandler::DoAction_Launch(CPDFSDK_Document* pDocument, 448 const CPDF_Action& action) {} 449 450 void CPDFSDK_ActionHandler::DoAction_URI(CPDFSDK_Document* pDocument, 451 const CPDF_Action& action) { 452 ASSERT(action); 453 454 CPDFDoc_Environment* pApp = pDocument->GetEnv(); 455 CFX_ByteString sURI = action.GetURI(pDocument->GetPDFDocument()); 456 pApp->FFI_DoURIAction(sURI.c_str()); 457 } 458 459 void CPDFSDK_ActionHandler::DoAction_Named(CPDFSDK_Document* pDocument, 460 const CPDF_Action& action) { 461 ASSERT(action); 462 463 CFX_ByteString csName = action.GetNamedAction(); 464 pDocument->GetEnv()->FFI_ExecuteNamedAction(csName); 465 } 466 467 void CPDFSDK_ActionHandler::DoAction_SetOCGState(CPDFSDK_Document* pDocument, 468 const CPDF_Action& action) {} 469 470 void CPDFSDK_ActionHandler::RunFieldJavaScript(CPDFSDK_Document* pDocument, 471 CPDF_FormField* pFormField, 472 CPDF_AAction::AActionType type, 473 PDFSDK_FieldAction& data, 474 const CFX_WideString& script) { 475 ASSERT(type != CPDF_AAction::Calculate); 476 ASSERT(type != CPDF_AAction::Format); 477 478 IJS_Runtime* pRuntime = pDocument->GetJsRuntime(); 479 pRuntime->SetReaderDocument(pDocument); 480 481 IJS_Context* pContext = pRuntime->NewContext(); 482 switch (type) { 483 case CPDF_AAction::CursorEnter: 484 pContext->OnField_MouseEnter(data.bModifier, data.bShift, pFormField); 485 break; 486 case CPDF_AAction::CursorExit: 487 pContext->OnField_MouseExit(data.bModifier, data.bShift, pFormField); 488 break; 489 case CPDF_AAction::ButtonDown: 490 pContext->OnField_MouseDown(data.bModifier, data.bShift, pFormField); 491 break; 492 case CPDF_AAction::ButtonUp: 493 pContext->OnField_MouseUp(data.bModifier, data.bShift, pFormField); 494 break; 495 case CPDF_AAction::GetFocus: 496 pContext->OnField_Focus(data.bModifier, data.bShift, pFormField, 497 data.sValue); 498 break; 499 case CPDF_AAction::LoseFocus: 500 pContext->OnField_Blur(data.bModifier, data.bShift, pFormField, 501 data.sValue); 502 break; 503 case CPDF_AAction::KeyStroke: 504 pContext->OnField_Keystroke(data.sChange, data.sChangeEx, data.bKeyDown, 505 data.bModifier, data.nSelEnd, data.nSelStart, 506 data.bShift, pFormField, data.sValue, 507 data.bWillCommit, data.bFieldFull, data.bRC); 508 break; 509 case CPDF_AAction::Validate: 510 pContext->OnField_Validate(data.sChange, data.sChangeEx, data.bKeyDown, 511 data.bModifier, data.bShift, pFormField, 512 data.sValue, data.bRC); 513 break; 514 default: 515 ASSERT(FALSE); 516 break; 517 } 518 519 CFX_WideString csInfo; 520 FX_BOOL bRet = pContext->RunScript(script, &csInfo); 521 if (!bRet) { 522 // FIXME: return error. 523 } 524 525 pRuntime->ReleaseContext(pContext); 526 } 527 528 void CPDFSDK_ActionHandler::RunDocumentOpenJavaScript( 529 CPDFSDK_Document* pDocument, 530 const CFX_WideString& sScriptName, 531 const CFX_WideString& script) { 532 IJS_Runtime* pRuntime = pDocument->GetJsRuntime(); 533 pRuntime->SetReaderDocument(pDocument); 534 IJS_Context* pContext = pRuntime->NewContext(); 535 pContext->OnDoc_Open(pDocument, sScriptName); 536 537 CFX_WideString csInfo; 538 FX_BOOL bRet = pContext->RunScript(script, &csInfo); 539 if (!bRet) { 540 // FIXME: return error. 541 } 542 543 pRuntime->ReleaseContext(pContext); 544 } 545 546 void CPDFSDK_ActionHandler::RunDocumentPageJavaScript( 547 CPDFSDK_Document* pDocument, 548 CPDF_AAction::AActionType type, 549 const CFX_WideString& script) { 550 IJS_Runtime* pRuntime = pDocument->GetJsRuntime(); 551 pRuntime->SetReaderDocument(pDocument); 552 553 IJS_Context* pContext = pRuntime->NewContext(); 554 switch (type) { 555 case CPDF_AAction::OpenPage: 556 pContext->OnPage_Open(pDocument); 557 break; 558 case CPDF_AAction::ClosePage: 559 pContext->OnPage_Close(pDocument); 560 break; 561 case CPDF_AAction::CloseDocument: 562 pContext->OnDoc_WillClose(pDocument); 563 break; 564 case CPDF_AAction::SaveDocument: 565 pContext->OnDoc_WillSave(pDocument); 566 break; 567 case CPDF_AAction::DocumentSaved: 568 pContext->OnDoc_DidSave(pDocument); 569 break; 570 case CPDF_AAction::PrintDocument: 571 pContext->OnDoc_WillPrint(pDocument); 572 break; 573 case CPDF_AAction::DocumentPrinted: 574 pContext->OnDoc_DidPrint(pDocument); 575 break; 576 case CPDF_AAction::PageVisible: 577 pContext->OnPage_InView(pDocument); 578 break; 579 case CPDF_AAction::PageInvisible: 580 pContext->OnPage_OutView(pDocument); 581 break; 582 default: 583 ASSERT(FALSE); 584 break; 585 } 586 587 CFX_WideString csInfo; 588 FX_BOOL bRet = pContext->RunScript(script, &csInfo); 589 if (!bRet) { 590 // FIXME: return error. 591 } 592 593 pRuntime->ReleaseContext(pContext); 594 } 595 596 FX_BOOL CPDFSDK_FormActionHandler::DoAction_Hide(const CPDF_Action& action, 597 CPDFSDK_Document* pDocument) { 598 CPDFSDK_InterForm* pInterForm = (CPDFSDK_InterForm*)pDocument->GetInterForm(); 599 if (pInterForm->DoAction_Hide(action)) { 600 pDocument->SetChangeMark(); 601 return TRUE; 602 } 603 604 return FALSE; 605 } 606 607 FX_BOOL CPDFSDK_FormActionHandler::DoAction_SubmitForm( 608 const CPDF_Action& action, 609 CPDFSDK_Document* pDocument) { 610 CPDFSDK_InterForm* pInterForm = (CPDFSDK_InterForm*)pDocument->GetInterForm(); 611 return pInterForm->DoAction_SubmitForm(action); 612 } 613 614 FX_BOOL CPDFSDK_FormActionHandler::DoAction_ResetForm( 615 const CPDF_Action& action, 616 CPDFSDK_Document* pDocument) { 617 CPDFSDK_InterForm* pInterForm = (CPDFSDK_InterForm*)pDocument->GetInterForm(); 618 return pInterForm->DoAction_ResetForm(action); 619 } 620 621 FX_BOOL CPDFSDK_FormActionHandler::DoAction_ImportData( 622 const CPDF_Action& action, 623 CPDFSDK_Document* pDocument) { 624 CPDFSDK_InterForm* pInterForm = (CPDFSDK_InterForm*)pDocument->GetInterForm(); 625 if (pInterForm->DoAction_ImportData(action)) { 626 pDocument->SetChangeMark(); 627 return TRUE; 628 } 629 630 return FALSE; 631 } 632