6010 lines
194 KiB
C++
6010 lines
194 KiB
C++
// Copyright 2016 PDFium Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
|
|
|
|
#include "xfa/fxfa/parser/cxfa_node.h"
|
|
|
|
#include <algorithm>
|
|
#include <map>
|
|
#include <memory>
|
|
#include <set>
|
|
#include <utility>
|
|
#include <vector>
|
|
|
|
#include "core/fxcrt/autorestorer.h"
|
|
#include "core/fxcrt/cfx_readonlymemorystream.h"
|
|
#include "core/fxcrt/fx_codepage.h"
|
|
#include "core/fxcrt/fx_extension.h"
|
|
#include "core/fxcrt/xml/cfx_xmldocument.h"
|
|
#include "core/fxcrt/xml/cfx_xmlelement.h"
|
|
#include "core/fxcrt/xml/cfx_xmlnode.h"
|
|
#include "core/fxcrt/xml/cfx_xmltext.h"
|
|
#include "core/fxge/dib/cfx_dibitmap.h"
|
|
#include "core/fxge/fx_font.h"
|
|
#include "fxjs/xfa/cfxjse_engine.h"
|
|
#include "fxjs/xfa/cfxjse_value.h"
|
|
#include "fxjs/xfa/cjx_node.h"
|
|
#include "third_party/base/compiler_specific.h"
|
|
#include "third_party/base/logging.h"
|
|
#include "third_party/base/ptr_util.h"
|
|
#include "third_party/base/span.h"
|
|
#include "third_party/base/stl_util.h"
|
|
#include "xfa/fde/cfde_textout.h"
|
|
#include "xfa/fgas/crt/cfgas_decimal.h"
|
|
#include "xfa/fgas/crt/locale_iface.h"
|
|
#include "xfa/fgas/font/cfgas_fontmgr.h"
|
|
#include "xfa/fgas/font/cfgas_gefont.h"
|
|
#include "xfa/fxfa/cxfa_eventparam.h"
|
|
#include "xfa/fxfa/cxfa_ffapp.h"
|
|
#include "xfa/fxfa/cxfa_ffdocview.h"
|
|
#include "xfa/fxfa/cxfa_ffnotify.h"
|
|
#include "xfa/fxfa/cxfa_fontmgr.h"
|
|
#include "xfa/fxfa/cxfa_textprovider.h"
|
|
#include "xfa/fxfa/parser/cxfa_accessiblecontent.h"
|
|
#include "xfa/fxfa/parser/cxfa_acrobat.h"
|
|
#include "xfa/fxfa/parser/cxfa_acrobat7.h"
|
|
#include "xfa/fxfa/parser/cxfa_adbe_jsconsole.h"
|
|
#include "xfa/fxfa/parser/cxfa_adbe_jsdebugger.h"
|
|
#include "xfa/fxfa/parser/cxfa_addsilentprint.h"
|
|
#include "xfa/fxfa/parser/cxfa_addviewerpreferences.h"
|
|
#include "xfa/fxfa/parser/cxfa_adjustdata.h"
|
|
#include "xfa/fxfa/parser/cxfa_adobeextensionlevel.h"
|
|
#include "xfa/fxfa/parser/cxfa_agent.h"
|
|
#include "xfa/fxfa/parser/cxfa_alwaysembed.h"
|
|
#include "xfa/fxfa/parser/cxfa_amd.h"
|
|
#include "xfa/fxfa/parser/cxfa_appearancefilter.h"
|
|
#include "xfa/fxfa/parser/cxfa_arc.h"
|
|
#include "xfa/fxfa/parser/cxfa_area.h"
|
|
#include "xfa/fxfa/parser/cxfa_arraynodelist.h"
|
|
#include "xfa/fxfa/parser/cxfa_assist.h"
|
|
#include "xfa/fxfa/parser/cxfa_attachnodelist.h"
|
|
#include "xfa/fxfa/parser/cxfa_attributes.h"
|
|
#include "xfa/fxfa/parser/cxfa_autosave.h"
|
|
#include "xfa/fxfa/parser/cxfa_barcode.h"
|
|
#include "xfa/fxfa/parser/cxfa_base.h"
|
|
#include "xfa/fxfa/parser/cxfa_batchoutput.h"
|
|
#include "xfa/fxfa/parser/cxfa_behavioroverride.h"
|
|
#include "xfa/fxfa/parser/cxfa_bind.h"
|
|
#include "xfa/fxfa/parser/cxfa_binditems.h"
|
|
#include "xfa/fxfa/parser/cxfa_bookend.h"
|
|
#include "xfa/fxfa/parser/cxfa_boolean.h"
|
|
#include "xfa/fxfa/parser/cxfa_border.h"
|
|
#include "xfa/fxfa/parser/cxfa_break.h"
|
|
#include "xfa/fxfa/parser/cxfa_breakafter.h"
|
|
#include "xfa/fxfa/parser/cxfa_breakbefore.h"
|
|
#include "xfa/fxfa/parser/cxfa_button.h"
|
|
#include "xfa/fxfa/parser/cxfa_cache.h"
|
|
#include "xfa/fxfa/parser/cxfa_calculate.h"
|
|
#include "xfa/fxfa/parser/cxfa_calendarsymbols.h"
|
|
#include "xfa/fxfa/parser/cxfa_caption.h"
|
|
#include "xfa/fxfa/parser/cxfa_certificate.h"
|
|
#include "xfa/fxfa/parser/cxfa_certificates.h"
|
|
#include "xfa/fxfa/parser/cxfa_change.h"
|
|
#include "xfa/fxfa/parser/cxfa_checkbutton.h"
|
|
#include "xfa/fxfa/parser/cxfa_choicelist.h"
|
|
#include "xfa/fxfa/parser/cxfa_color.h"
|
|
#include "xfa/fxfa/parser/cxfa_comb.h"
|
|
#include "xfa/fxfa/parser/cxfa_command.h"
|
|
#include "xfa/fxfa/parser/cxfa_common.h"
|
|
#include "xfa/fxfa/parser/cxfa_compress.h"
|
|
#include "xfa/fxfa/parser/cxfa_compression.h"
|
|
#include "xfa/fxfa/parser/cxfa_compresslogicalstructure.h"
|
|
#include "xfa/fxfa/parser/cxfa_compressobjectstream.h"
|
|
#include "xfa/fxfa/parser/cxfa_config.h"
|
|
#include "xfa/fxfa/parser/cxfa_conformance.h"
|
|
#include "xfa/fxfa/parser/cxfa_connect.h"
|
|
#include "xfa/fxfa/parser/cxfa_connectionset.h"
|
|
#include "xfa/fxfa/parser/cxfa_connectstring.h"
|
|
#include "xfa/fxfa/parser/cxfa_contentarea.h"
|
|
#include "xfa/fxfa/parser/cxfa_contentcopy.h"
|
|
#include "xfa/fxfa/parser/cxfa_copies.h"
|
|
#include "xfa/fxfa/parser/cxfa_corner.h"
|
|
#include "xfa/fxfa/parser/cxfa_creator.h"
|
|
#include "xfa/fxfa/parser/cxfa_currencysymbol.h"
|
|
#include "xfa/fxfa/parser/cxfa_currencysymbols.h"
|
|
#include "xfa/fxfa/parser/cxfa_currentpage.h"
|
|
#include "xfa/fxfa/parser/cxfa_data.h"
|
|
#include "xfa/fxfa/parser/cxfa_datagroup.h"
|
|
#include "xfa/fxfa/parser/cxfa_datamodel.h"
|
|
#include "xfa/fxfa/parser/cxfa_datavalue.h"
|
|
#include "xfa/fxfa/parser/cxfa_date.h"
|
|
#include "xfa/fxfa/parser/cxfa_datepattern.h"
|
|
#include "xfa/fxfa/parser/cxfa_datepatterns.h"
|
|
#include "xfa/fxfa/parser/cxfa_datetime.h"
|
|
#include "xfa/fxfa/parser/cxfa_datetimeedit.h"
|
|
#include "xfa/fxfa/parser/cxfa_datetimesymbols.h"
|
|
#include "xfa/fxfa/parser/cxfa_day.h"
|
|
#include "xfa/fxfa/parser/cxfa_daynames.h"
|
|
#include "xfa/fxfa/parser/cxfa_debug.h"
|
|
#include "xfa/fxfa/parser/cxfa_decimal.h"
|
|
#include "xfa/fxfa/parser/cxfa_defaulttypeface.h"
|
|
#include "xfa/fxfa/parser/cxfa_defaultui.h"
|
|
#include "xfa/fxfa/parser/cxfa_delete.h"
|
|
#include "xfa/fxfa/parser/cxfa_delta.h"
|
|
#include "xfa/fxfa/parser/cxfa_deltas.h"
|
|
#include "xfa/fxfa/parser/cxfa_desc.h"
|
|
#include "xfa/fxfa/parser/cxfa_destination.h"
|
|
#include "xfa/fxfa/parser/cxfa_digestmethod.h"
|
|
#include "xfa/fxfa/parser/cxfa_digestmethods.h"
|
|
#include "xfa/fxfa/parser/cxfa_document.h"
|
|
#include "xfa/fxfa/parser/cxfa_document_parser.h"
|
|
#include "xfa/fxfa/parser/cxfa_documentassembly.h"
|
|
#include "xfa/fxfa/parser/cxfa_draw.h"
|
|
#include "xfa/fxfa/parser/cxfa_driver.h"
|
|
#include "xfa/fxfa/parser/cxfa_dsigdata.h"
|
|
#include "xfa/fxfa/parser/cxfa_duplexoption.h"
|
|
#include "xfa/fxfa/parser/cxfa_dynamicrender.h"
|
|
#include "xfa/fxfa/parser/cxfa_edge.h"
|
|
#include "xfa/fxfa/parser/cxfa_effectiveinputpolicy.h"
|
|
#include "xfa/fxfa/parser/cxfa_effectiveoutputpolicy.h"
|
|
#include "xfa/fxfa/parser/cxfa_embed.h"
|
|
#include "xfa/fxfa/parser/cxfa_encoding.h"
|
|
#include "xfa/fxfa/parser/cxfa_encodings.h"
|
|
#include "xfa/fxfa/parser/cxfa_encrypt.h"
|
|
#include "xfa/fxfa/parser/cxfa_encryption.h"
|
|
#include "xfa/fxfa/parser/cxfa_encryptionlevel.h"
|
|
#include "xfa/fxfa/parser/cxfa_encryptionmethod.h"
|
|
#include "xfa/fxfa/parser/cxfa_encryptionmethods.h"
|
|
#include "xfa/fxfa/parser/cxfa_enforce.h"
|
|
#include "xfa/fxfa/parser/cxfa_equate.h"
|
|
#include "xfa/fxfa/parser/cxfa_equaterange.h"
|
|
#include "xfa/fxfa/parser/cxfa_era.h"
|
|
#include "xfa/fxfa/parser/cxfa_eranames.h"
|
|
#include "xfa/fxfa/parser/cxfa_event.h"
|
|
#include "xfa/fxfa/parser/cxfa_exclgroup.h"
|
|
#include "xfa/fxfa/parser/cxfa_exclude.h"
|
|
#include "xfa/fxfa/parser/cxfa_excludens.h"
|
|
#include "xfa/fxfa/parser/cxfa_exdata.h"
|
|
#include "xfa/fxfa/parser/cxfa_execute.h"
|
|
#include "xfa/fxfa/parser/cxfa_exobject.h"
|
|
#include "xfa/fxfa/parser/cxfa_extras.h"
|
|
#include "xfa/fxfa/parser/cxfa_field.h"
|
|
#include "xfa/fxfa/parser/cxfa_fill.h"
|
|
#include "xfa/fxfa/parser/cxfa_filter.h"
|
|
#include "xfa/fxfa/parser/cxfa_fliplabel.h"
|
|
#include "xfa/fxfa/parser/cxfa_float.h"
|
|
#include "xfa/fxfa/parser/cxfa_font.h"
|
|
#include "xfa/fxfa/parser/cxfa_fontinfo.h"
|
|
#include "xfa/fxfa/parser/cxfa_form.h"
|
|
#include "xfa/fxfa/parser/cxfa_format.h"
|
|
#include "xfa/fxfa/parser/cxfa_formfieldfilling.h"
|
|
#include "xfa/fxfa/parser/cxfa_groupparent.h"
|
|
#include "xfa/fxfa/parser/cxfa_handler.h"
|
|
#include "xfa/fxfa/parser/cxfa_hyphenation.h"
|
|
#include "xfa/fxfa/parser/cxfa_ifempty.h"
|
|
#include "xfa/fxfa/parser/cxfa_image.h"
|
|
#include "xfa/fxfa/parser/cxfa_imageedit.h"
|
|
#include "xfa/fxfa/parser/cxfa_includexdpcontent.h"
|
|
#include "xfa/fxfa/parser/cxfa_incrementalload.h"
|
|
#include "xfa/fxfa/parser/cxfa_incrementalmerge.h"
|
|
#include "xfa/fxfa/parser/cxfa_insert.h"
|
|
#include "xfa/fxfa/parser/cxfa_instancemanager.h"
|
|
#include "xfa/fxfa/parser/cxfa_integer.h"
|
|
#include "xfa/fxfa/parser/cxfa_interactive.h"
|
|
#include "xfa/fxfa/parser/cxfa_issuers.h"
|
|
#include "xfa/fxfa/parser/cxfa_items.h"
|
|
#include "xfa/fxfa/parser/cxfa_jog.h"
|
|
#include "xfa/fxfa/parser/cxfa_keep.h"
|
|
#include "xfa/fxfa/parser/cxfa_keyusage.h"
|
|
#include "xfa/fxfa/parser/cxfa_labelprinter.h"
|
|
#include "xfa/fxfa/parser/cxfa_layout.h"
|
|
#include "xfa/fxfa/parser/cxfa_level.h"
|
|
#include "xfa/fxfa/parser/cxfa_line.h"
|
|
#include "xfa/fxfa/parser/cxfa_linear.h"
|
|
#include "xfa/fxfa/parser/cxfa_linearized.h"
|
|
#include "xfa/fxfa/parser/cxfa_locale.h"
|
|
#include "xfa/fxfa/parser/cxfa_localeset.h"
|
|
#include "xfa/fxfa/parser/cxfa_localevalue.h"
|
|
#include "xfa/fxfa/parser/cxfa_lockdocument.h"
|
|
#include "xfa/fxfa/parser/cxfa_log.h"
|
|
#include "xfa/fxfa/parser/cxfa_manifest.h"
|
|
#include "xfa/fxfa/parser/cxfa_map.h"
|
|
#include "xfa/fxfa/parser/cxfa_margin.h"
|
|
#include "xfa/fxfa/parser/cxfa_mdp.h"
|
|
#include "xfa/fxfa/parser/cxfa_measurement.h"
|
|
#include "xfa/fxfa/parser/cxfa_medium.h"
|
|
#include "xfa/fxfa/parser/cxfa_mediuminfo.h"
|
|
#include "xfa/fxfa/parser/cxfa_meridiem.h"
|
|
#include "xfa/fxfa/parser/cxfa_meridiemnames.h"
|
|
#include "xfa/fxfa/parser/cxfa_message.h"
|
|
#include "xfa/fxfa/parser/cxfa_messaging.h"
|
|
#include "xfa/fxfa/parser/cxfa_mode.h"
|
|
#include "xfa/fxfa/parser/cxfa_modifyannots.h"
|
|
#include "xfa/fxfa/parser/cxfa_month.h"
|
|
#include "xfa/fxfa/parser/cxfa_monthnames.h"
|
|
#include "xfa/fxfa/parser/cxfa_msgid.h"
|
|
#include "xfa/fxfa/parser/cxfa_nameattr.h"
|
|
#include "xfa/fxfa/parser/cxfa_neverembed.h"
|
|
#include "xfa/fxfa/parser/cxfa_nodeiteratortemplate.h"
|
|
#include "xfa/fxfa/parser/cxfa_numberofcopies.h"
|
|
#include "xfa/fxfa/parser/cxfa_numberpattern.h"
|
|
#include "xfa/fxfa/parser/cxfa_numberpatterns.h"
|
|
#include "xfa/fxfa/parser/cxfa_numbersymbol.h"
|
|
#include "xfa/fxfa/parser/cxfa_numbersymbols.h"
|
|
#include "xfa/fxfa/parser/cxfa_numericedit.h"
|
|
#include "xfa/fxfa/parser/cxfa_occur.h"
|
|
#include "xfa/fxfa/parser/cxfa_oid.h"
|
|
#include "xfa/fxfa/parser/cxfa_oids.h"
|
|
#include "xfa/fxfa/parser/cxfa_openaction.h"
|
|
#include "xfa/fxfa/parser/cxfa_operation.h"
|
|
#include "xfa/fxfa/parser/cxfa_output.h"
|
|
#include "xfa/fxfa/parser/cxfa_outputbin.h"
|
|
#include "xfa/fxfa/parser/cxfa_outputxsl.h"
|
|
#include "xfa/fxfa/parser/cxfa_overflow.h"
|
|
#include "xfa/fxfa/parser/cxfa_overprint.h"
|
|
#include "xfa/fxfa/parser/cxfa_packet.h"
|
|
#include "xfa/fxfa/parser/cxfa_packets.h"
|
|
#include "xfa/fxfa/parser/cxfa_pagearea.h"
|
|
#include "xfa/fxfa/parser/cxfa_pageoffset.h"
|
|
#include "xfa/fxfa/parser/cxfa_pagerange.h"
|
|
#include "xfa/fxfa/parser/cxfa_pageset.h"
|
|
#include "xfa/fxfa/parser/cxfa_pagination.h"
|
|
#include "xfa/fxfa/parser/cxfa_paginationoverride.h"
|
|
#include "xfa/fxfa/parser/cxfa_para.h"
|
|
#include "xfa/fxfa/parser/cxfa_part.h"
|
|
#include "xfa/fxfa/parser/cxfa_password.h"
|
|
#include "xfa/fxfa/parser/cxfa_passwordedit.h"
|
|
#include "xfa/fxfa/parser/cxfa_pattern.h"
|
|
#include "xfa/fxfa/parser/cxfa_pcl.h"
|
|
#include "xfa/fxfa/parser/cxfa_pdf.h"
|
|
#include "xfa/fxfa/parser/cxfa_pdfa.h"
|
|
#include "xfa/fxfa/parser/cxfa_permissions.h"
|
|
#include "xfa/fxfa/parser/cxfa_picktraybypdfsize.h"
|
|
#include "xfa/fxfa/parser/cxfa_picture.h"
|
|
#include "xfa/fxfa/parser/cxfa_plaintextmetadata.h"
|
|
#include "xfa/fxfa/parser/cxfa_presence.h"
|
|
#include "xfa/fxfa/parser/cxfa_present.h"
|
|
#include "xfa/fxfa/parser/cxfa_print.h"
|
|
#include "xfa/fxfa/parser/cxfa_printername.h"
|
|
#include "xfa/fxfa/parser/cxfa_printhighquality.h"
|
|
#include "xfa/fxfa/parser/cxfa_printscaling.h"
|
|
#include "xfa/fxfa/parser/cxfa_producer.h"
|
|
#include "xfa/fxfa/parser/cxfa_proto.h"
|
|
#include "xfa/fxfa/parser/cxfa_ps.h"
|
|
#include "xfa/fxfa/parser/cxfa_psmap.h"
|
|
#include "xfa/fxfa/parser/cxfa_query.h"
|
|
#include "xfa/fxfa/parser/cxfa_radial.h"
|
|
#include "xfa/fxfa/parser/cxfa_range.h"
|
|
#include "xfa/fxfa/parser/cxfa_reason.h"
|
|
#include "xfa/fxfa/parser/cxfa_reasons.h"
|
|
#include "xfa/fxfa/parser/cxfa_record.h"
|
|
#include "xfa/fxfa/parser/cxfa_recordset.h"
|
|
#include "xfa/fxfa/parser/cxfa_rectangle.h"
|
|
#include "xfa/fxfa/parser/cxfa_ref.h"
|
|
#include "xfa/fxfa/parser/cxfa_relevant.h"
|
|
#include "xfa/fxfa/parser/cxfa_rename.h"
|
|
#include "xfa/fxfa/parser/cxfa_renderpolicy.h"
|
|
#include "xfa/fxfa/parser/cxfa_rootelement.h"
|
|
#include "xfa/fxfa/parser/cxfa_runscripts.h"
|
|
#include "xfa/fxfa/parser/cxfa_script.h"
|
|
#include "xfa/fxfa/parser/cxfa_scriptmodel.h"
|
|
#include "xfa/fxfa/parser/cxfa_select.h"
|
|
#include "xfa/fxfa/parser/cxfa_setproperty.h"
|
|
#include "xfa/fxfa/parser/cxfa_severity.h"
|
|
#include "xfa/fxfa/parser/cxfa_sharptext.h"
|
|
#include "xfa/fxfa/parser/cxfa_sharpxhtml.h"
|
|
#include "xfa/fxfa/parser/cxfa_sharpxml.h"
|
|
#include "xfa/fxfa/parser/cxfa_signature.h"
|
|
#include "xfa/fxfa/parser/cxfa_signatureproperties.h"
|
|
#include "xfa/fxfa/parser/cxfa_signdata.h"
|
|
#include "xfa/fxfa/parser/cxfa_signing.h"
|
|
#include "xfa/fxfa/parser/cxfa_silentprint.h"
|
|
#include "xfa/fxfa/parser/cxfa_soapaction.h"
|
|
#include "xfa/fxfa/parser/cxfa_soapaddress.h"
|
|
#include "xfa/fxfa/parser/cxfa_solid.h"
|
|
#include "xfa/fxfa/parser/cxfa_source.h"
|
|
#include "xfa/fxfa/parser/cxfa_sourceset.h"
|
|
#include "xfa/fxfa/parser/cxfa_speak.h"
|
|
#include "xfa/fxfa/parser/cxfa_staple.h"
|
|
#include "xfa/fxfa/parser/cxfa_startnode.h"
|
|
#include "xfa/fxfa/parser/cxfa_startpage.h"
|
|
#include "xfa/fxfa/parser/cxfa_stipple.h"
|
|
#include "xfa/fxfa/parser/cxfa_stroke.h"
|
|
#include "xfa/fxfa/parser/cxfa_subform.h"
|
|
#include "xfa/fxfa/parser/cxfa_subformset.h"
|
|
#include "xfa/fxfa/parser/cxfa_subjectdn.h"
|
|
#include "xfa/fxfa/parser/cxfa_subjectdns.h"
|
|
#include "xfa/fxfa/parser/cxfa_submit.h"
|
|
#include "xfa/fxfa/parser/cxfa_submitformat.h"
|
|
#include "xfa/fxfa/parser/cxfa_submiturl.h"
|
|
#include "xfa/fxfa/parser/cxfa_subsetbelow.h"
|
|
#include "xfa/fxfa/parser/cxfa_suppressbanner.h"
|
|
#include "xfa/fxfa/parser/cxfa_tagged.h"
|
|
#include "xfa/fxfa/parser/cxfa_template.h"
|
|
#include "xfa/fxfa/parser/cxfa_templatecache.h"
|
|
#include "xfa/fxfa/parser/cxfa_text.h"
|
|
#include "xfa/fxfa/parser/cxfa_textedit.h"
|
|
#include "xfa/fxfa/parser/cxfa_threshold.h"
|
|
#include "xfa/fxfa/parser/cxfa_time.h"
|
|
#include "xfa/fxfa/parser/cxfa_timepattern.h"
|
|
#include "xfa/fxfa/parser/cxfa_timepatterns.h"
|
|
#include "xfa/fxfa/parser/cxfa_timestamp.h"
|
|
#include "xfa/fxfa/parser/cxfa_to.h"
|
|
#include "xfa/fxfa/parser/cxfa_tooltip.h"
|
|
#include "xfa/fxfa/parser/cxfa_trace.h"
|
|
#include "xfa/fxfa/parser/cxfa_transform.h"
|
|
#include "xfa/fxfa/parser/cxfa_traversal.h"
|
|
#include "xfa/fxfa/parser/cxfa_traverse.h"
|
|
#include "xfa/fxfa/parser/cxfa_traversestrategy_xfacontainernode.h"
|
|
#include "xfa/fxfa/parser/cxfa_traversestrategy_xfanode.h"
|
|
#include "xfa/fxfa/parser/cxfa_type.h"
|
|
#include "xfa/fxfa/parser/cxfa_typeface.h"
|
|
#include "xfa/fxfa/parser/cxfa_typefaces.h"
|
|
#include "xfa/fxfa/parser/cxfa_ui.h"
|
|
#include "xfa/fxfa/parser/cxfa_update.h"
|
|
#include "xfa/fxfa/parser/cxfa_uri.h"
|
|
#include "xfa/fxfa/parser/cxfa_user.h"
|
|
#include "xfa/fxfa/parser/cxfa_validate.h"
|
|
#include "xfa/fxfa/parser/cxfa_validateapprovalsignatures.h"
|
|
#include "xfa/fxfa/parser/cxfa_validationmessaging.h"
|
|
#include "xfa/fxfa/parser/cxfa_value.h"
|
|
#include "xfa/fxfa/parser/cxfa_variables.h"
|
|
#include "xfa/fxfa/parser/cxfa_version.h"
|
|
#include "xfa/fxfa/parser/cxfa_versioncontrol.h"
|
|
#include "xfa/fxfa/parser/cxfa_viewerpreferences.h"
|
|
#include "xfa/fxfa/parser/cxfa_webclient.h"
|
|
#include "xfa/fxfa/parser/cxfa_whitespace.h"
|
|
#include "xfa/fxfa/parser/cxfa_window.h"
|
|
#include "xfa/fxfa/parser/cxfa_wsdladdress.h"
|
|
#include "xfa/fxfa/parser/cxfa_wsdlconnection.h"
|
|
#include "xfa/fxfa/parser/cxfa_xdc.h"
|
|
#include "xfa/fxfa/parser/cxfa_xdp.h"
|
|
#include "xfa/fxfa/parser/cxfa_xfa.h"
|
|
#include "xfa/fxfa/parser/cxfa_xmlconnection.h"
|
|
#include "xfa/fxfa/parser/cxfa_xsdconnection.h"
|
|
#include "xfa/fxfa/parser/cxfa_xsl.h"
|
|
#include "xfa/fxfa/parser/cxfa_zpl.h"
|
|
#include "xfa/fxfa/parser/xfa_basic_data.h"
|
|
#include "xfa/fxfa/parser/xfa_utils.h"
|
|
|
|
class CXFA_FieldLayoutData;
|
|
class CXFA_ImageEditData;
|
|
class CXFA_ImageLayoutData;
|
|
class CXFA_TextEditData;
|
|
class CXFA_TextLayoutData;
|
|
|
|
namespace {
|
|
|
|
constexpr uint8_t kMaxExecuteRecursion = 2;
|
|
|
|
constexpr uint8_t g_inv_base64[128] = {
|
|
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 62, 255,
|
|
255, 255, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255,
|
|
255, 255, 255, 255, 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
|
|
10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
|
|
25, 255, 255, 255, 255, 255, 255, 26, 27, 28, 29, 30, 31, 32, 33,
|
|
34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
|
|
49, 50, 51, 255, 255, 255, 255, 255,
|
|
};
|
|
|
|
inline uint8_t GetInvBase64(uint8_t x) {
|
|
return (x & 128) == 0 ? g_inv_base64[x] : 255;
|
|
}
|
|
|
|
std::vector<uint8_t> XFA_RemoveBase64Whitespace(
|
|
pdfium::span<const uint8_t> spStr) {
|
|
std::vector<uint8_t> result;
|
|
result.reserve(spStr.size());
|
|
for (uint8_t ch : spStr) {
|
|
if (GetInvBase64(ch) != 255 || ch == '=')
|
|
result.push_back(ch);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
std::vector<uint8_t> XFA_Base64Decode(const ByteString& bsStr) {
|
|
std::vector<uint8_t> result;
|
|
if (bsStr.IsEmpty())
|
|
return result;
|
|
|
|
std::vector<uint8_t> buffer = XFA_RemoveBase64Whitespace(bsStr.raw_span());
|
|
result.reserve(3 * (buffer.size() / 4));
|
|
|
|
uint32_t dwLimb = 0;
|
|
for (size_t i = 0; i + 3 < buffer.size(); i += 4) {
|
|
if (buffer[i] == '=' || buffer[i + 1] == '=' || buffer[i + 2] == '=' ||
|
|
buffer[i + 3] == '=') {
|
|
if (buffer[i] == '=' || buffer[i + 1] == '=') {
|
|
break;
|
|
}
|
|
if (buffer[i + 2] == '=') {
|
|
dwLimb = ((uint32_t)g_inv_base64[buffer[i]] << 6) |
|
|
((uint32_t)g_inv_base64[buffer[i + 1]]);
|
|
result.push_back((uint8_t)(dwLimb >> 4) & 0xFF);
|
|
} else {
|
|
dwLimb = ((uint32_t)g_inv_base64[buffer[i]] << 12) |
|
|
((uint32_t)g_inv_base64[buffer[i + 1]] << 6) |
|
|
((uint32_t)g_inv_base64[buffer[i + 2]]);
|
|
result.push_back((uint8_t)(dwLimb >> 10) & 0xFF);
|
|
result.push_back((uint8_t)(dwLimb >> 2) & 0xFF);
|
|
}
|
|
} else {
|
|
dwLimb = ((uint32_t)g_inv_base64[buffer[i]] << 18) |
|
|
((uint32_t)g_inv_base64[buffer[i + 1]] << 12) |
|
|
((uint32_t)g_inv_base64[buffer[i + 2]] << 6) |
|
|
((uint32_t)g_inv_base64[buffer[i + 3]]);
|
|
result.push_back((uint8_t)(dwLimb >> 16) & 0xff);
|
|
result.push_back((uint8_t)(dwLimb >> 8) & 0xff);
|
|
result.push_back((uint8_t)(dwLimb)&0xff);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
FXCODEC_IMAGE_TYPE XFA_GetImageType(const WideString& wsType) {
|
|
WideString wsContentType(wsType);
|
|
if (wsContentType.EqualsASCIINoCase("image/jpg"))
|
|
return FXCODEC_IMAGE_JPG;
|
|
|
|
#ifdef PDF_ENABLE_XFA_BMP
|
|
if (wsContentType.EqualsASCIINoCase("image/bmp"))
|
|
return FXCODEC_IMAGE_BMP;
|
|
#endif // PDF_ENABLE_XFA_BMP
|
|
|
|
#ifdef PDF_ENABLE_XFA_GIF
|
|
if (wsContentType.EqualsASCIINoCase("image/gif"))
|
|
return FXCODEC_IMAGE_GIF;
|
|
#endif // PDF_ENABLE_XFA_GIF
|
|
|
|
#ifdef PDF_ENABLE_XFA_PNG
|
|
if (wsContentType.EqualsASCIINoCase("image/png"))
|
|
return FXCODEC_IMAGE_PNG;
|
|
#endif // PDF_ENABLE_XFA_PNG
|
|
|
|
#ifdef PDF_ENABLE_XFA_TIFF
|
|
if (wsContentType.EqualsASCII("image/tif"))
|
|
return FXCODEC_IMAGE_TIFF;
|
|
#endif // PDF_ENABLE_XFA_TIFF
|
|
|
|
return FXCODEC_IMAGE_UNKNOWN;
|
|
}
|
|
|
|
RetainPtr<CFX_DIBitmap> XFA_LoadImageData(CXFA_FFDoc* pDoc,
|
|
CXFA_Image* pImage,
|
|
bool& bNameImage,
|
|
int32_t& iImageXDpi,
|
|
int32_t& iImageYDpi) {
|
|
WideString wsHref = pImage->GetHref();
|
|
WideString wsImage = pImage->GetContent();
|
|
if (wsHref.IsEmpty() && wsImage.IsEmpty())
|
|
return nullptr;
|
|
|
|
FXCODEC_IMAGE_TYPE type = XFA_GetImageType(pImage->GetContentType());
|
|
ByteString bsData; // Must outlive |pImageFileRead|.
|
|
std::vector<uint8_t> buffer; // Must outlive |pImageFileRead|.
|
|
RetainPtr<IFX_SeekableReadStream> pImageFileRead;
|
|
if (wsImage.GetLength() > 0) {
|
|
XFA_AttributeValue iEncoding = pImage->GetTransferEncoding();
|
|
if (iEncoding == XFA_AttributeValue::Base64) {
|
|
bsData = wsImage.ToUTF8();
|
|
buffer = XFA_Base64Decode(bsData);
|
|
if (!buffer.empty())
|
|
pImageFileRead = pdfium::MakeRetain<CFX_ReadOnlyMemoryStream>(buffer);
|
|
} else {
|
|
bsData = wsImage.ToDefANSI();
|
|
pImageFileRead =
|
|
pdfium::MakeRetain<CFX_ReadOnlyMemoryStream>(bsData.raw_span());
|
|
}
|
|
} else {
|
|
WideString wsURL = wsHref;
|
|
if (!(wsURL.First(7).EqualsASCII("http://") ||
|
|
wsURL.First(6).EqualsASCII("ftp://"))) {
|
|
RetainPtr<CFX_DIBitmap> pBitmap =
|
|
pDoc->GetPDFNamedImage(wsURL.AsStringView(), iImageXDpi, iImageYDpi);
|
|
if (pBitmap) {
|
|
bNameImage = true;
|
|
return pBitmap;
|
|
}
|
|
}
|
|
pImageFileRead = pDoc->GetDocEnvironment()->OpenLinkedFile(pDoc, wsURL);
|
|
}
|
|
if (!pImageFileRead)
|
|
return nullptr;
|
|
|
|
bNameImage = false;
|
|
RetainPtr<CFX_DIBitmap> pBitmap =
|
|
XFA_LoadImageFromBuffer(pImageFileRead, type, iImageXDpi, iImageYDpi);
|
|
return pBitmap;
|
|
}
|
|
|
|
bool SplitDateTime(const WideString& wsDateTime,
|
|
WideString& wsDate,
|
|
WideString& wsTime) {
|
|
wsDate.clear();
|
|
wsTime.clear();
|
|
if (wsDateTime.IsEmpty())
|
|
return false;
|
|
|
|
auto nSplitIndex = wsDateTime.Find('T');
|
|
if (!nSplitIndex.has_value())
|
|
nSplitIndex = wsDateTime.Find(' ');
|
|
if (!nSplitIndex.has_value())
|
|
return false;
|
|
|
|
wsDate = wsDateTime.First(nSplitIndex.value());
|
|
if (!wsDate.IsEmpty()) {
|
|
if (!std::any_of(wsDate.begin(), wsDate.end(),
|
|
[](wchar_t c) { return FXSYS_IsDecimalDigit(c); })) {
|
|
return false;
|
|
}
|
|
}
|
|
wsTime = wsDateTime.Last(wsDateTime.GetLength() - nSplitIndex.value() - 1);
|
|
if (!wsTime.IsEmpty()) {
|
|
if (!std::any_of(wsTime.begin(), wsTime.end(),
|
|
[](wchar_t c) { return FXSYS_IsDecimalDigit(c); })) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
std::vector<CXFA_Node*> NodesSortedByDocumentIdx(
|
|
const std::set<CXFA_Node*>& rgNodeSet) {
|
|
if (rgNodeSet.empty())
|
|
return std::vector<CXFA_Node*>();
|
|
|
|
std::vector<CXFA_Node*> rgNodeArray;
|
|
CXFA_Node* pCommonParent = (*rgNodeSet.begin())->GetParent();
|
|
for (CXFA_Node* pNode = pCommonParent->GetFirstChild(); pNode;
|
|
pNode = pNode->GetNextSibling()) {
|
|
if (pdfium::ContainsValue(rgNodeSet, pNode))
|
|
rgNodeArray.push_back(pNode);
|
|
}
|
|
return rgNodeArray;
|
|
}
|
|
|
|
using CXFA_NodeSetPair = std::pair<std::set<CXFA_Node*>, std::set<CXFA_Node*>>;
|
|
using CXFA_NodeSetPairMap =
|
|
std::map<uint32_t, std::unique_ptr<CXFA_NodeSetPair>>;
|
|
using CXFA_NodeSetPairMapMap =
|
|
std::map<CXFA_Node*, std::unique_ptr<CXFA_NodeSetPairMap>>;
|
|
|
|
CXFA_NodeSetPair* NodeSetPairForNode(CXFA_Node* pNode,
|
|
CXFA_NodeSetPairMapMap* pMap) {
|
|
CXFA_Node* pParentNode = pNode->GetParent();
|
|
uint32_t dwNameHash = pNode->GetNameHash();
|
|
if (!pParentNode || !dwNameHash)
|
|
return nullptr;
|
|
|
|
if (!(*pMap)[pParentNode])
|
|
(*pMap)[pParentNode] = pdfium::MakeUnique<CXFA_NodeSetPairMap>();
|
|
|
|
CXFA_NodeSetPairMap* pNodeSetPairMap = (*pMap)[pParentNode].get();
|
|
if (!(*pNodeSetPairMap)[dwNameHash])
|
|
(*pNodeSetPairMap)[dwNameHash] = pdfium::MakeUnique<CXFA_NodeSetPair>();
|
|
|
|
return (*pNodeSetPairMap)[dwNameHash].get();
|
|
}
|
|
|
|
void ReorderDataNodes(const std::set<CXFA_Node*>& sSet1,
|
|
const std::set<CXFA_Node*>& sSet2,
|
|
bool bInsertBefore) {
|
|
CXFA_NodeSetPairMapMap rgMap;
|
|
for (CXFA_Node* pNode : sSet1) {
|
|
CXFA_NodeSetPair* pNodeSetPair = NodeSetPairForNode(pNode, &rgMap);
|
|
if (pNodeSetPair)
|
|
pNodeSetPair->first.insert(pNode);
|
|
}
|
|
for (CXFA_Node* pNode : sSet2) {
|
|
CXFA_NodeSetPair* pNodeSetPair = NodeSetPairForNode(pNode, &rgMap);
|
|
if (pNodeSetPair) {
|
|
if (pdfium::ContainsValue(pNodeSetPair->first, pNode))
|
|
pNodeSetPair->first.erase(pNode);
|
|
else
|
|
pNodeSetPair->second.insert(pNode);
|
|
}
|
|
}
|
|
for (const auto& iter1 : rgMap) {
|
|
CXFA_NodeSetPairMap* pNodeSetPairMap = iter1.second.get();
|
|
if (!pNodeSetPairMap)
|
|
continue;
|
|
|
|
for (const auto& iter2 : *pNodeSetPairMap) {
|
|
CXFA_NodeSetPair* pNodeSetPair = iter2.second.get();
|
|
if (!pNodeSetPair)
|
|
continue;
|
|
if (!pNodeSetPair->first.empty() && !pNodeSetPair->second.empty()) {
|
|
std::vector<CXFA_Node*> rgNodeArray1 =
|
|
NodesSortedByDocumentIdx(pNodeSetPair->first);
|
|
std::vector<CXFA_Node*> rgNodeArray2 =
|
|
NodesSortedByDocumentIdx(pNodeSetPair->second);
|
|
CXFA_Node* pParentNode = nullptr;
|
|
CXFA_Node* pBeforeNode = nullptr;
|
|
if (bInsertBefore) {
|
|
pBeforeNode = rgNodeArray2.front();
|
|
pParentNode = pBeforeNode->GetParent();
|
|
} else {
|
|
CXFA_Node* pLastNode = rgNodeArray2.back();
|
|
pParentNode = pLastNode->GetParent();
|
|
pBeforeNode = pLastNode->GetNextSibling();
|
|
}
|
|
for (auto* pCurNode : rgNodeArray1) {
|
|
pParentNode->RemoveChildAndNotify(pCurNode, true);
|
|
pParentNode->InsertChildAndNotify(pCurNode, pBeforeNode);
|
|
}
|
|
}
|
|
}
|
|
pNodeSetPairMap->clear();
|
|
}
|
|
}
|
|
|
|
float GetEdgeThickness(const std::vector<CXFA_Stroke*>& strokes,
|
|
bool b3DStyle,
|
|
int32_t nIndex) {
|
|
float fThickness = 0.0f;
|
|
CXFA_Stroke* stroke = strokes[nIndex * 2 + 1];
|
|
if (stroke->IsVisible()) {
|
|
if (nIndex == 0)
|
|
fThickness += 2.5f;
|
|
|
|
fThickness += stroke->GetThickness() * (b3DStyle ? 4 : 2);
|
|
}
|
|
return fThickness;
|
|
}
|
|
|
|
WideString FormatNumStr(const WideString& wsValue, LocaleIface* pLocale) {
|
|
if (wsValue.IsEmpty())
|
|
return WideString();
|
|
|
|
WideString wsSrcNum = wsValue;
|
|
WideString wsGroupSymbol = pLocale->GetGroupingSymbol();
|
|
bool bNeg = false;
|
|
if (wsSrcNum[0] == '-') {
|
|
bNeg = true;
|
|
wsSrcNum.Delete(0, 1);
|
|
}
|
|
|
|
auto dot_index = wsSrcNum.Find('.');
|
|
dot_index = !dot_index.has_value() ? wsSrcNum.GetLength() : dot_index;
|
|
|
|
if (dot_index.value() < 1)
|
|
return WideString();
|
|
|
|
size_t nPos = dot_index.value() % 3;
|
|
WideString wsOutput;
|
|
for (size_t i = 0; i < dot_index.value(); i++) {
|
|
if (i % 3 == nPos && i != 0)
|
|
wsOutput += wsGroupSymbol;
|
|
|
|
wsOutput += wsSrcNum[i];
|
|
}
|
|
if (dot_index.value() < wsSrcNum.GetLength()) {
|
|
wsOutput += pLocale->GetDecimalSymbol();
|
|
wsOutput += wsSrcNum.Last(wsSrcNum.GetLength() - dot_index.value() - 1);
|
|
}
|
|
if (bNeg)
|
|
return pLocale->GetMinusSymbol() + wsOutput;
|
|
|
|
return wsOutput;
|
|
}
|
|
|
|
CXFA_Node* FindFirstSiblingNamedInList(CXFA_Node* parent,
|
|
uint32_t dwNameHash,
|
|
uint32_t dwFilter);
|
|
CXFA_Node* FindFirstSiblingOfClassInList(CXFA_Node* parent,
|
|
XFA_Element element,
|
|
uint32_t dwFilter);
|
|
|
|
CXFA_Node* FindFirstSiblingNamed(CXFA_Node* parent, uint32_t dwNameHash) {
|
|
CXFA_Node* result = FindFirstSiblingNamedInList(parent, dwNameHash,
|
|
XFA_NODEFILTER_Properties);
|
|
if (result)
|
|
return result;
|
|
|
|
return FindFirstSiblingNamedInList(parent, dwNameHash,
|
|
XFA_NODEFILTER_Children);
|
|
}
|
|
|
|
CXFA_Node* FindFirstSiblingNamedInList(CXFA_Node* parent,
|
|
uint32_t dwNameHash,
|
|
uint32_t dwFilter) {
|
|
for (CXFA_Node* child : parent->GetNodeListWithFilter(dwFilter)) {
|
|
if (child->GetNameHash() == dwNameHash)
|
|
return child;
|
|
|
|
CXFA_Node* result = FindFirstSiblingNamed(child, dwNameHash);
|
|
if (result)
|
|
return result;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
CXFA_Node* FindFirstSiblingOfClass(CXFA_Node* parent, XFA_Element element) {
|
|
CXFA_Node* result =
|
|
FindFirstSiblingOfClassInList(parent, element, XFA_NODEFILTER_Properties);
|
|
if (result)
|
|
return result;
|
|
|
|
return FindFirstSiblingOfClassInList(parent, element,
|
|
XFA_NODEFILTER_Children);
|
|
}
|
|
|
|
CXFA_Node* FindFirstSiblingOfClassInList(CXFA_Node* parent,
|
|
XFA_Element element,
|
|
uint32_t dwFilter) {
|
|
for (CXFA_Node* child : parent->GetNodeListWithFilter(dwFilter)) {
|
|
if (child->GetElementType() == element)
|
|
return child;
|
|
|
|
CXFA_Node* result = FindFirstSiblingOfClass(child, element);
|
|
if (result)
|
|
return result;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
WideString GetNameExpressionSinglePath(CXFA_Node* pNode) {
|
|
const bool bIsProperty = pNode->IsProperty();
|
|
const bool bIsClassIndex =
|
|
pNode->IsUnnamed() ||
|
|
(bIsProperty && pNode->GetElementType() != XFA_Element::PageSet);
|
|
const wchar_t* pszFormat;
|
|
WideString ws;
|
|
if (bIsClassIndex) {
|
|
pszFormat = L"#%ls[%zu]";
|
|
ws = WideString::FromASCII(pNode->GetClassName());
|
|
} else {
|
|
pszFormat = L"%ls[%zu]";
|
|
ws = pNode->JSObject()->GetCData(XFA_Attribute::Name);
|
|
ws.Replace(L".", L"\\.");
|
|
}
|
|
|
|
return WideString::Format(pszFormat, ws.c_str(),
|
|
pNode->GetIndex(bIsProperty, bIsClassIndex));
|
|
}
|
|
|
|
void TraverseSiblings(CXFA_Node* parent,
|
|
uint32_t dwNameHash,
|
|
std::vector<CXFA_Node*>* pSiblings,
|
|
bool bIsClassName,
|
|
bool bIsFindProperty) {
|
|
ASSERT(parent);
|
|
ASSERT(pSiblings);
|
|
|
|
if (bIsFindProperty) {
|
|
for (CXFA_Node* child :
|
|
parent->GetNodeListWithFilter(XFA_NODEFILTER_Properties)) {
|
|
if (bIsClassName) {
|
|
if (child->GetClassHashCode() == dwNameHash)
|
|
pSiblings->push_back(child);
|
|
} else {
|
|
if (child->GetNameHash() == dwNameHash) {
|
|
if (child->GetElementType() != XFA_Element::PageSet &&
|
|
child->GetElementType() != XFA_Element::Extras &&
|
|
child->GetElementType() != XFA_Element::Items) {
|
|
pSiblings->push_back(child);
|
|
}
|
|
}
|
|
}
|
|
if (child->IsUnnamed() &&
|
|
child->GetElementType() == XFA_Element::PageSet) {
|
|
TraverseSiblings(child, dwNameHash, pSiblings, bIsClassName, false);
|
|
}
|
|
}
|
|
if (!pSiblings->empty())
|
|
return;
|
|
}
|
|
for (CXFA_Node* child :
|
|
parent->GetNodeListWithFilter(XFA_NODEFILTER_Children)) {
|
|
if (child->GetElementType() == XFA_Element::Variables)
|
|
continue;
|
|
|
|
if (bIsClassName) {
|
|
if (child->GetClassHashCode() == dwNameHash)
|
|
pSiblings->push_back(child);
|
|
} else {
|
|
if (child->GetNameHash() == dwNameHash)
|
|
pSiblings->push_back(child);
|
|
}
|
|
|
|
if (child->IsTransparent() &&
|
|
child->GetElementType() != XFA_Element::PageSet) {
|
|
TraverseSiblings(child, dwNameHash, pSiblings, bIsClassName, false);
|
|
}
|
|
}
|
|
}
|
|
|
|
} // namespace
|
|
|
|
class CXFA_WidgetLayoutData {
|
|
public:
|
|
CXFA_WidgetLayoutData() = default;
|
|
virtual ~CXFA_WidgetLayoutData() = default;
|
|
|
|
virtual CXFA_FieldLayoutData* AsFieldLayoutData() { return nullptr; }
|
|
virtual CXFA_ImageLayoutData* AsImageLayoutData() { return nullptr; }
|
|
virtual CXFA_TextLayoutData* AsTextLayoutData() { return nullptr; }
|
|
|
|
float m_fWidgetHeight = -1.0f;
|
|
};
|
|
|
|
class CXFA_TextLayoutData final : public CXFA_WidgetLayoutData {
|
|
public:
|
|
CXFA_TextLayoutData() = default;
|
|
~CXFA_TextLayoutData() override = default;
|
|
|
|
CXFA_TextLayoutData* AsTextLayoutData() override { return this; }
|
|
|
|
CXFA_TextLayout* GetTextLayout() const { return m_pTextLayout.get(); }
|
|
CXFA_TextProvider* GetTextProvider() const { return m_pTextProvider.get(); }
|
|
|
|
void LoadText(CXFA_FFDoc* doc, CXFA_Node* pNode) {
|
|
if (m_pTextLayout)
|
|
return;
|
|
|
|
m_pTextProvider =
|
|
pdfium::MakeUnique<CXFA_TextProvider>(pNode, XFA_TEXTPROVIDERTYPE_Text);
|
|
m_pTextLayout =
|
|
pdfium::MakeUnique<CXFA_TextLayout>(doc, m_pTextProvider.get());
|
|
}
|
|
|
|
private:
|
|
std::unique_ptr<CXFA_TextLayout> m_pTextLayout;
|
|
std::unique_ptr<CXFA_TextProvider> m_pTextProvider;
|
|
};
|
|
|
|
class CXFA_ImageLayoutData final : public CXFA_WidgetLayoutData {
|
|
public:
|
|
CXFA_ImageLayoutData() = default;
|
|
~CXFA_ImageLayoutData() override = default;
|
|
|
|
CXFA_ImageLayoutData* AsImageLayoutData() override { return this; }
|
|
|
|
bool LoadImageData(CXFA_FFDoc* doc, CXFA_Node* pNode) {
|
|
if (m_pDIBitmap)
|
|
return true;
|
|
|
|
CXFA_Value* value = pNode->GetFormValueIfExists();
|
|
if (!value)
|
|
return false;
|
|
|
|
CXFA_Image* image = value->GetImageIfExists();
|
|
if (!image)
|
|
return false;
|
|
|
|
pNode->SetImageImage(XFA_LoadImageData(doc, image, m_bNamedImage,
|
|
m_iImageXDpi, m_iImageYDpi));
|
|
return !!m_pDIBitmap;
|
|
}
|
|
|
|
bool m_bNamedImage = false;
|
|
int32_t m_iImageXDpi = 0;
|
|
int32_t m_iImageYDpi = 0;
|
|
RetainPtr<CFX_DIBitmap> m_pDIBitmap;
|
|
};
|
|
|
|
class CXFA_FieldLayoutData : public CXFA_WidgetLayoutData {
|
|
public:
|
|
CXFA_FieldLayoutData() = default;
|
|
~CXFA_FieldLayoutData() override = default;
|
|
|
|
CXFA_FieldLayoutData* AsFieldLayoutData() override { return this; }
|
|
|
|
virtual CXFA_ImageEditData* AsImageEditData() { return nullptr; }
|
|
virtual CXFA_TextEditData* AsTextEditData() { return nullptr; }
|
|
|
|
bool LoadCaption(CXFA_FFDoc* doc, CXFA_Node* pNode) {
|
|
if (m_pCapTextLayout)
|
|
return true;
|
|
CXFA_Caption* caption = pNode->GetCaptionIfExists();
|
|
if (!caption || caption->IsHidden())
|
|
return false;
|
|
|
|
m_pCapTextProvider = pdfium::MakeUnique<CXFA_TextProvider>(
|
|
pNode, XFA_TEXTPROVIDERTYPE_Caption);
|
|
m_pCapTextLayout =
|
|
pdfium::MakeUnique<CXFA_TextLayout>(doc, m_pCapTextProvider.get());
|
|
return true;
|
|
}
|
|
|
|
std::unique_ptr<CXFA_TextLayout> m_pCapTextLayout;
|
|
std::unique_ptr<CXFA_TextProvider> m_pCapTextProvider;
|
|
std::unique_ptr<CFDE_TextOut> m_pTextOut;
|
|
std::vector<float> m_FieldSplitArray;
|
|
};
|
|
|
|
class CXFA_TextEditData final : public CXFA_FieldLayoutData {
|
|
public:
|
|
CXFA_TextEditData() = default;
|
|
~CXFA_TextEditData() override = default;
|
|
|
|
CXFA_TextEditData* AsTextEditData() override { return this; }
|
|
};
|
|
|
|
class CXFA_ImageEditData final : public CXFA_FieldLayoutData {
|
|
public:
|
|
CXFA_ImageEditData() = default;
|
|
~CXFA_ImageEditData() override = default;
|
|
|
|
CXFA_ImageEditData* AsImageEditData() override { return this; }
|
|
|
|
bool LoadImageData(CXFA_FFDoc* doc, CXFA_Node* pNode) {
|
|
if (m_pDIBitmap)
|
|
return true;
|
|
|
|
CXFA_Value* value = pNode->GetFormValueIfExists();
|
|
if (!value)
|
|
return false;
|
|
|
|
CXFA_Image* image = value->GetImageIfExists();
|
|
if (!image)
|
|
return false;
|
|
|
|
pNode->SetImageEditImage(XFA_LoadImageData(doc, image, m_bNamedImage,
|
|
m_iImageXDpi, m_iImageYDpi));
|
|
return !!m_pDIBitmap;
|
|
}
|
|
|
|
bool m_bNamedImage = false;
|
|
int32_t m_iImageXDpi = 0;
|
|
int32_t m_iImageYDpi = 0;
|
|
RetainPtr<CFX_DIBitmap> m_pDIBitmap;
|
|
};
|
|
|
|
CXFA_Node::CXFA_Node(CXFA_Document* pDoc,
|
|
XFA_PacketType ePacket,
|
|
uint32_t validPackets,
|
|
XFA_ObjectType oType,
|
|
XFA_Element eType,
|
|
pdfium::span<const PropertyData> properties,
|
|
pdfium::span<const AttributeData> attributes,
|
|
std::unique_ptr<CJX_Object> js_object)
|
|
: CXFA_Object(pDoc, oType, eType, std::move(js_object)),
|
|
m_Properties(properties),
|
|
m_Attributes(attributes),
|
|
m_ValidPackets(validPackets),
|
|
m_ePacket(ePacket) {
|
|
ASSERT(m_pDocument);
|
|
}
|
|
|
|
CXFA_Node::~CXFA_Node() = default;
|
|
|
|
CXFA_Node* CXFA_Node::Clone(bool bRecursive) {
|
|
CXFA_Node* pClone = m_pDocument->CreateNode(m_ePacket, m_elementType);
|
|
if (!pClone)
|
|
return nullptr;
|
|
|
|
JSObject()->MergeAllData(pClone);
|
|
pClone->UpdateNameHash();
|
|
if (IsNeedSavingXMLNode()) {
|
|
CFX_XMLNode* pCloneXML;
|
|
if (IsAttributeInXML()) {
|
|
WideString wsName = JSObject()
|
|
->TryAttribute(XFA_Attribute::Name, false)
|
|
.value_or(WideString());
|
|
auto* pCloneXMLElement =
|
|
GetXMLDocument()->CreateNode<CFX_XMLElement>(wsName);
|
|
|
|
WideString wsValue = JSObject()->GetCData(XFA_Attribute::Value);
|
|
if (!wsValue.IsEmpty()) {
|
|
auto* text = GetXMLDocument()->CreateNode<CFX_XMLText>(wsValue);
|
|
pCloneXMLElement->AppendLastChild(text);
|
|
}
|
|
|
|
pCloneXML = pCloneXMLElement;
|
|
pClone->JSObject()->SetEnum(XFA_Attribute::Contains,
|
|
XFA_AttributeValue::Unknown, false);
|
|
} else {
|
|
pCloneXML = xml_node_->Clone(GetXMLDocument());
|
|
}
|
|
pClone->SetXMLMappingNode(pCloneXML);
|
|
}
|
|
if (bRecursive) {
|
|
for (CXFA_Node* pChild = GetFirstChild(); pChild;
|
|
pChild = pChild->GetNextSibling()) {
|
|
pClone->InsertChildAndNotify(pChild->Clone(bRecursive), nullptr);
|
|
}
|
|
}
|
|
pClone->SetFlagAndNotify(XFA_NodeFlag_Initialized);
|
|
pClone->SetBindingNode(nullptr);
|
|
return pClone;
|
|
}
|
|
|
|
CXFA_Node* CXFA_Node::GetNextContainerSibling() const {
|
|
for (auto* pNode = GetNextSibling(); pNode; pNode = pNode->GetNextSibling()) {
|
|
if (pNode->GetObjectType() == XFA_ObjectType::ContainerNode)
|
|
return pNode;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
CXFA_Node* CXFA_Node::GetPrevContainerSibling() const {
|
|
for (auto* pNode = GetPrevSibling(); pNode; pNode = pNode->GetPrevSibling()) {
|
|
if (pNode->GetObjectType() == XFA_ObjectType::ContainerNode)
|
|
return pNode;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
CXFA_Node* CXFA_Node::GetFirstContainerChild() const {
|
|
for (auto* pNode = GetFirstChild(); pNode; pNode = pNode->GetNextSibling()) {
|
|
if (pNode->GetObjectType() == XFA_ObjectType::ContainerNode)
|
|
return pNode;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
CXFA_Node* CXFA_Node::GetContainerParent() const {
|
|
for (auto* pNode = GetParent(); pNode; pNode = pNode->GetParent()) {
|
|
if (pNode->GetObjectType() == XFA_ObjectType::ContainerNode)
|
|
return pNode;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
bool CXFA_Node::IsValidInPacket(XFA_PacketType packet) const {
|
|
return !!(m_ValidPackets & (1 << static_cast<uint8_t>(packet)));
|
|
}
|
|
|
|
const CXFA_Node::PropertyData* CXFA_Node::GetPropertyData(
|
|
XFA_Element property) const {
|
|
ASSERT(property != XFA_Element::Unknown);
|
|
for (const auto& prop : m_Properties) {
|
|
if (prop.property == property)
|
|
return ∝
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
bool CXFA_Node::HasProperty(XFA_Element property) const {
|
|
return !!GetPropertyData(property);
|
|
}
|
|
|
|
bool CXFA_Node::HasPropertyFlags(XFA_Element property, uint8_t flags) const {
|
|
const PropertyData* data = GetPropertyData(property);
|
|
return data && !!(data->flags & flags);
|
|
}
|
|
|
|
uint8_t CXFA_Node::PropertyOccuranceCount(XFA_Element property) const {
|
|
const PropertyData* data = GetPropertyData(property);
|
|
return data ? data->occurance_count : 0;
|
|
}
|
|
|
|
std::pair<CXFA_Node*, int32_t> CXFA_Node::GetProperty(
|
|
int32_t index,
|
|
XFA_Element eProperty) const {
|
|
if (index < 0 || index >= PropertyOccuranceCount(eProperty))
|
|
return {nullptr, 0};
|
|
|
|
int32_t iCount = 0;
|
|
for (CXFA_Node* pNode = GetFirstChild(); pNode;
|
|
pNode = pNode->GetNextSibling()) {
|
|
if (pNode->GetElementType() == eProperty) {
|
|
iCount++;
|
|
if (iCount > index)
|
|
return {pNode, iCount};
|
|
}
|
|
}
|
|
return {nullptr, iCount};
|
|
}
|
|
|
|
CXFA_Node* CXFA_Node::GetOrCreateProperty(int32_t index,
|
|
XFA_Element eProperty) {
|
|
if (index < 0 || index >= PropertyOccuranceCount(eProperty))
|
|
return nullptr;
|
|
|
|
int32_t iCount = 0;
|
|
CXFA_Node* node;
|
|
std::tie(node, iCount) = GetProperty(index, eProperty);
|
|
if (node)
|
|
return node;
|
|
|
|
if (HasPropertyFlags(eProperty, XFA_PROPERTYFLAG_OneOf)) {
|
|
for (CXFA_Node* pNode = GetFirstChild(); pNode;
|
|
pNode = pNode->GetNextSibling()) {
|
|
if (HasPropertyFlags(pNode->GetElementType(), XFA_PROPERTYFLAG_OneOf)) {
|
|
return nullptr;
|
|
}
|
|
}
|
|
}
|
|
|
|
CXFA_Node* pNewNode = nullptr;
|
|
for (; iCount <= index; ++iCount) {
|
|
pNewNode = GetDocument()->CreateNode(GetPacketType(), eProperty);
|
|
if (!pNewNode)
|
|
return nullptr;
|
|
|
|
InsertChildAndNotify(pNewNode, nullptr);
|
|
pNewNode->SetFlagAndNotify(XFA_NodeFlag_Initialized);
|
|
}
|
|
return pNewNode;
|
|
}
|
|
|
|
Optional<XFA_Element> CXFA_Node::GetFirstPropertyWithFlag(uint8_t flag) const {
|
|
for (const auto& prop : m_Properties) {
|
|
if (prop.flags & flag)
|
|
return prop.property;
|
|
}
|
|
return {};
|
|
}
|
|
|
|
const CXFA_Node::AttributeData* CXFA_Node::GetAttributeData(
|
|
XFA_Attribute attr) const {
|
|
ASSERT(attr != XFA_Attribute::Unknown);
|
|
for (const auto& cur_attr : m_Attributes) {
|
|
if (cur_attr.attribute == attr)
|
|
return &cur_attr;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
bool CXFA_Node::HasAttribute(XFA_Attribute attr) const {
|
|
return !!GetAttributeData(attr);
|
|
}
|
|
|
|
XFA_Attribute CXFA_Node::GetAttribute(size_t i) const {
|
|
return i < m_Attributes.size() ? m_Attributes[i].attribute
|
|
: XFA_Attribute::Unknown;
|
|
}
|
|
|
|
XFA_AttributeType CXFA_Node::GetAttributeType(XFA_Attribute type) const {
|
|
const AttributeData* data = GetAttributeData(type);
|
|
return data ? data->type : XFA_AttributeType::CData;
|
|
}
|
|
|
|
std::vector<CXFA_Node*> CXFA_Node::GetNodeListForType(XFA_Element eTypeFilter) {
|
|
std::vector<CXFA_Node*> nodes;
|
|
for (CXFA_Node* pChild = GetFirstChild(); pChild;
|
|
pChild = pChild->GetNextSibling()) {
|
|
if (pChild->GetElementType() == eTypeFilter)
|
|
nodes.push_back(pChild);
|
|
}
|
|
return nodes;
|
|
}
|
|
|
|
std::vector<CXFA_Node*> CXFA_Node::GetNodeListWithFilter(
|
|
uint32_t dwTypeFilter) {
|
|
std::vector<CXFA_Node*> nodes;
|
|
if (dwTypeFilter == (XFA_NODEFILTER_Children | XFA_NODEFILTER_Properties)) {
|
|
for (CXFA_Node* pChild = GetFirstChild(); pChild;
|
|
pChild = pChild->GetNextSibling())
|
|
nodes.push_back(pChild);
|
|
return nodes;
|
|
}
|
|
|
|
if (dwTypeFilter == 0)
|
|
return nodes;
|
|
|
|
bool bFilterChildren = !!(dwTypeFilter & XFA_NODEFILTER_Children);
|
|
bool bFilterProperties = !!(dwTypeFilter & XFA_NODEFILTER_Properties);
|
|
bool bFilterOneOfProperties = !!(dwTypeFilter & XFA_NODEFILTER_OneOfProperty);
|
|
for (CXFA_Node* pChild = GetFirstChild(); pChild;
|
|
pChild = pChild->GetNextSibling()) {
|
|
if (HasProperty(pChild->GetElementType())) {
|
|
if (bFilterProperties) {
|
|
nodes.push_back(pChild);
|
|
} else if (bFilterOneOfProperties &&
|
|
HasPropertyFlags(pChild->GetElementType(),
|
|
XFA_PROPERTYFLAG_OneOf)) {
|
|
nodes.push_back(pChild);
|
|
} else if (bFilterChildren &&
|
|
(pChild->GetElementType() == XFA_Element::Variables ||
|
|
pChild->GetElementType() == XFA_Element::PageSet)) {
|
|
nodes.push_back(pChild);
|
|
}
|
|
} else if (bFilterChildren) {
|
|
nodes.push_back(pChild);
|
|
}
|
|
}
|
|
|
|
if (!bFilterOneOfProperties || !nodes.empty())
|
|
return nodes;
|
|
|
|
Optional<XFA_Element> property =
|
|
GetFirstPropertyWithFlag(XFA_PROPERTYFLAG_DefaultOneOf);
|
|
if (!property.has_value())
|
|
return nodes;
|
|
|
|
CXFA_Node* pNewNode =
|
|
m_pDocument->CreateNode(GetPacketType(), property.value());
|
|
if (pNewNode) {
|
|
InsertChildAndNotify(pNewNode, nullptr);
|
|
pNewNode->SetFlagAndNotify(XFA_NodeFlag_Initialized);
|
|
nodes.push_back(pNewNode);
|
|
}
|
|
return nodes;
|
|
}
|
|
|
|
CXFA_Node* CXFA_Node::CreateSamePacketNode(XFA_Element eType) {
|
|
CXFA_Node* pNode = m_pDocument->CreateNode(m_ePacket, eType);
|
|
if (!pNode)
|
|
return nullptr;
|
|
|
|
pNode->SetFlagAndNotify(XFA_NodeFlag_Initialized);
|
|
return pNode;
|
|
}
|
|
|
|
CXFA_Node* CXFA_Node::CloneTemplateToForm(bool bRecursive) {
|
|
ASSERT(m_ePacket == XFA_PacketType::Template);
|
|
CXFA_Node* pClone =
|
|
m_pDocument->CreateNode(XFA_PacketType::Form, m_elementType);
|
|
if (!pClone)
|
|
return nullptr;
|
|
|
|
pClone->SetTemplateNode(this);
|
|
pClone->UpdateNameHash();
|
|
pClone->SetXMLMappingNode(GetXMLMappingNode());
|
|
if (bRecursive) {
|
|
for (CXFA_Node* pChild = GetFirstChild(); pChild;
|
|
pChild = pChild->GetNextSibling()) {
|
|
pClone->InsertChildAndNotify(pChild->CloneTemplateToForm(bRecursive),
|
|
nullptr);
|
|
}
|
|
}
|
|
pClone->SetFlagAndNotify(XFA_NodeFlag_Initialized);
|
|
return pClone;
|
|
}
|
|
|
|
CXFA_Node* CXFA_Node::GetTemplateNodeIfExists() const {
|
|
return m_pAuxNode;
|
|
}
|
|
|
|
void CXFA_Node::SetTemplateNode(CXFA_Node* pTemplateNode) {
|
|
m_pAuxNode = pTemplateNode;
|
|
}
|
|
|
|
CXFA_Node* CXFA_Node::GetBindData() {
|
|
ASSERT(GetPacketType() == XFA_PacketType::Form);
|
|
return GetBindingNode();
|
|
}
|
|
|
|
int32_t CXFA_Node::AddBindItem(CXFA_Node* pFormNode) {
|
|
ASSERT(pFormNode);
|
|
|
|
if (BindsFormItems()) {
|
|
bool found = false;
|
|
for (auto* v : binding_nodes_) {
|
|
if (v == pFormNode) {
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!found)
|
|
binding_nodes_.emplace_back(pFormNode);
|
|
return pdfium::CollectionSize<int32_t>(binding_nodes_);
|
|
}
|
|
|
|
CXFA_Node* pOldFormItem = GetBindingNode();
|
|
if (!pOldFormItem) {
|
|
SetBindingNode(pFormNode);
|
|
return 1;
|
|
}
|
|
if (pOldFormItem == pFormNode)
|
|
return 1;
|
|
|
|
std::vector<CXFA_Node*> items;
|
|
items.push_back(pOldFormItem);
|
|
items.push_back(pFormNode);
|
|
binding_nodes_ = std::move(items);
|
|
|
|
m_uNodeFlags |= XFA_NodeFlag_BindFormItems;
|
|
return 2;
|
|
}
|
|
|
|
int32_t CXFA_Node::RemoveBindItem(CXFA_Node* pFormNode) {
|
|
if (BindsFormItems()) {
|
|
auto it =
|
|
std::find(binding_nodes_.begin(), binding_nodes_.end(), pFormNode);
|
|
if (it != binding_nodes_.end())
|
|
binding_nodes_.erase(it);
|
|
|
|
if (binding_nodes_.size() == 1) {
|
|
m_uNodeFlags &= ~XFA_NodeFlag_BindFormItems;
|
|
return 1;
|
|
}
|
|
return pdfium::CollectionSize<int32_t>(binding_nodes_);
|
|
}
|
|
|
|
CXFA_Node* pOldFormItem = GetBindingNode();
|
|
if (pOldFormItem != pFormNode)
|
|
return pOldFormItem ? 1 : 0;
|
|
|
|
SetBindingNode(nullptr);
|
|
return 0;
|
|
}
|
|
|
|
bool CXFA_Node::HasBindItem() const {
|
|
return GetPacketType() == XFA_PacketType::Datasets && GetBindingNode();
|
|
}
|
|
|
|
CXFA_Node* CXFA_Node::GetContainerNode() {
|
|
if (GetPacketType() != XFA_PacketType::Form)
|
|
return nullptr;
|
|
XFA_Element eType = GetElementType();
|
|
if (eType == XFA_Element::ExclGroup)
|
|
return nullptr;
|
|
CXFA_Node* pParentNode = GetParent();
|
|
if (pParentNode && pParentNode->GetElementType() == XFA_Element::ExclGroup)
|
|
return nullptr;
|
|
|
|
if (eType == XFA_Element::Field) {
|
|
if (IsChoiceListMultiSelect())
|
|
return nullptr;
|
|
|
|
WideString wsPicture = GetPictureContent(XFA_VALUEPICTURE_DataBind);
|
|
if (!wsPicture.IsEmpty())
|
|
return this;
|
|
|
|
CXFA_Node* pDataNode = GetBindData();
|
|
if (!pDataNode)
|
|
return nullptr;
|
|
|
|
CXFA_Node* pFieldNode = nullptr;
|
|
for (auto* pFormNode : pDataNode->GetBindItemsCopy()) {
|
|
if (!pFormNode || pFormNode->HasRemovedChildren())
|
|
continue;
|
|
pFieldNode = pFormNode->IsWidgetReady() ? pFormNode : nullptr;
|
|
if (pFieldNode)
|
|
wsPicture = pFieldNode->GetPictureContent(XFA_VALUEPICTURE_DataBind);
|
|
if (!wsPicture.IsEmpty())
|
|
break;
|
|
|
|
pFieldNode = nullptr;
|
|
}
|
|
return pFieldNode;
|
|
}
|
|
|
|
CXFA_Node* pGrandNode = pParentNode ? pParentNode->GetParent() : nullptr;
|
|
CXFA_Node* pValueNode =
|
|
(pParentNode && pParentNode->GetElementType() == XFA_Element::Value)
|
|
? pParentNode
|
|
: nullptr;
|
|
if (!pValueNode) {
|
|
pValueNode =
|
|
(pGrandNode && pGrandNode->GetElementType() == XFA_Element::Value)
|
|
? pGrandNode
|
|
: nullptr;
|
|
}
|
|
CXFA_Node* pParentOfValueNode =
|
|
pValueNode ? pValueNode->GetParent() : nullptr;
|
|
return pParentOfValueNode ? pParentOfValueNode->GetContainerNode() : nullptr;
|
|
}
|
|
|
|
LocaleIface* CXFA_Node::GetLocale() {
|
|
Optional<WideString> localeName = GetLocaleName();
|
|
if (!localeName.has_value())
|
|
return nullptr;
|
|
if (localeName.value().EqualsASCII("ambient"))
|
|
return GetDocument()->GetLocaleMgr()->GetDefLocale();
|
|
return GetDocument()->GetLocaleMgr()->GetLocaleByName(localeName.value());
|
|
}
|
|
|
|
Optional<WideString> CXFA_Node::GetLocaleName() {
|
|
CXFA_Node* pForm = ToNode(GetDocument()->GetXFAObject(XFA_HASHCODE_Form));
|
|
if (!pForm)
|
|
return {};
|
|
|
|
CXFA_Subform* pTopSubform =
|
|
pForm->GetFirstChildByClass<CXFA_Subform>(XFA_Element::Subform);
|
|
if (!pTopSubform)
|
|
return {};
|
|
|
|
CXFA_Node* pLocaleNode = this;
|
|
do {
|
|
Optional<WideString> localeName =
|
|
pLocaleNode->JSObject()->TryCData(XFA_Attribute::Locale, false);
|
|
if (localeName)
|
|
return localeName;
|
|
|
|
pLocaleNode = pLocaleNode->GetParent();
|
|
} while (pLocaleNode && pLocaleNode != pTopSubform);
|
|
|
|
CXFA_Node* pConfig = ToNode(GetDocument()->GetXFAObject(XFA_HASHCODE_Config));
|
|
WideString wsLocaleName =
|
|
GetDocument()->GetLocaleMgr()->GetConfigLocaleName(pConfig);
|
|
if (!wsLocaleName.IsEmpty())
|
|
return wsLocaleName;
|
|
|
|
if (pTopSubform) {
|
|
Optional<WideString> localeName =
|
|
pTopSubform->JSObject()->TryCData(XFA_Attribute::Locale, false);
|
|
if (localeName)
|
|
return localeName;
|
|
}
|
|
|
|
LocaleIface* pLocale = GetDocument()->GetLocaleMgr()->GetDefLocale();
|
|
if (!pLocale)
|
|
return {};
|
|
|
|
return pLocale->GetName();
|
|
}
|
|
|
|
XFA_AttributeValue CXFA_Node::GetIntact() {
|
|
CXFA_Keep* pKeep = GetFirstChildByClass<CXFA_Keep>(XFA_Element::Keep);
|
|
auto layout = JSObject()->TryEnum(XFA_Attribute::Layout, true);
|
|
XFA_AttributeValue eLayoutType =
|
|
layout.value_or(XFA_AttributeValue::Position);
|
|
if (pKeep) {
|
|
Optional<XFA_AttributeValue> intact = GetIntactFromKeep(pKeep, eLayoutType);
|
|
if (intact)
|
|
return *intact;
|
|
}
|
|
|
|
switch (GetElementType()) {
|
|
case XFA_Element::Subform:
|
|
switch (eLayoutType) {
|
|
case XFA_AttributeValue::Position:
|
|
case XFA_AttributeValue::Row:
|
|
return XFA_AttributeValue::ContentArea;
|
|
default:
|
|
return XFA_AttributeValue::None;
|
|
}
|
|
case XFA_Element::Field: {
|
|
CXFA_Node* parent = GetParent();
|
|
if (!parent || parent->GetElementType() == XFA_Element::PageArea)
|
|
return XFA_AttributeValue::ContentArea;
|
|
if (parent->GetIntact() != XFA_AttributeValue::None)
|
|
return XFA_AttributeValue::ContentArea;
|
|
|
|
auto value = parent->JSObject()->TryEnum(XFA_Attribute::Layout, true);
|
|
XFA_AttributeValue eParLayout =
|
|
value.value_or(XFA_AttributeValue::Position);
|
|
if (eParLayout == XFA_AttributeValue::Position ||
|
|
eParLayout == XFA_AttributeValue::Row ||
|
|
eParLayout == XFA_AttributeValue::Table) {
|
|
return XFA_AttributeValue::None;
|
|
}
|
|
|
|
XFA_VERSION version = m_pDocument->GetCurVersionMode();
|
|
if (eParLayout == XFA_AttributeValue::Tb && version < XFA_VERSION_208) {
|
|
Optional<CXFA_Measurement> measureH =
|
|
JSObject()->TryMeasure(XFA_Attribute::H, false);
|
|
if (measureH)
|
|
return XFA_AttributeValue::ContentArea;
|
|
}
|
|
return XFA_AttributeValue::None;
|
|
}
|
|
case XFA_Element::Draw:
|
|
return XFA_AttributeValue::ContentArea;
|
|
default:
|
|
return XFA_AttributeValue::None;
|
|
}
|
|
}
|
|
|
|
WideString CXFA_Node::GetNameExpression() {
|
|
WideString wsName = GetNameExpressionSinglePath(this);
|
|
CXFA_Node* parent = GetParent();
|
|
while (parent) {
|
|
WideString wsParent = GetNameExpressionSinglePath(parent);
|
|
wsParent += L".";
|
|
wsParent += wsName;
|
|
wsName = std::move(wsParent);
|
|
parent = parent->GetParent();
|
|
}
|
|
return wsName;
|
|
}
|
|
|
|
CXFA_Node* CXFA_Node::GetDataDescriptionNode() {
|
|
if (m_ePacket == XFA_PacketType::Datasets)
|
|
return m_pAuxNode;
|
|
return nullptr;
|
|
}
|
|
|
|
void CXFA_Node::SetDataDescriptionNode(CXFA_Node* pDataDescriptionNode) {
|
|
ASSERT(m_ePacket == XFA_PacketType::Datasets);
|
|
m_pAuxNode = pDataDescriptionNode;
|
|
}
|
|
|
|
CXFA_Node* CXFA_Node::GetModelNode() {
|
|
switch (GetPacketType()) {
|
|
case XFA_PacketType::Xdp:
|
|
return m_pDocument->GetRoot();
|
|
case XFA_PacketType::Config:
|
|
return ToNode(m_pDocument->GetXFAObject(XFA_HASHCODE_Config));
|
|
case XFA_PacketType::Template:
|
|
return ToNode(m_pDocument->GetXFAObject(XFA_HASHCODE_Template));
|
|
case XFA_PacketType::Form:
|
|
return ToNode(m_pDocument->GetXFAObject(XFA_HASHCODE_Form));
|
|
case XFA_PacketType::Datasets:
|
|
return ToNode(m_pDocument->GetXFAObject(XFA_HASHCODE_Datasets));
|
|
case XFA_PacketType::LocaleSet:
|
|
return ToNode(m_pDocument->GetXFAObject(XFA_HASHCODE_LocaleSet));
|
|
case XFA_PacketType::ConnectionSet:
|
|
return ToNode(m_pDocument->GetXFAObject(XFA_HASHCODE_ConnectionSet));
|
|
case XFA_PacketType::SourceSet:
|
|
return ToNode(m_pDocument->GetXFAObject(XFA_HASHCODE_SourceSet));
|
|
case XFA_PacketType::Xdc:
|
|
return ToNode(m_pDocument->GetXFAObject(XFA_HASHCODE_Xdc));
|
|
default:
|
|
return this;
|
|
}
|
|
}
|
|
|
|
size_t CXFA_Node::CountChildren(XFA_Element eType, bool bOnlyChild) {
|
|
size_t count = 0;
|
|
for (CXFA_Node* pNode = GetFirstChild(); pNode;
|
|
pNode = pNode->GetNextSibling()) {
|
|
if (pNode->GetElementType() != eType && eType != XFA_Element::Unknown)
|
|
continue;
|
|
if (bOnlyChild && HasProperty(pNode->GetElementType()))
|
|
continue;
|
|
++count;
|
|
}
|
|
return count;
|
|
}
|
|
|
|
CXFA_Node* CXFA_Node::GetChildInternal(size_t index,
|
|
XFA_Element eType,
|
|
bool bOnlyChild) const {
|
|
size_t count = 0;
|
|
for (CXFA_Node* pNode = GetFirstChild(); pNode;
|
|
pNode = pNode->GetNextSibling()) {
|
|
if (pNode->GetElementType() != eType && eType != XFA_Element::Unknown)
|
|
continue;
|
|
if (bOnlyChild && HasProperty(pNode->GetElementType()))
|
|
continue;
|
|
if (count == index)
|
|
return pNode;
|
|
|
|
++count;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
void CXFA_Node::InsertChildAndNotify(int32_t index, CXFA_Node* pNode) {
|
|
InsertChildAndNotify(pNode, GetNthChild(index));
|
|
}
|
|
|
|
void CXFA_Node::InsertChildAndNotify(CXFA_Node* pNode, CXFA_Node* pBeforeNode) {
|
|
CHECK(!pNode->GetParent());
|
|
CHECK(!pBeforeNode || pBeforeNode->GetParent() == this);
|
|
pNode->ClearFlag(XFA_NodeFlag_HasRemovedChildren);
|
|
InsertBefore(pNode, pBeforeNode);
|
|
|
|
CXFA_FFNotify* pNotify = m_pDocument->GetNotify();
|
|
if (pNotify)
|
|
pNotify->OnChildAdded(this);
|
|
|
|
if (!IsNeedSavingXMLNode() || !pNode->xml_node_)
|
|
return;
|
|
|
|
ASSERT(!pNode->xml_node_->GetParent());
|
|
xml_node_->InsertBefore(pNode->xml_node_.Get(),
|
|
pBeforeNode ? pBeforeNode->xml_node_.Get() : nullptr);
|
|
}
|
|
|
|
void CXFA_Node::RemoveChildAndNotify(CXFA_Node* pNode, bool bNotify) {
|
|
CHECK(pNode);
|
|
if (pNode->GetParent() != this)
|
|
return;
|
|
|
|
pNode->SetFlag(XFA_NodeFlag_HasRemovedChildren);
|
|
TreeNode<CXFA_Node>::RemoveChild(pNode);
|
|
OnRemoved(bNotify);
|
|
|
|
if (!IsNeedSavingXMLNode() || !pNode->xml_node_)
|
|
return;
|
|
|
|
if (!pNode->IsAttributeInXML()) {
|
|
xml_node_->RemoveChild(pNode->xml_node_.Get());
|
|
return;
|
|
}
|
|
|
|
ASSERT(pNode->xml_node_ == xml_node_);
|
|
CFX_XMLElement* pXMLElement = ToXMLElement(pNode->xml_node_.Get());
|
|
if (pXMLElement) {
|
|
WideString wsAttributeName =
|
|
pNode->JSObject()->GetCData(XFA_Attribute::QualifiedName);
|
|
pXMLElement->RemoveAttribute(wsAttributeName);
|
|
}
|
|
|
|
WideString wsName = pNode->JSObject()
|
|
->TryAttribute(XFA_Attribute::Name, false)
|
|
.value_or(WideString());
|
|
|
|
auto* pNewXMLElement = GetXMLDocument()->CreateNode<CFX_XMLElement>(wsName);
|
|
WideString wsValue = JSObject()->GetCData(XFA_Attribute::Value);
|
|
if (!wsValue.IsEmpty()) {
|
|
auto* text = GetXMLDocument()->CreateNode<CFX_XMLText>(wsValue);
|
|
pNewXMLElement->AppendLastChild(text);
|
|
}
|
|
pNode->xml_node_ = pNewXMLElement;
|
|
pNode->JSObject()->SetEnum(XFA_Attribute::Contains,
|
|
XFA_AttributeValue::Unknown, false);
|
|
}
|
|
|
|
CXFA_Node* CXFA_Node::GetFirstChildByName(WideStringView wsName) const {
|
|
return GetFirstChildByName(FX_HashCode_GetW(wsName, false));
|
|
}
|
|
|
|
CXFA_Node* CXFA_Node::GetFirstChildByName(uint32_t dwNameHash) const {
|
|
for (CXFA_Node* pNode = GetFirstChild(); pNode;
|
|
pNode = pNode->GetNextSibling()) {
|
|
if (pNode->GetNameHash() == dwNameHash)
|
|
return pNode;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
CXFA_Node* CXFA_Node::GetFirstChildByClassInternal(XFA_Element eType) const {
|
|
for (CXFA_Node* pNode = GetFirstChild(); pNode;
|
|
pNode = pNode->GetNextSibling()) {
|
|
if (pNode->GetElementType() == eType)
|
|
return pNode;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
CXFA_Node* CXFA_Node::GetNextSameNameSibling(uint32_t dwNameHash) const {
|
|
for (CXFA_Node* pNode = GetNextSibling(); pNode;
|
|
pNode = pNode->GetNextSibling()) {
|
|
if (pNode->GetNameHash() == dwNameHash)
|
|
return pNode;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
CXFA_Node* CXFA_Node::GetNextSameNameSiblingInternal(
|
|
WideStringView wsNodeName) const {
|
|
return GetNextSameNameSibling(FX_HashCode_GetW(wsNodeName, false));
|
|
}
|
|
|
|
CXFA_Node* CXFA_Node::GetNextSameClassSiblingInternal(XFA_Element eType) const {
|
|
for (CXFA_Node* pNode = GetNextSibling(); pNode;
|
|
pNode = pNode->GetNextSibling()) {
|
|
if (pNode->GetElementType() == eType)
|
|
return pNode;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
CXFA_Node* CXFA_Node::GetOneChildNamed(WideStringView wsName) {
|
|
return FindFirstSiblingNamed(this, FX_HashCode_GetW(wsName, false));
|
|
}
|
|
|
|
CXFA_Node* CXFA_Node::GetOneChildOfClass(WideStringView wsClass) {
|
|
XFA_Element element = XFA_GetElementByName(wsClass);
|
|
if (element == XFA_Element::Unknown)
|
|
return nullptr;
|
|
|
|
return FindFirstSiblingOfClass(this, element);
|
|
}
|
|
|
|
std::vector<CXFA_Node*> CXFA_Node::GetSiblings(bool bIsClassName) {
|
|
std::vector<CXFA_Node*> siblings;
|
|
CXFA_Node* parent = GetParent();
|
|
if (!parent)
|
|
return siblings;
|
|
if (!parent->HasProperty(GetElementType())) {
|
|
parent = GetTransparentParent();
|
|
if (!parent)
|
|
return siblings;
|
|
}
|
|
|
|
uint32_t dwNameHash = bIsClassName ? GetClassHashCode() : GetNameHash();
|
|
TraverseSiblings(parent, dwNameHash, &siblings, bIsClassName, true);
|
|
return siblings;
|
|
}
|
|
|
|
size_t CXFA_Node::GetIndex(bool bIsProperty, bool bIsClassIndex) {
|
|
CXFA_Node* parent = GetParent();
|
|
if (!parent)
|
|
return 0;
|
|
|
|
if (!bIsProperty) {
|
|
parent = GetTransparentParent();
|
|
if (!parent)
|
|
return 0;
|
|
}
|
|
uint32_t dwHashName = bIsClassIndex ? GetClassHashCode() : GetNameHash();
|
|
std::vector<CXFA_Node*> siblings;
|
|
TraverseSiblings(parent, dwHashName, &siblings, bIsClassIndex, true);
|
|
for (size_t i = 0; i < siblings.size(); ++i) {
|
|
if (siblings[i] == this)
|
|
return i;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
size_t CXFA_Node::GetIndexByName() {
|
|
return GetIndex(IsProperty(), /*bIsClassIndex=*/false);
|
|
}
|
|
|
|
size_t CXFA_Node::GetIndexByClassName() {
|
|
return GetIndex(IsProperty(), /*bIsClassIndex=*/true);
|
|
}
|
|
|
|
CXFA_Node* CXFA_Node::GetInstanceMgrOfSubform() {
|
|
CXFA_Node* pInstanceMgr = nullptr;
|
|
if (m_ePacket == XFA_PacketType::Form) {
|
|
CXFA_Node* pParentNode = GetParent();
|
|
if (!pParentNode || pParentNode->GetElementType() == XFA_Element::Area)
|
|
return pInstanceMgr;
|
|
|
|
for (CXFA_Node* pNode = GetPrevSibling(); pNode;
|
|
pNode = pNode->GetPrevSibling()) {
|
|
XFA_Element eType = pNode->GetElementType();
|
|
if ((eType == XFA_Element::Subform || eType == XFA_Element::SubformSet) &&
|
|
pNode->m_dwNameHash != m_dwNameHash) {
|
|
break;
|
|
}
|
|
if (eType == XFA_Element::InstanceManager) {
|
|
WideString wsName = JSObject()->GetCData(XFA_Attribute::Name);
|
|
WideString wsInstName =
|
|
pNode->JSObject()->GetCData(XFA_Attribute::Name);
|
|
if (wsInstName.GetLength() > 0 && wsInstName[0] == '_' &&
|
|
wsInstName.Last(wsInstName.GetLength() - 1) == wsName) {
|
|
pInstanceMgr = pNode;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return pInstanceMgr;
|
|
}
|
|
|
|
CXFA_Occur* CXFA_Node::GetOccurIfExists() {
|
|
return GetFirstChildByClass<CXFA_Occur>(XFA_Element::Occur);
|
|
}
|
|
|
|
bool CXFA_Node::HasFlag(XFA_NodeFlag dwFlag) const {
|
|
if (m_uNodeFlags & dwFlag)
|
|
return true;
|
|
if (dwFlag == XFA_NodeFlag_HasRemovedChildren)
|
|
return GetParent() && GetParent()->HasFlag(dwFlag);
|
|
return false;
|
|
}
|
|
|
|
void CXFA_Node::SetFlagAndNotify(uint32_t dwFlag) {
|
|
ASSERT(dwFlag == XFA_NodeFlag_Initialized);
|
|
|
|
if (!IsInitialized()) {
|
|
CXFA_FFNotify* pNotify = m_pDocument->GetNotify();
|
|
if (pNotify) {
|
|
pNotify->OnNodeReady(this);
|
|
}
|
|
}
|
|
m_uNodeFlags |= dwFlag;
|
|
}
|
|
|
|
void CXFA_Node::SetFlag(uint32_t dwFlag) {
|
|
m_uNodeFlags |= dwFlag;
|
|
}
|
|
|
|
void CXFA_Node::ClearFlag(uint32_t dwFlag) {
|
|
m_uNodeFlags &= ~dwFlag;
|
|
}
|
|
|
|
bool CXFA_Node::IsAttributeInXML() {
|
|
return JSObject()->GetEnum(XFA_Attribute::Contains) ==
|
|
XFA_AttributeValue::MetaData;
|
|
}
|
|
|
|
void CXFA_Node::OnRemoved(bool bNotify) const {
|
|
if (!bNotify)
|
|
return;
|
|
|
|
CXFA_FFNotify* pNotify = m_pDocument->GetNotify();
|
|
if (pNotify)
|
|
pNotify->OnChildRemoved();
|
|
}
|
|
|
|
void CXFA_Node::UpdateNameHash() {
|
|
WideString wsName = JSObject()->GetCData(XFA_Attribute::Name);
|
|
m_dwNameHash = FX_HashCode_GetW(wsName.AsStringView(), false);
|
|
}
|
|
|
|
CFX_XMLNode* CXFA_Node::CreateXMLMappingNode() {
|
|
if (!xml_node_) {
|
|
xml_node_ = GetXMLDocument()->CreateNode<CFX_XMLElement>(
|
|
JSObject()->GetCData(XFA_Attribute::Name));
|
|
}
|
|
return xml_node_.Get();
|
|
}
|
|
|
|
bool CXFA_Node::IsNeedSavingXMLNode() const {
|
|
return xml_node_ && (GetPacketType() == XFA_PacketType::Datasets ||
|
|
GetElementType() == XFA_Element::Xfa);
|
|
}
|
|
|
|
CXFA_Node* CXFA_Node::GetItemIfExists(int32_t iIndex) {
|
|
int32_t iCount = 0;
|
|
uint32_t dwNameHash = 0;
|
|
for (CXFA_Node* pNode = GetNextSibling(); pNode;
|
|
pNode = pNode->GetNextSibling()) {
|
|
XFA_Element eCurType = pNode->GetElementType();
|
|
if (eCurType == XFA_Element::InstanceManager)
|
|
break;
|
|
if ((eCurType != XFA_Element::Subform) &&
|
|
(eCurType != XFA_Element::SubformSet)) {
|
|
continue;
|
|
}
|
|
if (iCount == 0) {
|
|
WideString wsName = pNode->JSObject()->GetCData(XFA_Attribute::Name);
|
|
WideString wsInstName = JSObject()->GetCData(XFA_Attribute::Name);
|
|
if (wsInstName.GetLength() < 1 || wsInstName[0] != '_' ||
|
|
wsInstName.Last(wsInstName.GetLength() - 1) != wsName) {
|
|
return nullptr;
|
|
}
|
|
dwNameHash = pNode->GetNameHash();
|
|
}
|
|
if (dwNameHash != pNode->GetNameHash())
|
|
break;
|
|
|
|
iCount++;
|
|
if (iCount > iIndex)
|
|
return pNode;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
int32_t CXFA_Node::GetCount() {
|
|
int32_t iCount = 0;
|
|
uint32_t dwNameHash = 0;
|
|
for (CXFA_Node* pNode = GetNextSibling(); pNode;
|
|
pNode = pNode->GetNextSibling()) {
|
|
XFA_Element eCurType = pNode->GetElementType();
|
|
if (eCurType == XFA_Element::InstanceManager)
|
|
break;
|
|
if ((eCurType != XFA_Element::Subform) &&
|
|
(eCurType != XFA_Element::SubformSet)) {
|
|
continue;
|
|
}
|
|
if (iCount == 0) {
|
|
WideString wsName = pNode->JSObject()->GetCData(XFA_Attribute::Name);
|
|
WideString wsInstName = JSObject()->GetCData(XFA_Attribute::Name);
|
|
if (wsInstName.GetLength() < 1 || wsInstName[0] != '_' ||
|
|
wsInstName.Last(wsInstName.GetLength() - 1) != wsName) {
|
|
return iCount;
|
|
}
|
|
dwNameHash = pNode->GetNameHash();
|
|
}
|
|
if (dwNameHash != pNode->GetNameHash())
|
|
break;
|
|
|
|
iCount++;
|
|
}
|
|
return iCount;
|
|
}
|
|
|
|
void CXFA_Node::InsertItem(CXFA_Node* pNewInstance,
|
|
int32_t iPos,
|
|
int32_t iCount,
|
|
bool bMoveDataBindingNodes) {
|
|
if (iCount < 0)
|
|
iCount = GetCount();
|
|
if (iPos < 0)
|
|
iPos = iCount;
|
|
if (iPos == iCount) {
|
|
CXFA_Node* item = GetItemIfExists(iCount - 1);
|
|
if (!item)
|
|
return;
|
|
|
|
CXFA_Node* pNextSibling =
|
|
iCount > 0 ? item->GetNextSibling() : GetNextSibling();
|
|
GetParent()->InsertChildAndNotify(pNewInstance, pNextSibling);
|
|
if (bMoveDataBindingNodes) {
|
|
std::set<CXFA_Node*> sNew;
|
|
std::set<CXFA_Node*> sAfter;
|
|
CXFA_NodeIteratorTemplate<CXFA_Node,
|
|
CXFA_TraverseStrategy_XFAContainerNode>
|
|
sIteratorNew(pNewInstance);
|
|
for (CXFA_Node* pNode = sIteratorNew.GetCurrent(); pNode;
|
|
pNode = sIteratorNew.MoveToNext()) {
|
|
CXFA_Node* pDataNode = pNode->GetBindData();
|
|
if (!pDataNode)
|
|
continue;
|
|
|
|
sNew.insert(pDataNode);
|
|
}
|
|
CXFA_NodeIteratorTemplate<CXFA_Node,
|
|
CXFA_TraverseStrategy_XFAContainerNode>
|
|
sIteratorAfter(pNextSibling);
|
|
for (CXFA_Node* pNode = sIteratorAfter.GetCurrent(); pNode;
|
|
pNode = sIteratorAfter.MoveToNext()) {
|
|
CXFA_Node* pDataNode = pNode->GetBindData();
|
|
if (!pDataNode)
|
|
continue;
|
|
|
|
sAfter.insert(pDataNode);
|
|
}
|
|
ReorderDataNodes(sNew, sAfter, false);
|
|
}
|
|
} else {
|
|
CXFA_Node* pBeforeInstance = GetItemIfExists(iPos);
|
|
if (!pBeforeInstance) {
|
|
// TODO(dsinclair): What should happen here?
|
|
return;
|
|
}
|
|
|
|
GetParent()->InsertChildAndNotify(pNewInstance, pBeforeInstance);
|
|
if (bMoveDataBindingNodes) {
|
|
std::set<CXFA_Node*> sNew;
|
|
std::set<CXFA_Node*> sBefore;
|
|
CXFA_NodeIteratorTemplate<CXFA_Node,
|
|
CXFA_TraverseStrategy_XFAContainerNode>
|
|
sIteratorNew(pNewInstance);
|
|
for (CXFA_Node* pNode = sIteratorNew.GetCurrent(); pNode;
|
|
pNode = sIteratorNew.MoveToNext()) {
|
|
CXFA_Node* pDataNode = pNode->GetBindData();
|
|
if (!pDataNode)
|
|
continue;
|
|
|
|
sNew.insert(pDataNode);
|
|
}
|
|
CXFA_NodeIteratorTemplate<CXFA_Node,
|
|
CXFA_TraverseStrategy_XFAContainerNode>
|
|
sIteratorBefore(pBeforeInstance);
|
|
for (CXFA_Node* pNode = sIteratorBefore.GetCurrent(); pNode;
|
|
pNode = sIteratorBefore.MoveToNext()) {
|
|
CXFA_Node* pDataNode = pNode->GetBindData();
|
|
if (!pDataNode)
|
|
continue;
|
|
|
|
sBefore.insert(pDataNode);
|
|
}
|
|
ReorderDataNodes(sNew, sBefore, true);
|
|
}
|
|
}
|
|
}
|
|
|
|
void CXFA_Node::RemoveItem(CXFA_Node* pRemoveInstance,
|
|
bool bRemoveDataBinding) {
|
|
GetParent()->RemoveChildAndNotify(pRemoveInstance, true);
|
|
if (!bRemoveDataBinding)
|
|
return;
|
|
|
|
CXFA_NodeIteratorTemplate<CXFA_Node, CXFA_TraverseStrategy_XFAContainerNode>
|
|
sIterator(pRemoveInstance);
|
|
for (CXFA_Node* pFormNode = sIterator.GetCurrent(); pFormNode;
|
|
pFormNode = sIterator.MoveToNext()) {
|
|
CXFA_Node* pDataNode = pFormNode->GetBindData();
|
|
if (!pDataNode)
|
|
continue;
|
|
|
|
if (pDataNode->RemoveBindItem(pFormNode) == 0) {
|
|
if (CXFA_Node* pDataParent = pDataNode->GetParent()) {
|
|
pDataParent->RemoveChildAndNotify(pDataNode, true);
|
|
}
|
|
}
|
|
pFormNode->SetBindingNode(nullptr);
|
|
}
|
|
}
|
|
|
|
CXFA_Node* CXFA_Node::CreateInstanceIfPossible(bool bDataMerge) {
|
|
CXFA_Document* pDocument = GetDocument();
|
|
CXFA_Node* pTemplateNode = GetTemplateNodeIfExists();
|
|
if (!pTemplateNode)
|
|
return nullptr;
|
|
|
|
CXFA_Node* pFormParent = GetParent();
|
|
CXFA_Node* pDataScope = nullptr;
|
|
for (CXFA_Node* pRootBoundNode = pFormParent;
|
|
pRootBoundNode && pRootBoundNode->IsContainerNode();
|
|
pRootBoundNode = pRootBoundNode->GetParent()) {
|
|
pDataScope = pRootBoundNode->GetBindData();
|
|
if (pDataScope)
|
|
break;
|
|
}
|
|
if (!pDataScope) {
|
|
pDataScope = ToNode(pDocument->GetXFAObject(XFA_HASHCODE_Record));
|
|
ASSERT(pDataScope);
|
|
}
|
|
|
|
CXFA_Node* pInstance = pDocument->DataMerge_CopyContainer(
|
|
pTemplateNode, pFormParent, pDataScope, true, bDataMerge, true);
|
|
if (pInstance) {
|
|
pDocument->DataMerge_UpdateBindingRelations(pInstance);
|
|
pFormParent->RemoveChildAndNotify(pInstance, true);
|
|
}
|
|
return pInstance;
|
|
}
|
|
|
|
Optional<bool> CXFA_Node::GetDefaultBoolean(XFA_Attribute attr) const {
|
|
Optional<void*> value = GetDefaultValue(attr, XFA_AttributeType::Boolean);
|
|
if (!value)
|
|
return {};
|
|
return {!!*value};
|
|
}
|
|
|
|
Optional<int32_t> CXFA_Node::GetDefaultInteger(XFA_Attribute attr) const {
|
|
Optional<void*> value = GetDefaultValue(attr, XFA_AttributeType::Integer);
|
|
if (!value)
|
|
return {};
|
|
return {static_cast<int32_t>(reinterpret_cast<uintptr_t>(*value))};
|
|
}
|
|
|
|
Optional<CXFA_Measurement> CXFA_Node::GetDefaultMeasurement(
|
|
XFA_Attribute attr) const {
|
|
Optional<void*> value = GetDefaultValue(attr, XFA_AttributeType::Measure);
|
|
if (!value)
|
|
return {};
|
|
|
|
WideString str = WideString(static_cast<const wchar_t*>(*value));
|
|
return {CXFA_Measurement(str.AsStringView())};
|
|
}
|
|
|
|
Optional<WideString> CXFA_Node::GetDefaultCData(XFA_Attribute attr) const {
|
|
Optional<void*> value = GetDefaultValue(attr, XFA_AttributeType::CData);
|
|
if (!value)
|
|
return {};
|
|
|
|
return {WideString(static_cast<const wchar_t*>(*value))};
|
|
}
|
|
|
|
Optional<XFA_AttributeValue> CXFA_Node::GetDefaultEnum(
|
|
XFA_Attribute attr) const {
|
|
Optional<void*> value = GetDefaultValue(attr, XFA_AttributeType::Enum);
|
|
if (!value)
|
|
return {};
|
|
return {static_cast<XFA_AttributeValue>(reinterpret_cast<uintptr_t>(*value))};
|
|
}
|
|
|
|
Optional<void*> CXFA_Node::GetDefaultValue(XFA_Attribute attr,
|
|
XFA_AttributeType eType) const {
|
|
const AttributeData* data = GetAttributeData(attr);
|
|
if (!data)
|
|
return {};
|
|
if (data->type == eType)
|
|
return {data->default_value};
|
|
return {};
|
|
}
|
|
|
|
void CXFA_Node::SendAttributeChangeMessage(XFA_Attribute eAttribute,
|
|
bool bScriptModify) {
|
|
CXFA_FFNotify* pNotify = GetDocument()->GetNotify();
|
|
if (!pNotify)
|
|
return;
|
|
|
|
if (GetPacketType() != XFA_PacketType::Form) {
|
|
pNotify->OnValueChanged(this, eAttribute, this, this);
|
|
return;
|
|
}
|
|
|
|
bool bNeedFindContainer = false;
|
|
switch (GetElementType()) {
|
|
case XFA_Element::Caption:
|
|
bNeedFindContainer = true;
|
|
pNotify->OnValueChanged(this, eAttribute, this, GetParent());
|
|
break;
|
|
case XFA_Element::Font:
|
|
case XFA_Element::Para: {
|
|
bNeedFindContainer = true;
|
|
CXFA_Node* pParentNode = GetParent();
|
|
if (pParentNode->GetElementType() == XFA_Element::Caption) {
|
|
pNotify->OnValueChanged(this, eAttribute, pParentNode,
|
|
pParentNode->GetParent());
|
|
} else {
|
|
pNotify->OnValueChanged(this, eAttribute, this, pParentNode);
|
|
}
|
|
break;
|
|
}
|
|
case XFA_Element::Margin: {
|
|
bNeedFindContainer = true;
|
|
CXFA_Node* pParentNode = GetParent();
|
|
XFA_Element eParentType = pParentNode->GetElementType();
|
|
if (pParentNode->IsContainerNode()) {
|
|
pNotify->OnValueChanged(this, eAttribute, this, pParentNode);
|
|
} else if (eParentType == XFA_Element::Caption) {
|
|
pNotify->OnValueChanged(this, eAttribute, pParentNode,
|
|
pParentNode->GetParent());
|
|
} else {
|
|
CXFA_Node* pNode = pParentNode->GetParent();
|
|
if (pNode && pNode->GetElementType() == XFA_Element::Ui)
|
|
pNotify->OnValueChanged(this, eAttribute, pNode, pNode->GetParent());
|
|
}
|
|
break;
|
|
}
|
|
case XFA_Element::Comb: {
|
|
CXFA_Node* pEditNode = GetParent();
|
|
XFA_Element eUIType = pEditNode->GetElementType();
|
|
if (pEditNode && (eUIType == XFA_Element::DateTimeEdit ||
|
|
eUIType == XFA_Element::NumericEdit ||
|
|
eUIType == XFA_Element::TextEdit)) {
|
|
CXFA_Node* pUINode = pEditNode->GetParent();
|
|
if (pUINode) {
|
|
pNotify->OnValueChanged(this, eAttribute, pUINode,
|
|
pUINode->GetParent());
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case XFA_Element::Button:
|
|
case XFA_Element::Barcode:
|
|
case XFA_Element::ChoiceList:
|
|
case XFA_Element::DateTimeEdit:
|
|
case XFA_Element::NumericEdit:
|
|
case XFA_Element::PasswordEdit:
|
|
case XFA_Element::TextEdit: {
|
|
CXFA_Node* pUINode = GetParent();
|
|
if (pUINode) {
|
|
pNotify->OnValueChanged(this, eAttribute, pUINode,
|
|
pUINode->GetParent());
|
|
}
|
|
break;
|
|
}
|
|
case XFA_Element::CheckButton: {
|
|
bNeedFindContainer = true;
|
|
CXFA_Node* pUINode = GetParent();
|
|
if (pUINode) {
|
|
pNotify->OnValueChanged(this, eAttribute, pUINode,
|
|
pUINode->GetParent());
|
|
}
|
|
break;
|
|
}
|
|
case XFA_Element::Keep:
|
|
case XFA_Element::Bookend:
|
|
case XFA_Element::Break:
|
|
case XFA_Element::BreakAfter:
|
|
case XFA_Element::BreakBefore:
|
|
case XFA_Element::Overflow:
|
|
bNeedFindContainer = true;
|
|
break;
|
|
case XFA_Element::Area:
|
|
case XFA_Element::Draw:
|
|
case XFA_Element::ExclGroup:
|
|
case XFA_Element::Field:
|
|
case XFA_Element::Subform:
|
|
case XFA_Element::SubformSet:
|
|
pNotify->OnContainerChanged(this);
|
|
pNotify->OnValueChanged(this, eAttribute, this, this);
|
|
break;
|
|
case XFA_Element::Sharptext:
|
|
case XFA_Element::Sharpxml:
|
|
case XFA_Element::SharpxHTML: {
|
|
CXFA_Node* pTextNode = GetParent();
|
|
if (!pTextNode)
|
|
return;
|
|
|
|
CXFA_Node* pValueNode = pTextNode->GetParent();
|
|
if (!pValueNode)
|
|
return;
|
|
|
|
XFA_Element eType = pValueNode->GetElementType();
|
|
if (eType == XFA_Element::Value) {
|
|
bNeedFindContainer = true;
|
|
CXFA_Node* pNode = pValueNode->GetParent();
|
|
if (pNode && pNode->IsContainerNode()) {
|
|
if (bScriptModify)
|
|
pValueNode = pNode;
|
|
|
|
pNotify->OnValueChanged(this, eAttribute, pValueNode, pNode);
|
|
} else {
|
|
pNotify->OnValueChanged(this, eAttribute, pNode, pNode->GetParent());
|
|
}
|
|
} else {
|
|
if (eType == XFA_Element::Items) {
|
|
CXFA_Node* pNode = pValueNode->GetParent();
|
|
if (pNode && pNode->IsContainerNode()) {
|
|
pNotify->OnValueChanged(this, eAttribute, pValueNode, pNode);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (!bNeedFindContainer)
|
|
return;
|
|
|
|
CXFA_Node* pParent = this;
|
|
while (pParent && !pParent->IsContainerNode())
|
|
pParent = pParent->GetParent();
|
|
|
|
if (pParent)
|
|
pNotify->OnContainerChanged(pParent);
|
|
}
|
|
|
|
void CXFA_Node::SyncValue(const WideString& wsValue, bool bNotify) {
|
|
WideString wsFormatValue = wsValue;
|
|
CXFA_Node* pContainerNode = GetContainerNode();
|
|
if (pContainerNode)
|
|
wsFormatValue = pContainerNode->GetFormatDataValue(wsValue);
|
|
|
|
JSObject()->SetContent(wsValue, wsFormatValue, bNotify, false, true);
|
|
}
|
|
|
|
WideString CXFA_Node::GetRawValue() {
|
|
return JSObject()->GetContent(false);
|
|
}
|
|
|
|
int32_t CXFA_Node::GetRotate() const {
|
|
Optional<int32_t> degrees =
|
|
JSObject()->TryInteger(XFA_Attribute::Rotate, false);
|
|
return degrees ? XFA_MapRotation(*degrees) / 90 * 90 : 0;
|
|
}
|
|
|
|
CXFA_Border* CXFA_Node::GetBorderIfExists() const {
|
|
return JSObject()->GetProperty<CXFA_Border>(0, XFA_Element::Border);
|
|
}
|
|
|
|
CXFA_Border* CXFA_Node::GetOrCreateBorderIfPossible() {
|
|
return JSObject()->GetOrCreateProperty<CXFA_Border>(0, XFA_Element::Border);
|
|
}
|
|
|
|
CXFA_Caption* CXFA_Node::GetCaptionIfExists() const {
|
|
return JSObject()->GetProperty<CXFA_Caption>(0, XFA_Element::Caption);
|
|
}
|
|
|
|
CXFA_Font* CXFA_Node::GetOrCreateFontIfPossible() {
|
|
return JSObject()->GetOrCreateProperty<CXFA_Font>(0, XFA_Element::Font);
|
|
}
|
|
|
|
CXFA_Font* CXFA_Node::GetFontIfExists() const {
|
|
return JSObject()->GetProperty<CXFA_Font>(0, XFA_Element::Font);
|
|
}
|
|
|
|
float CXFA_Node::GetFontSize() const {
|
|
CXFA_Font* font = GetFontIfExists();
|
|
float fFontSize = font ? font->GetFontSize() : 10.0f;
|
|
return fFontSize < 0.1f ? 10.0f : fFontSize;
|
|
}
|
|
|
|
float CXFA_Node::GetLineHeight() const {
|
|
float fLineHeight = 0;
|
|
CXFA_Para* para = GetParaIfExists();
|
|
if (para)
|
|
fLineHeight = para->GetLineHeight();
|
|
|
|
if (fLineHeight < 1)
|
|
fLineHeight = GetFontSize() * 1.2f;
|
|
return fLineHeight;
|
|
}
|
|
|
|
FX_ARGB CXFA_Node::GetTextColor() const {
|
|
CXFA_Font* font = GetFontIfExists();
|
|
return font ? font->GetColor() : 0xFF000000;
|
|
}
|
|
|
|
CXFA_Margin* CXFA_Node::GetMarginIfExists() const {
|
|
return JSObject()->GetProperty<CXFA_Margin>(0, XFA_Element::Margin);
|
|
}
|
|
|
|
CXFA_Para* CXFA_Node::GetParaIfExists() const {
|
|
return JSObject()->GetProperty<CXFA_Para>(0, XFA_Element::Para);
|
|
}
|
|
|
|
bool CXFA_Node::IsOpenAccess() const {
|
|
for (auto* pNode = this; pNode; pNode = pNode->GetContainerParent()) {
|
|
XFA_AttributeValue iAcc = pNode->JSObject()->GetEnum(XFA_Attribute::Access);
|
|
if (iAcc != XFA_AttributeValue::Open)
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
CXFA_Value* CXFA_Node::GetDefaultValueIfExists() {
|
|
CXFA_Node* pTemNode = GetTemplateNodeIfExists();
|
|
return pTemNode ? pTemNode->JSObject()->GetProperty<CXFA_Value>(
|
|
0, XFA_Element::Value)
|
|
: nullptr;
|
|
}
|
|
|
|
CXFA_Value* CXFA_Node::GetFormValueIfExists() const {
|
|
return JSObject()->GetProperty<CXFA_Value>(0, XFA_Element::Value);
|
|
}
|
|
|
|
CXFA_Calculate* CXFA_Node::GetCalculateIfExists() const {
|
|
return JSObject()->GetProperty<CXFA_Calculate>(0, XFA_Element::Calculate);
|
|
}
|
|
|
|
CXFA_Validate* CXFA_Node::GetValidateIfExists() const {
|
|
return JSObject()->GetProperty<CXFA_Validate>(0, XFA_Element::Validate);
|
|
}
|
|
|
|
CXFA_Validate* CXFA_Node::GetOrCreateValidateIfPossible() {
|
|
return JSObject()->GetOrCreateProperty<CXFA_Validate>(0,
|
|
XFA_Element::Validate);
|
|
}
|
|
|
|
CXFA_Bind* CXFA_Node::GetBindIfExists() const {
|
|
return JSObject()->GetProperty<CXFA_Bind>(0, XFA_Element::Bind);
|
|
}
|
|
|
|
Optional<XFA_AttributeValue> CXFA_Node::GetIntactFromKeep(
|
|
const CXFA_Keep* pKeep,
|
|
XFA_AttributeValue eLayoutType) const {
|
|
Optional<XFA_AttributeValue> intact =
|
|
pKeep->JSObject()->TryEnum(XFA_Attribute::Intact, false);
|
|
if (!intact.has_value())
|
|
return {};
|
|
|
|
if (intact.value() != XFA_AttributeValue::None ||
|
|
eLayoutType != XFA_AttributeValue::Row ||
|
|
m_pDocument->GetCurVersionMode() >= XFA_VERSION_208) {
|
|
return intact;
|
|
}
|
|
|
|
CXFA_Node* pPreviewRow = GetPrevContainerSibling();
|
|
if (!pPreviewRow || pPreviewRow->JSObject()->GetEnum(XFA_Attribute::Layout) !=
|
|
XFA_AttributeValue::Row) {
|
|
return intact;
|
|
}
|
|
|
|
Optional<XFA_AttributeValue> value =
|
|
pKeep->JSObject()->TryEnum(XFA_Attribute::Previous, false);
|
|
if (value && (*value == XFA_AttributeValue::ContentArea ||
|
|
*value == XFA_AttributeValue::PageArea)) {
|
|
return XFA_AttributeValue::ContentArea;
|
|
}
|
|
|
|
CXFA_Keep* pNode =
|
|
pPreviewRow->GetFirstChildByClass<CXFA_Keep>(XFA_Element::Keep);
|
|
if (!pNode)
|
|
return intact;
|
|
|
|
Optional<XFA_AttributeValue> ret =
|
|
pNode->JSObject()->TryEnum(XFA_Attribute::Next, false);
|
|
if (!ret)
|
|
return intact;
|
|
|
|
return (*ret == XFA_AttributeValue::ContentArea ||
|
|
*ret == XFA_AttributeValue::PageArea)
|
|
? XFA_AttributeValue::ContentArea
|
|
: intact;
|
|
}
|
|
|
|
Optional<float> CXFA_Node::TryWidth() {
|
|
return JSObject()->TryMeasureAsFloat(XFA_Attribute::W);
|
|
}
|
|
|
|
Optional<float> CXFA_Node::TryHeight() {
|
|
return JSObject()->TryMeasureAsFloat(XFA_Attribute::H);
|
|
}
|
|
|
|
Optional<float> CXFA_Node::TryMinWidth() {
|
|
return JSObject()->TryMeasureAsFloat(XFA_Attribute::MinW);
|
|
}
|
|
|
|
Optional<float> CXFA_Node::TryMinHeight() {
|
|
return JSObject()->TryMeasureAsFloat(XFA_Attribute::MinH);
|
|
}
|
|
|
|
Optional<float> CXFA_Node::TryMaxWidth() {
|
|
return JSObject()->TryMeasureAsFloat(XFA_Attribute::MaxW);
|
|
}
|
|
|
|
Optional<float> CXFA_Node::TryMaxHeight() {
|
|
return JSObject()->TryMeasureAsFloat(XFA_Attribute::MaxH);
|
|
}
|
|
|
|
CXFA_Node* CXFA_Node::GetExclGroupIfExists() {
|
|
CXFA_Node* pExcl = GetParent();
|
|
if (!pExcl || pExcl->GetElementType() != XFA_Element::ExclGroup)
|
|
return nullptr;
|
|
return pExcl;
|
|
}
|
|
|
|
XFA_EventError CXFA_Node::ProcessEvent(CXFA_FFDocView* pDocView,
|
|
XFA_AttributeValue iActivity,
|
|
CXFA_EventParam* pEventParam) {
|
|
if (GetElementType() == XFA_Element::Draw)
|
|
return XFA_EventError::kNotExist;
|
|
|
|
std::vector<CXFA_Event*> eventArray =
|
|
GetEventByActivity(iActivity, pEventParam->m_bIsFormReady);
|
|
bool first = true;
|
|
XFA_EventError iRet = XFA_EventError::kNotExist;
|
|
for (CXFA_Event* event : eventArray) {
|
|
XFA_EventError result =
|
|
ProcessEventInternal(pDocView, iActivity, event, pEventParam);
|
|
if (first || result == XFA_EventError::kSuccess)
|
|
iRet = result;
|
|
first = false;
|
|
}
|
|
return iRet;
|
|
}
|
|
|
|
XFA_EventError CXFA_Node::ProcessEventInternal(CXFA_FFDocView* pDocView,
|
|
XFA_AttributeValue iActivity,
|
|
CXFA_Event* event,
|
|
CXFA_EventParam* pEventParam) {
|
|
if (!event)
|
|
return XFA_EventError::kNotExist;
|
|
|
|
switch (event->GetEventType()) {
|
|
case XFA_Element::Execute:
|
|
break;
|
|
case XFA_Element::Script:
|
|
if (iActivity == XFA_AttributeValue::DocClose) {
|
|
// Too late, scripting engine already gone.
|
|
return XFA_EventError::kNotExist;
|
|
}
|
|
return ExecuteScript(pDocView, event->GetScriptIfExists(), pEventParam);
|
|
case XFA_Element::SignData:
|
|
break;
|
|
case XFA_Element::Submit: {
|
|
// TODO(crbug.com/867485): Submit is disabled for now. Fix it and reenable this
|
|
// code.
|
|
#ifdef PDF_XFA_ELEMENT_SUBMIT_ENABLED
|
|
CXFA_Submit* submit = event->GetSubmitIfExists();
|
|
if (!submit)
|
|
return XFA_EventError::kNotExist;
|
|
return pDocView->GetDoc()->GetDocEnvironment()->Submit(pDocView->GetDoc(),
|
|
submit);
|
|
#else
|
|
return XFA_EventError::kDisabled;
|
|
#endif // PDF_XFA_ELEMENT_SUBMIT_ENABLED
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
return XFA_EventError::kNotExist;
|
|
}
|
|
|
|
XFA_EventError CXFA_Node::ProcessCalculate(CXFA_FFDocView* pDocView) {
|
|
if (GetElementType() == XFA_Element::Draw)
|
|
return XFA_EventError::kNotExist;
|
|
|
|
CXFA_Calculate* calc = GetCalculateIfExists();
|
|
if (!calc)
|
|
return XFA_EventError::kNotExist;
|
|
if (IsUserInteractive())
|
|
return XFA_EventError::kDisabled;
|
|
|
|
CXFA_EventParam EventParam;
|
|
EventParam.m_eType = XFA_EVENT_Calculate;
|
|
XFA_EventError iRet =
|
|
ExecuteScript(pDocView, calc->GetScriptIfExists(), &EventParam);
|
|
if (iRet != XFA_EventError::kSuccess)
|
|
return iRet;
|
|
|
|
if (GetRawValue() != EventParam.m_wsResult) {
|
|
SetValue(XFA_VALUEPICTURE_Raw, EventParam.m_wsResult);
|
|
pDocView->UpdateUIDisplay(this, nullptr);
|
|
}
|
|
return XFA_EventError::kSuccess;
|
|
}
|
|
|
|
void CXFA_Node::ProcessScriptTestValidate(CXFA_FFDocView* pDocView,
|
|
CXFA_Validate* validate,
|
|
XFA_EventError iRet,
|
|
bool bRetValue,
|
|
bool bVersionFlag) {
|
|
if (iRet != XFA_EventError::kSuccess)
|
|
return;
|
|
if (bRetValue)
|
|
return;
|
|
|
|
IXFA_AppProvider* pAppProvider =
|
|
pDocView->GetDoc()->GetApp()->GetAppProvider();
|
|
if (!pAppProvider)
|
|
return;
|
|
|
|
WideString wsTitle = pAppProvider->GetAppTitle();
|
|
WideString wsScriptMsg = validate->GetScriptMessageText();
|
|
if (validate->GetScriptTest() == XFA_AttributeValue::Warning) {
|
|
if (IsUserInteractive())
|
|
return;
|
|
if (wsScriptMsg.IsEmpty())
|
|
wsScriptMsg = GetValidateMessage(false, bVersionFlag);
|
|
|
|
if (bVersionFlag) {
|
|
pAppProvider->MsgBox(wsScriptMsg, wsTitle,
|
|
static_cast<uint32_t>(AlertIcon::kWarning),
|
|
static_cast<uint32_t>(AlertButton::kOK));
|
|
return;
|
|
}
|
|
if (pAppProvider->MsgBox(wsScriptMsg, wsTitle,
|
|
static_cast<uint32_t>(AlertIcon::kWarning),
|
|
static_cast<uint32_t>(AlertButton::kYesNo)) ==
|
|
static_cast<uint32_t>(AlertReturn::kYes)) {
|
|
SetFlag(XFA_NodeFlag_UserInteractive);
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (wsScriptMsg.IsEmpty())
|
|
wsScriptMsg = GetValidateMessage(true, bVersionFlag);
|
|
pAppProvider->MsgBox(wsScriptMsg, wsTitle,
|
|
static_cast<uint32_t>(AlertIcon::kError),
|
|
static_cast<uint32_t>(AlertButton::kOK));
|
|
}
|
|
|
|
XFA_EventError CXFA_Node::ProcessFormatTestValidate(CXFA_FFDocView* pDocView,
|
|
CXFA_Validate* validate,
|
|
bool bVersionFlag) {
|
|
WideString wsPicture = validate->GetPicture();
|
|
if (wsPicture.IsEmpty())
|
|
return XFA_EventError::kNotExist;
|
|
|
|
WideString wsRawValue = GetRawValue();
|
|
if (wsRawValue.IsEmpty())
|
|
return XFA_EventError::kError;
|
|
|
|
LocaleIface* pLocale = GetLocale();
|
|
if (!pLocale)
|
|
return XFA_EventError::kNotExist;
|
|
|
|
CXFA_LocaleValue lcValue = XFA_GetLocaleValue(this);
|
|
if (lcValue.ValidateValue(lcValue.GetValue(), wsPicture, pLocale, nullptr))
|
|
return XFA_EventError::kSuccess;
|
|
|
|
IXFA_AppProvider* pAppProvider =
|
|
pDocView->GetDoc()->GetApp()->GetAppProvider();
|
|
if (!pAppProvider)
|
|
return XFA_EventError::kNotExist;
|
|
|
|
WideString wsFormatMsg = validate->GetFormatMessageText();
|
|
WideString wsTitle = pAppProvider->GetAppTitle();
|
|
if (validate->GetFormatTest() == XFA_AttributeValue::Error) {
|
|
if (wsFormatMsg.IsEmpty())
|
|
wsFormatMsg = GetValidateMessage(true, bVersionFlag);
|
|
pAppProvider->MsgBox(wsFormatMsg, wsTitle,
|
|
static_cast<uint32_t>(AlertIcon::kError),
|
|
static_cast<uint32_t>(AlertButton::kOK));
|
|
return XFA_EventError::kError;
|
|
}
|
|
|
|
if (wsFormatMsg.IsEmpty())
|
|
wsFormatMsg = GetValidateMessage(false, bVersionFlag);
|
|
|
|
if (bVersionFlag) {
|
|
pAppProvider->MsgBox(wsFormatMsg, wsTitle,
|
|
static_cast<uint32_t>(AlertIcon::kWarning),
|
|
static_cast<uint32_t>(AlertButton::kOK));
|
|
return XFA_EventError::kError;
|
|
}
|
|
|
|
if (pAppProvider->MsgBox(wsFormatMsg, wsTitle,
|
|
static_cast<uint32_t>(AlertIcon::kWarning),
|
|
static_cast<uint32_t>(AlertButton::kYesNo)) ==
|
|
static_cast<uint32_t>(AlertReturn::kYes)) {
|
|
SetFlag(XFA_NodeFlag_UserInteractive);
|
|
}
|
|
|
|
return XFA_EventError::kError;
|
|
}
|
|
|
|
XFA_EventError CXFA_Node::ProcessNullTestValidate(CXFA_FFDocView* pDocView,
|
|
CXFA_Validate* validate,
|
|
int32_t iFlags,
|
|
bool bVersionFlag) {
|
|
if (!GetValue(XFA_VALUEPICTURE_Raw).IsEmpty())
|
|
return XFA_EventError::kSuccess;
|
|
if (m_bIsNull && m_bPreNull)
|
|
return XFA_EventError::kSuccess;
|
|
|
|
XFA_AttributeValue eNullTest = validate->GetNullTest();
|
|
WideString wsNullMsg = validate->GetNullMessageText();
|
|
if (iFlags & 0x01) {
|
|
XFA_EventError iRet = XFA_EventError::kSuccess;
|
|
if (eNullTest != XFA_AttributeValue::Disabled)
|
|
iRet = XFA_EventError::kError;
|
|
|
|
if (wsNullMsg.IsEmpty())
|
|
return iRet;
|
|
|
|
if (eNullTest != XFA_AttributeValue::Disabled) {
|
|
pDocView->m_arrNullTestMsg.push_back(wsNullMsg);
|
|
return XFA_EventError::kError;
|
|
}
|
|
return XFA_EventError::kSuccess;
|
|
}
|
|
if (wsNullMsg.IsEmpty() && bVersionFlag &&
|
|
eNullTest != XFA_AttributeValue::Disabled) {
|
|
return XFA_EventError::kError;
|
|
}
|
|
IXFA_AppProvider* pAppProvider =
|
|
pDocView->GetDoc()->GetApp()->GetAppProvider();
|
|
if (!pAppProvider)
|
|
return XFA_EventError::kNotExist;
|
|
|
|
WideString wsCaptionName;
|
|
WideString wsTitle = pAppProvider->GetAppTitle();
|
|
switch (eNullTest) {
|
|
case XFA_AttributeValue::Error: {
|
|
if (wsNullMsg.IsEmpty()) {
|
|
wsCaptionName = GetValidateCaptionName(bVersionFlag);
|
|
wsNullMsg = wsCaptionName + L" cannot be blank.";
|
|
}
|
|
pAppProvider->MsgBox(wsNullMsg, wsTitle,
|
|
static_cast<uint32_t>(AlertIcon::kStatus),
|
|
static_cast<uint32_t>(AlertButton::kOK));
|
|
return XFA_EventError::kError;
|
|
}
|
|
case XFA_AttributeValue::Warning: {
|
|
if (IsUserInteractive())
|
|
return XFA_EventError::kSuccess;
|
|
|
|
if (wsNullMsg.IsEmpty()) {
|
|
wsCaptionName = GetValidateCaptionName(bVersionFlag);
|
|
wsNullMsg = wsCaptionName +
|
|
L" cannot be blank. To ignore validations for " +
|
|
wsCaptionName + L", click Ignore.";
|
|
}
|
|
if (pAppProvider->MsgBox(wsNullMsg, wsTitle,
|
|
static_cast<uint32_t>(AlertIcon::kWarning),
|
|
static_cast<uint32_t>(AlertButton::kYesNo)) ==
|
|
static_cast<uint32_t>(AlertReturn::kYes)) {
|
|
SetFlag(XFA_NodeFlag_UserInteractive);
|
|
}
|
|
return XFA_EventError::kError;
|
|
}
|
|
case XFA_AttributeValue::Disabled:
|
|
default:
|
|
break;
|
|
}
|
|
return XFA_EventError::kSuccess;
|
|
}
|
|
|
|
XFA_EventError CXFA_Node::ProcessValidate(CXFA_FFDocView* pDocView,
|
|
int32_t iFlags) {
|
|
if (GetElementType() == XFA_Element::Draw)
|
|
return XFA_EventError::kNotExist;
|
|
|
|
CXFA_Validate* validate = GetValidateIfExists();
|
|
if (!validate)
|
|
return XFA_EventError::kNotExist;
|
|
|
|
bool bInitDoc = validate->NeedsInitApp();
|
|
bool bStatus = pDocView->GetLayoutStatus() < XFA_DOCVIEW_LAYOUTSTATUS_End;
|
|
XFA_EventError iFormat = XFA_EventError::kNotExist;
|
|
XFA_EventError iRet = XFA_EventError::kNotExist;
|
|
CXFA_Script* script = validate->GetScriptIfExists();
|
|
bool bRet = false;
|
|
bool hasBoolResult = (bInitDoc || bStatus) && GetRawValue().IsEmpty();
|
|
if (script) {
|
|
CXFA_EventParam eParam;
|
|
eParam.m_eType = XFA_EVENT_Validate;
|
|
eParam.m_pTarget = this;
|
|
std::tie(iRet, bRet) = ExecuteBoolScript(pDocView, script, &eParam);
|
|
}
|
|
|
|
XFA_VERSION version = pDocView->GetDoc()->GetXFADoc()->GetCurVersionMode();
|
|
bool bVersionFlag = version < XFA_VERSION_208;
|
|
|
|
if (bInitDoc) {
|
|
validate->ClearFlag(XFA_NodeFlag_NeedsInitApp);
|
|
} else {
|
|
iFormat = ProcessFormatTestValidate(pDocView, validate, bVersionFlag);
|
|
if (!bVersionFlag)
|
|
bVersionFlag = pDocView->GetDoc()->GetXFADoc()->is_scripting();
|
|
XFA_EventErrorAccumulate(
|
|
&iRet,
|
|
ProcessNullTestValidate(pDocView, validate, iFlags, bVersionFlag));
|
|
}
|
|
if (iFormat != XFA_EventError::kSuccess && hasBoolResult)
|
|
ProcessScriptTestValidate(pDocView, validate, iRet, bRet, bVersionFlag);
|
|
|
|
XFA_EventErrorAccumulate(&iRet, iFormat);
|
|
return iRet;
|
|
}
|
|
|
|
WideString CXFA_Node::GetValidateCaptionName(bool bVersionFlag) {
|
|
WideString wsCaptionName;
|
|
|
|
if (!bVersionFlag) {
|
|
CXFA_Caption* caption = GetCaptionIfExists();
|
|
if (caption) {
|
|
CXFA_Value* capValue = caption->GetValueIfExists();
|
|
if (capValue) {
|
|
CXFA_Text* captionText = capValue->GetTextIfExists();
|
|
if (captionText)
|
|
wsCaptionName = captionText->GetContent();
|
|
}
|
|
}
|
|
}
|
|
if (!wsCaptionName.IsEmpty())
|
|
return wsCaptionName;
|
|
return JSObject()->GetCData(XFA_Attribute::Name);
|
|
}
|
|
|
|
WideString CXFA_Node::GetValidateMessage(bool bError, bool bVersionFlag) {
|
|
WideString wsCaptionName = GetValidateCaptionName(bVersionFlag);
|
|
if (bVersionFlag)
|
|
return wsCaptionName + L" validation failed";
|
|
WideString result =
|
|
L"The value you entered for " + wsCaptionName + L" is invalid.";
|
|
if (!bError) {
|
|
result +=
|
|
L" To ignore validations for " + wsCaptionName + L", click Ignore.";
|
|
}
|
|
return result;
|
|
}
|
|
|
|
XFA_EventError CXFA_Node::ExecuteScript(CXFA_FFDocView* pDocView,
|
|
CXFA_Script* script,
|
|
CXFA_EventParam* pEventParam) {
|
|
return ExecuteBoolScript(pDocView, script, pEventParam).first;
|
|
}
|
|
|
|
std::pair<XFA_EventError, bool> CXFA_Node::ExecuteBoolScript(
|
|
CXFA_FFDocView* pDocView,
|
|
CXFA_Script* script,
|
|
CXFA_EventParam* pEventParam) {
|
|
if (m_ExecuteRecursionDepth > kMaxExecuteRecursion)
|
|
return {XFA_EventError::kSuccess, false};
|
|
|
|
ASSERT(pEventParam);
|
|
if (!script)
|
|
return {XFA_EventError::kNotExist, false};
|
|
if (script->GetRunAt() == XFA_AttributeValue::Server)
|
|
return {XFA_EventError::kDisabled, false};
|
|
|
|
WideString wsExpression = script->GetExpression();
|
|
if (wsExpression.IsEmpty())
|
|
return {XFA_EventError::kNotExist, false};
|
|
|
|
CXFA_Script::Type eScriptType = script->GetContentType();
|
|
if (eScriptType == CXFA_Script::Type::Unknown)
|
|
return {XFA_EventError::kSuccess, false};
|
|
|
|
CXFA_FFDoc* pDoc = pDocView->GetDoc();
|
|
CFXJSE_Engine* pContext = pDoc->GetXFADoc()->GetScriptContext();
|
|
pContext->SetEventParam(pEventParam);
|
|
pContext->SetRunAtType(script->GetRunAt());
|
|
|
|
std::vector<CXFA_Node*> refNodes;
|
|
if (pEventParam->m_eType == XFA_EVENT_InitCalculate ||
|
|
pEventParam->m_eType == XFA_EVENT_Calculate) {
|
|
pContext->SetNodesOfRunScript(&refNodes);
|
|
}
|
|
|
|
auto pTmpRetValue = pdfium::MakeUnique<CFXJSE_Value>(pContext->GetIsolate());
|
|
bool bRet = false;
|
|
{
|
|
AutoRestorer<uint8_t> restorer(&m_ExecuteRecursionDepth);
|
|
++m_ExecuteRecursionDepth;
|
|
bRet = pContext->RunScript(eScriptType, wsExpression.AsStringView(),
|
|
pTmpRetValue.get(), this);
|
|
}
|
|
|
|
XFA_EventError iRet = XFA_EventError::kError;
|
|
if (bRet) {
|
|
iRet = XFA_EventError::kSuccess;
|
|
if (pEventParam->m_eType == XFA_EVENT_Calculate ||
|
|
pEventParam->m_eType == XFA_EVENT_InitCalculate) {
|
|
if (!pTmpRetValue->IsUndefined()) {
|
|
if (!pTmpRetValue->IsNull())
|
|
pEventParam->m_wsResult = pTmpRetValue->ToWideString();
|
|
|
|
iRet = XFA_EventError::kSuccess;
|
|
} else {
|
|
iRet = XFA_EventError::kError;
|
|
}
|
|
if (pEventParam->m_eType == XFA_EVENT_InitCalculate) {
|
|
if ((iRet == XFA_EventError::kSuccess) &&
|
|
(GetRawValue() != pEventParam->m_wsResult)) {
|
|
SetValue(XFA_VALUEPICTURE_Raw, pEventParam->m_wsResult);
|
|
pDocView->AddValidateNode(this);
|
|
}
|
|
}
|
|
for (CXFA_Node* pRefNode : refNodes) {
|
|
if (pRefNode == this)
|
|
continue;
|
|
|
|
CXFA_CalcData* pGlobalData = pRefNode->JSObject()->GetCalcData();
|
|
if (!pGlobalData) {
|
|
pRefNode->JSObject()->SetCalcData(
|
|
pdfium::MakeUnique<CXFA_CalcData>());
|
|
pGlobalData = pRefNode->JSObject()->GetCalcData();
|
|
}
|
|
if (!pdfium::ContainsValue(pGlobalData->m_Globals, this))
|
|
pGlobalData->m_Globals.push_back(this);
|
|
}
|
|
}
|
|
}
|
|
pContext->SetNodesOfRunScript(nullptr);
|
|
pContext->SetEventParam(nullptr);
|
|
|
|
return {iRet, pTmpRetValue->IsBoolean() && pTmpRetValue->ToBoolean()};
|
|
}
|
|
|
|
std::pair<XFA_FFWidgetType, CXFA_Ui*>
|
|
CXFA_Node::CreateChildUIAndValueNodesIfNeeded() {
|
|
XFA_Element eType = GetElementType();
|
|
ASSERT(eType == XFA_Element::Field || eType == XFA_Element::Draw);
|
|
|
|
// Both Field and Draw have a UI property. We should always be able to
|
|
// retrieve or create the UI element. If we can't something is wrong.
|
|
CXFA_Ui* pUI = JSObject()->GetOrCreateProperty<CXFA_Ui>(0, XFA_Element::Ui);
|
|
ASSERT(pUI);
|
|
|
|
CXFA_Node* pUIChild = nullptr;
|
|
// Search through the children of the UI node to see if we have any of our
|
|
// One-Of entries. If so, that is the node associated with our UI.
|
|
for (CXFA_Node* pChild = pUI->GetFirstChild(); pChild;
|
|
pChild = pChild->GetNextSibling()) {
|
|
if (pUI->IsAOneOfChild(pChild)) {
|
|
pUIChild = pChild;
|
|
break;
|
|
}
|
|
}
|
|
|
|
XFA_FFWidgetType widget_type = XFA_FFWidgetType::kNone;
|
|
XFA_Element expected_ui_child_type = XFA_Element::Unknown;
|
|
|
|
// Both Field and Draw nodes have a Value child. So, we should either always
|
|
// have it, or always create it. If we don't get the Value child for some
|
|
// reason something has gone really wrong.
|
|
CXFA_Value* value =
|
|
JSObject()->GetOrCreateProperty<CXFA_Value>(0, XFA_Element::Value);
|
|
ASSERT(value);
|
|
|
|
// The Value nodes only have One-Of children. So, if we have a first child
|
|
// that child must be the type we want to use.
|
|
CXFA_Node* child = value->GetFirstChild();
|
|
if (child) {
|
|
switch (child->GetElementType()) {
|
|
case XFA_Element::Boolean:
|
|
expected_ui_child_type = XFA_Element::CheckButton;
|
|
break;
|
|
case XFA_Element::Integer:
|
|
case XFA_Element::Decimal:
|
|
case XFA_Element::Float:
|
|
expected_ui_child_type = XFA_Element::NumericEdit;
|
|
break;
|
|
case XFA_Element::ExData:
|
|
case XFA_Element::Text:
|
|
expected_ui_child_type = XFA_Element::TextEdit;
|
|
widget_type = XFA_FFWidgetType::kText;
|
|
break;
|
|
case XFA_Element::Date:
|
|
case XFA_Element::Time:
|
|
case XFA_Element::DateTime:
|
|
expected_ui_child_type = XFA_Element::DateTimeEdit;
|
|
break;
|
|
case XFA_Element::Image:
|
|
expected_ui_child_type = XFA_Element::ImageEdit;
|
|
widget_type = XFA_FFWidgetType::kImage;
|
|
break;
|
|
case XFA_Element::Arc:
|
|
expected_ui_child_type = XFA_Element::DefaultUi;
|
|
widget_type = XFA_FFWidgetType::kArc;
|
|
break;
|
|
case XFA_Element::Line:
|
|
expected_ui_child_type = XFA_Element::DefaultUi;
|
|
widget_type = XFA_FFWidgetType::kLine;
|
|
break;
|
|
case XFA_Element::Rectangle:
|
|
expected_ui_child_type = XFA_Element::DefaultUi;
|
|
widget_type = XFA_FFWidgetType::kRectangle;
|
|
break;
|
|
default:
|
|
NOTREACHED();
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (eType == XFA_Element::Draw) {
|
|
if (pUIChild && pUIChild->GetElementType() == XFA_Element::TextEdit) {
|
|
widget_type = XFA_FFWidgetType::kText;
|
|
} else if (pUIChild &&
|
|
pUIChild->GetElementType() == XFA_Element::ImageEdit) {
|
|
widget_type = XFA_FFWidgetType::kImage;
|
|
} else if (widget_type == XFA_FFWidgetType::kNone) {
|
|
widget_type = XFA_FFWidgetType::kText;
|
|
}
|
|
} else if (eType == XFA_Element::Field) {
|
|
if (pUIChild && pUIChild->GetElementType() == XFA_Element::DefaultUi) {
|
|
widget_type = XFA_FFWidgetType::kTextEdit;
|
|
} else if (pUIChild) {
|
|
widget_type = pUIChild->GetDefaultFFWidgetType();
|
|
} else if (expected_ui_child_type == XFA_Element::Unknown) {
|
|
widget_type = XFA_FFWidgetType::kTextEdit;
|
|
}
|
|
} else {
|
|
NOTREACHED();
|
|
}
|
|
|
|
if (!pUIChild) {
|
|
if (expected_ui_child_type == XFA_Element::Unknown)
|
|
expected_ui_child_type = XFA_Element::TextEdit;
|
|
pUIChild = pUI->JSObject()->GetOrCreateProperty<CXFA_Node>(
|
|
0, expected_ui_child_type);
|
|
}
|
|
|
|
CreateValueNodeIfNeeded(value, pUIChild);
|
|
return {widget_type, pUI};
|
|
}
|
|
|
|
XFA_FFWidgetType CXFA_Node::GetDefaultFFWidgetType() const {
|
|
NOTREACHED();
|
|
return XFA_FFWidgetType::kNone;
|
|
}
|
|
|
|
CXFA_Node* CXFA_Node::CreateUINodeIfNeeded(CXFA_Ui* ui, XFA_Element type) {
|
|
return ui->JSObject()->GetOrCreateProperty<CXFA_Node>(0, type);
|
|
}
|
|
|
|
void CXFA_Node::CreateValueNodeIfNeeded(CXFA_Value* value,
|
|
CXFA_Node* pUIChild) {
|
|
// Value nodes only have one child. If we have one already we're done.
|
|
if (value->GetFirstChild())
|
|
return;
|
|
|
|
// Create the Value node for our UI if needed.
|
|
XFA_Element valueType = pUIChild->GetValueNodeType();
|
|
if (pUIChild->GetElementType() == XFA_Element::CheckButton) {
|
|
CXFA_Items* pItems = GetChild<CXFA_Items>(0, XFA_Element::Items, false);
|
|
if (pItems) {
|
|
CXFA_Node* pItem =
|
|
pItems->GetChild<CXFA_Node>(0, XFA_Element::Unknown, false);
|
|
if (pItem)
|
|
valueType = pItem->GetElementType();
|
|
}
|
|
}
|
|
value->JSObject()->GetOrCreateProperty<CXFA_Node>(0, valueType);
|
|
}
|
|
|
|
XFA_Element CXFA_Node::GetValueNodeType() const {
|
|
return XFA_Element::Text;
|
|
}
|
|
|
|
CXFA_Node* CXFA_Node::GetUIChildNode() {
|
|
ASSERT(HasCreatedUIWidget());
|
|
|
|
if (ff_widget_type_ != XFA_FFWidgetType::kNone)
|
|
return ui_ ? ui_->GetFirstChild() : nullptr;
|
|
|
|
XFA_Element type = GetElementType();
|
|
if (type == XFA_Element::Field || type == XFA_Element::Draw) {
|
|
std::tie(ff_widget_type_, ui_) = CreateChildUIAndValueNodesIfNeeded();
|
|
} else if (type == XFA_Element::Subform) {
|
|
ff_widget_type_ = XFA_FFWidgetType::kSubform;
|
|
} else if (type == XFA_Element::ExclGroup) {
|
|
ff_widget_type_ = XFA_FFWidgetType::kExclGroup;
|
|
} else {
|
|
NOTREACHED();
|
|
}
|
|
return ui_ ? ui_->GetFirstChild() : nullptr;
|
|
}
|
|
|
|
XFA_FFWidgetType CXFA_Node::GetFFWidgetType() {
|
|
GetUIChildNode();
|
|
return ff_widget_type_;
|
|
}
|
|
|
|
CXFA_Border* CXFA_Node::GetUIBorder() {
|
|
CXFA_Node* pUIChild = GetUIChildNode();
|
|
return pUIChild ? pUIChild->JSObject()->GetProperty<CXFA_Border>(
|
|
0, XFA_Element::Border)
|
|
: nullptr;
|
|
}
|
|
|
|
CFX_RectF CXFA_Node::GetUIMargin() {
|
|
CXFA_Node* pUIChild = GetUIChildNode();
|
|
if (!pUIChild)
|
|
return CFX_RectF();
|
|
|
|
CXFA_Margin* mgUI =
|
|
pUIChild->JSObject()->GetProperty<CXFA_Margin>(0, XFA_Element::Margin);
|
|
if (!mgUI)
|
|
return CFX_RectF();
|
|
|
|
CXFA_Border* border = GetUIBorder();
|
|
if (border && border->GetPresence() != XFA_AttributeValue::Visible)
|
|
return CFX_RectF();
|
|
|
|
Optional<float> left = mgUI->TryLeftInset();
|
|
Optional<float> top = mgUI->TryTopInset();
|
|
Optional<float> right = mgUI->TryRightInset();
|
|
Optional<float> bottom = mgUI->TryBottomInset();
|
|
if (border) {
|
|
bool bVisible = false;
|
|
float fThickness = 0;
|
|
XFA_AttributeValue iType = XFA_AttributeValue::Unknown;
|
|
std::tie(iType, bVisible, fThickness) = border->Get3DStyle();
|
|
if (!left || !top || !right || !bottom) {
|
|
std::vector<CXFA_Stroke*> strokes = border->GetStrokes();
|
|
if (!top)
|
|
top = GetEdgeThickness(strokes, bVisible, 0);
|
|
if (!right)
|
|
right = GetEdgeThickness(strokes, bVisible, 1);
|
|
if (!bottom)
|
|
bottom = GetEdgeThickness(strokes, bVisible, 2);
|
|
if (!left)
|
|
left = GetEdgeThickness(strokes, bVisible, 3);
|
|
}
|
|
}
|
|
return CFX_RectF(left.value_or(0.0), top.value_or(0.0), right.value_or(0.0),
|
|
bottom.value_or(0.0));
|
|
}
|
|
|
|
std::vector<CXFA_Event*> CXFA_Node::GetEventByActivity(
|
|
XFA_AttributeValue iActivity,
|
|
bool bIsFormReady) {
|
|
std::vector<CXFA_Event*> events;
|
|
for (CXFA_Node* node : GetNodeListForType(XFA_Element::Event)) {
|
|
auto* event = static_cast<CXFA_Event*>(node);
|
|
if (event->GetActivity() != iActivity)
|
|
continue;
|
|
|
|
if (iActivity != XFA_AttributeValue::Ready) {
|
|
events.push_back(event);
|
|
continue;
|
|
}
|
|
|
|
WideString wsRef = event->GetRef();
|
|
if (bIsFormReady) {
|
|
if (wsRef == WideStringView(L"$form"))
|
|
events.push_back(event);
|
|
continue;
|
|
}
|
|
|
|
if (wsRef == WideStringView(L"$layout"))
|
|
events.push_back(event);
|
|
}
|
|
return events;
|
|
}
|
|
|
|
void CXFA_Node::ResetData() {
|
|
WideString wsValue;
|
|
switch (GetFFWidgetType()) {
|
|
case XFA_FFWidgetType::kImageEdit: {
|
|
CXFA_Value* imageValue = GetDefaultValueIfExists();
|
|
CXFA_Image* image = imageValue ? imageValue->GetImageIfExists() : nullptr;
|
|
WideString wsContentType, wsHref;
|
|
if (image) {
|
|
wsValue = image->GetContent();
|
|
wsContentType = image->GetContentType();
|
|
wsHref = image->GetHref();
|
|
}
|
|
SetImageEdit(wsContentType, wsHref, wsValue);
|
|
break;
|
|
}
|
|
case XFA_FFWidgetType::kExclGroup: {
|
|
CXFA_Node* pNextChild = GetFirstContainerChild();
|
|
while (pNextChild) {
|
|
CXFA_Node* pChild = pNextChild;
|
|
if (!pChild->IsWidgetReady())
|
|
continue;
|
|
|
|
bool done = false;
|
|
if (wsValue.IsEmpty()) {
|
|
CXFA_Value* defValue = pChild->GetDefaultValueIfExists();
|
|
if (defValue) {
|
|
wsValue = defValue->GetChildValueContent();
|
|
SetValue(XFA_VALUEPICTURE_Raw, wsValue);
|
|
pChild->SetValue(XFA_VALUEPICTURE_Raw, wsValue);
|
|
done = true;
|
|
}
|
|
}
|
|
if (!done) {
|
|
CXFA_Items* pItems =
|
|
pChild->GetChild<CXFA_Items>(0, XFA_Element::Items, false);
|
|
if (!pItems)
|
|
continue;
|
|
|
|
WideString itemText;
|
|
if (pItems->CountChildren(XFA_Element::Unknown, false) > 1) {
|
|
itemText =
|
|
pItems->GetChild<CXFA_Node>(1, XFA_Element::Unknown, false)
|
|
->JSObject()
|
|
->GetContent(false);
|
|
}
|
|
pChild->SetValue(XFA_VALUEPICTURE_Raw, itemText);
|
|
}
|
|
pNextChild = pChild->GetNextContainerSibling();
|
|
}
|
|
break;
|
|
}
|
|
case XFA_FFWidgetType::kChoiceList:
|
|
ClearAllSelections();
|
|
FALLTHROUGH;
|
|
default: {
|
|
CXFA_Value* defValue = GetDefaultValueIfExists();
|
|
if (defValue)
|
|
wsValue = defValue->GetChildValueContent();
|
|
|
|
SetValue(XFA_VALUEPICTURE_Raw, wsValue);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void CXFA_Node::SetImageEdit(const WideString& wsContentType,
|
|
const WideString& wsHref,
|
|
const WideString& wsData) {
|
|
CXFA_Value* formValue = GetFormValueIfExists();
|
|
CXFA_Image* image = formValue ? formValue->GetImageIfExists() : nullptr;
|
|
if (image) {
|
|
image->SetContentType(WideString(wsContentType));
|
|
image->SetHref(wsHref);
|
|
}
|
|
|
|
JSObject()->SetContent(wsData, GetFormatDataValue(wsData), true, false, true);
|
|
|
|
CXFA_Node* pBind = GetBindData();
|
|
if (!pBind) {
|
|
if (image)
|
|
image->SetTransferEncoding(XFA_AttributeValue::Base64);
|
|
return;
|
|
}
|
|
pBind->JSObject()->SetCData(XFA_Attribute::ContentType, wsContentType, false,
|
|
false);
|
|
CXFA_Node* pHrefNode = pBind->GetFirstChild();
|
|
if (pHrefNode) {
|
|
pHrefNode->JSObject()->SetCData(XFA_Attribute::Value, wsHref, false, false);
|
|
return;
|
|
}
|
|
CFX_XMLElement* pElement = ToXMLElement(pBind->GetXMLMappingNode());
|
|
pElement->SetAttribute(L"href", wsHref);
|
|
}
|
|
|
|
void CXFA_Node::CalcCaptionSize(CXFA_FFDoc* doc, CFX_SizeF* pszCap) {
|
|
CXFA_Caption* caption = GetCaptionIfExists();
|
|
if (!caption || !caption->IsVisible())
|
|
return;
|
|
|
|
LoadCaption(doc);
|
|
|
|
const float fCapReserve = caption->GetReserve();
|
|
const XFA_AttributeValue iCapPlacement = caption->GetPlacementType();
|
|
const bool bReserveExit = fCapReserve > 0.01;
|
|
const bool bVert = iCapPlacement == XFA_AttributeValue::Top ||
|
|
iCapPlacement == XFA_AttributeValue::Bottom;
|
|
CXFA_TextLayout* pCapTextLayout =
|
|
m_pLayoutData->AsFieldLayoutData()->m_pCapTextLayout.get();
|
|
if (pCapTextLayout) {
|
|
if (!bVert && GetFFWidgetType() != XFA_FFWidgetType::kButton)
|
|
pszCap->width = fCapReserve;
|
|
|
|
CFX_SizeF minSize;
|
|
*pszCap = pCapTextLayout->CalcSize(minSize, *pszCap);
|
|
if (bReserveExit)
|
|
bVert ? pszCap->height = fCapReserve : pszCap->width = fCapReserve;
|
|
} else {
|
|
float fFontSize = 10.0f;
|
|
CXFA_Font* font = caption->GetFontIfExists();
|
|
if (font) {
|
|
fFontSize = font->GetFontSize();
|
|
} else {
|
|
CXFA_Font* widgetfont = GetFontIfExists();
|
|
if (widgetfont)
|
|
fFontSize = widgetfont->GetFontSize();
|
|
}
|
|
|
|
if (bVert) {
|
|
pszCap->height = fCapReserve > 0 ? fCapReserve : fFontSize;
|
|
} else {
|
|
pszCap->width = fCapReserve > 0 ? fCapReserve : 0;
|
|
pszCap->height = fFontSize;
|
|
}
|
|
}
|
|
|
|
CXFA_Margin* captionMargin = caption->GetMarginIfExists();
|
|
if (!captionMargin)
|
|
return;
|
|
|
|
float fLeftInset = captionMargin->GetLeftInset();
|
|
float fTopInset = captionMargin->GetTopInset();
|
|
float fRightInset = captionMargin->GetRightInset();
|
|
float fBottomInset = captionMargin->GetBottomInset();
|
|
if (bReserveExit) {
|
|
bVert ? (pszCap->width += fLeftInset + fRightInset)
|
|
: (pszCap->height += fTopInset + fBottomInset);
|
|
} else {
|
|
pszCap->width += fLeftInset + fRightInset;
|
|
pszCap->height += fTopInset + fBottomInset;
|
|
}
|
|
}
|
|
|
|
bool CXFA_Node::CalculateFieldAutoSize(CXFA_FFDoc* doc, CFX_SizeF* pSize) {
|
|
CFX_SizeF szCap;
|
|
CalcCaptionSize(doc, &szCap);
|
|
|
|
CFX_RectF rtUIMargin = GetUIMargin();
|
|
pSize->width += rtUIMargin.left + rtUIMargin.width;
|
|
pSize->height += rtUIMargin.top + rtUIMargin.height;
|
|
if (szCap.width > 0 && szCap.height > 0) {
|
|
CXFA_Caption* caption = GetCaptionIfExists();
|
|
XFA_AttributeValue placement = caption
|
|
? caption->GetPlacementType()
|
|
: CXFA_Caption::kDefaultPlacementType;
|
|
switch (placement) {
|
|
case XFA_AttributeValue::Left:
|
|
case XFA_AttributeValue::Right:
|
|
case XFA_AttributeValue::Inline: {
|
|
pSize->width += szCap.width;
|
|
pSize->height = std::max(pSize->height, szCap.height);
|
|
} break;
|
|
case XFA_AttributeValue::Top:
|
|
case XFA_AttributeValue::Bottom: {
|
|
pSize->height += szCap.height;
|
|
pSize->width = std::max(pSize->width, szCap.width);
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
return CalculateWidgetAutoSize(pSize);
|
|
}
|
|
|
|
bool CXFA_Node::CalculateWidgetAutoSize(CFX_SizeF* pSize) {
|
|
CXFA_Margin* margin = GetMarginIfExists();
|
|
if (margin) {
|
|
pSize->width += margin->GetLeftInset() + margin->GetRightInset();
|
|
pSize->height += margin->GetTopInset() + margin->GetBottomInset();
|
|
}
|
|
|
|
CXFA_Para* para = GetParaIfExists();
|
|
if (para)
|
|
pSize->width += para->GetMarginLeft() + para->GetTextIndent();
|
|
|
|
Optional<float> width = TryWidth();
|
|
if (width) {
|
|
pSize->width = *width;
|
|
} else {
|
|
Optional<float> min = TryMinWidth();
|
|
if (min)
|
|
pSize->width = std::max(pSize->width, *min);
|
|
|
|
Optional<float> max = TryMaxWidth();
|
|
if (max && *max > 0)
|
|
pSize->width = std::min(pSize->width, *max);
|
|
}
|
|
|
|
Optional<float> height = TryHeight();
|
|
if (height) {
|
|
pSize->height = *height;
|
|
} else {
|
|
Optional<float> min = TryMinHeight();
|
|
if (min)
|
|
pSize->height = std::max(pSize->height, *min);
|
|
|
|
Optional<float> max = TryMaxHeight();
|
|
if (max && *max > 0)
|
|
pSize->height = std::min(pSize->height, *max);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void CXFA_Node::CalculateTextContentSize(CXFA_FFDoc* doc, CFX_SizeF* pSize) {
|
|
float fFontSize = GetFontSize();
|
|
WideString wsText = GetValue(XFA_VALUEPICTURE_Display);
|
|
if (wsText.IsEmpty()) {
|
|
pSize->height += fFontSize;
|
|
return;
|
|
}
|
|
|
|
if (wsText.Back() == L'\n')
|
|
wsText += L'\n';
|
|
|
|
CXFA_FieldLayoutData* layoutData = m_pLayoutData->AsFieldLayoutData();
|
|
if (!layoutData->m_pTextOut) {
|
|
layoutData->m_pTextOut = pdfium::MakeUnique<CFDE_TextOut>();
|
|
CFDE_TextOut* pTextOut = layoutData->m_pTextOut.get();
|
|
pTextOut->SetFont(GetFDEFont(doc));
|
|
pTextOut->SetFontSize(fFontSize);
|
|
pTextOut->SetLineBreakTolerance(fFontSize * 0.2f);
|
|
pTextOut->SetLineSpace(GetLineHeight());
|
|
|
|
FDE_TextStyle dwStyles;
|
|
dwStyles.last_line_height_ = true;
|
|
if (GetFFWidgetType() == XFA_FFWidgetType::kTextEdit && IsMultiLine())
|
|
dwStyles.line_wrap_ = true;
|
|
|
|
pTextOut->SetStyles(dwStyles);
|
|
}
|
|
layoutData->m_pTextOut->CalcLogicSize(wsText.AsStringView(), pSize);
|
|
}
|
|
|
|
bool CXFA_Node::CalculateTextEditAutoSize(CXFA_FFDoc* doc, CFX_SizeF* pSize) {
|
|
if (pSize->width > 0) {
|
|
CFX_SizeF szOrz = *pSize;
|
|
CFX_SizeF szCap;
|
|
CalcCaptionSize(doc, &szCap);
|
|
bool bCapExit = szCap.width > 0.01 && szCap.height > 0.01;
|
|
XFA_AttributeValue iCapPlacement = XFA_AttributeValue::Unknown;
|
|
if (bCapExit) {
|
|
CXFA_Caption* caption = GetCaptionIfExists();
|
|
iCapPlacement = caption ? caption->GetPlacementType()
|
|
: CXFA_Caption::kDefaultPlacementType;
|
|
switch (iCapPlacement) {
|
|
case XFA_AttributeValue::Left:
|
|
case XFA_AttributeValue::Right:
|
|
case XFA_AttributeValue::Inline: {
|
|
pSize->width -= szCap.width;
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
CFX_RectF rtUIMargin = GetUIMargin();
|
|
pSize->width -= rtUIMargin.left + rtUIMargin.width;
|
|
CXFA_Margin* margin = GetMarginIfExists();
|
|
if (margin)
|
|
pSize->width -= margin->GetLeftInset() + margin->GetRightInset();
|
|
|
|
CalculateTextContentSize(doc, pSize);
|
|
pSize->height += rtUIMargin.top + rtUIMargin.height;
|
|
if (bCapExit) {
|
|
switch (iCapPlacement) {
|
|
case XFA_AttributeValue::Left:
|
|
case XFA_AttributeValue::Right:
|
|
case XFA_AttributeValue::Inline: {
|
|
pSize->height = std::max(pSize->height, szCap.height);
|
|
} break;
|
|
case XFA_AttributeValue::Top:
|
|
case XFA_AttributeValue::Bottom: {
|
|
pSize->height += szCap.height;
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
pSize->width = szOrz.width;
|
|
return CalculateWidgetAutoSize(pSize);
|
|
}
|
|
CalculateTextContentSize(doc, pSize);
|
|
return CalculateFieldAutoSize(doc, pSize);
|
|
}
|
|
|
|
bool CXFA_Node::CalculateCheckButtonAutoSize(CXFA_FFDoc* doc,
|
|
CFX_SizeF* pSize) {
|
|
float fCheckSize = GetCheckButtonSize();
|
|
*pSize = CFX_SizeF(fCheckSize, fCheckSize);
|
|
return CalculateFieldAutoSize(doc, pSize);
|
|
}
|
|
|
|
bool CXFA_Node::CalculatePushButtonAutoSize(CXFA_FFDoc* doc, CFX_SizeF* pSize) {
|
|
CalcCaptionSize(doc, pSize);
|
|
return CalculateWidgetAutoSize(pSize);
|
|
}
|
|
|
|
CFX_SizeF CXFA_Node::CalculateImageSize(float img_width,
|
|
float img_height,
|
|
const CFX_Size& dpi) {
|
|
CFX_RectF rtImage(0, 0, XFA_UnitPx2Pt(img_width, dpi.width),
|
|
XFA_UnitPx2Pt(img_height, dpi.height));
|
|
|
|
CFX_RectF rtFit;
|
|
Optional<float> width = TryWidth();
|
|
if (width) {
|
|
rtFit.width = *width;
|
|
GetWidthWithoutMargin(rtFit.width);
|
|
} else {
|
|
rtFit.width = rtImage.width;
|
|
}
|
|
|
|
Optional<float> height = TryHeight();
|
|
if (height) {
|
|
rtFit.height = *height;
|
|
GetHeightWithoutMargin(rtFit.height);
|
|
} else {
|
|
rtFit.height = rtImage.height;
|
|
}
|
|
|
|
return rtFit.Size();
|
|
}
|
|
|
|
bool CXFA_Node::CalculateImageAutoSize(CXFA_FFDoc* doc, CFX_SizeF* pSize) {
|
|
if (!GetImageImage())
|
|
LoadImageImage(doc);
|
|
|
|
pSize->clear();
|
|
RetainPtr<CFX_DIBitmap> pBitmap = GetImageImage();
|
|
if (!pBitmap)
|
|
return CalculateWidgetAutoSize(pSize);
|
|
|
|
*pSize = CalculateImageSize(pBitmap->GetWidth(), pBitmap->GetHeight(),
|
|
GetImageDpi());
|
|
return CalculateWidgetAutoSize(pSize);
|
|
}
|
|
|
|
bool CXFA_Node::CalculateImageEditAutoSize(CXFA_FFDoc* doc, CFX_SizeF* pSize) {
|
|
if (!GetImageEditImage())
|
|
LoadImageEditImage(doc);
|
|
|
|
pSize->clear();
|
|
RetainPtr<CFX_DIBitmap> pBitmap = GetImageEditImage();
|
|
if (!pBitmap)
|
|
return CalculateFieldAutoSize(doc, pSize);
|
|
|
|
*pSize = CalculateImageSize(pBitmap->GetWidth(), pBitmap->GetHeight(),
|
|
GetImageEditDpi());
|
|
return CalculateFieldAutoSize(doc, pSize);
|
|
}
|
|
|
|
bool CXFA_Node::LoadImageImage(CXFA_FFDoc* doc) {
|
|
InitLayoutData();
|
|
return m_pLayoutData->AsImageLayoutData()->LoadImageData(doc, this);
|
|
}
|
|
|
|
bool CXFA_Node::LoadImageEditImage(CXFA_FFDoc* doc) {
|
|
InitLayoutData();
|
|
return m_pLayoutData->AsFieldLayoutData()->AsImageEditData()->LoadImageData(
|
|
doc, this);
|
|
}
|
|
|
|
CFX_Size CXFA_Node::GetImageDpi() const {
|
|
CXFA_ImageLayoutData* pData = m_pLayoutData->AsImageLayoutData();
|
|
return CFX_Size(pData->m_iImageXDpi, pData->m_iImageYDpi);
|
|
}
|
|
|
|
CFX_Size CXFA_Node::GetImageEditDpi() const {
|
|
CXFA_ImageEditData* pData =
|
|
m_pLayoutData->AsFieldLayoutData()->AsImageEditData();
|
|
return CFX_Size(pData->m_iImageXDpi, pData->m_iImageYDpi);
|
|
}
|
|
|
|
float CXFA_Node::CalculateWidgetAutoWidth(float fWidthCalc) {
|
|
CXFA_Margin* margin = GetMarginIfExists();
|
|
if (margin)
|
|
fWidthCalc += margin->GetLeftInset() + margin->GetRightInset();
|
|
|
|
Optional<float> min = TryMinWidth();
|
|
if (min)
|
|
fWidthCalc = std::max(fWidthCalc, *min);
|
|
|
|
Optional<float> max = TryMaxWidth();
|
|
if (max && *max > 0)
|
|
fWidthCalc = std::min(fWidthCalc, *max);
|
|
|
|
return fWidthCalc;
|
|
}
|
|
|
|
float CXFA_Node::GetWidthWithoutMargin(float fWidthCalc) const {
|
|
CXFA_Margin* margin = GetMarginIfExists();
|
|
if (margin)
|
|
fWidthCalc -= margin->GetLeftInset() + margin->GetRightInset();
|
|
return fWidthCalc;
|
|
}
|
|
|
|
float CXFA_Node::CalculateWidgetAutoHeight(float fHeightCalc) {
|
|
CXFA_Margin* margin = GetMarginIfExists();
|
|
if (margin)
|
|
fHeightCalc += margin->GetTopInset() + margin->GetBottomInset();
|
|
|
|
Optional<float> min = TryMinHeight();
|
|
if (min)
|
|
fHeightCalc = std::max(fHeightCalc, *min);
|
|
|
|
Optional<float> max = TryMaxHeight();
|
|
if (max && *max > 0)
|
|
fHeightCalc = std::min(fHeightCalc, *max);
|
|
|
|
return fHeightCalc;
|
|
}
|
|
|
|
float CXFA_Node::GetHeightWithoutMargin(float fHeightCalc) const {
|
|
CXFA_Margin* margin = GetMarginIfExists();
|
|
if (margin)
|
|
fHeightCalc -= margin->GetTopInset() + margin->GetBottomInset();
|
|
return fHeightCalc;
|
|
}
|
|
|
|
void CXFA_Node::StartWidgetLayout(CXFA_FFDoc* doc,
|
|
float* pCalcWidth,
|
|
float* pCalcHeight) {
|
|
InitLayoutData();
|
|
|
|
if (GetFFWidgetType() == XFA_FFWidgetType::kText) {
|
|
m_pLayoutData->m_fWidgetHeight = TryHeight().value_or(-1);
|
|
StartTextLayout(doc, pCalcWidth, pCalcHeight);
|
|
return;
|
|
}
|
|
if (*pCalcWidth > 0 && *pCalcHeight > 0)
|
|
return;
|
|
|
|
m_pLayoutData->m_fWidgetHeight = -1;
|
|
float fWidth = 0;
|
|
if (*pCalcWidth > 0 && *pCalcHeight < 0) {
|
|
Optional<float> height = TryHeight();
|
|
if (height) {
|
|
*pCalcHeight = *height;
|
|
} else {
|
|
CFX_SizeF size = CalculateAccWidthAndHeight(doc, *pCalcWidth);
|
|
*pCalcWidth = size.width;
|
|
*pCalcHeight = size.height;
|
|
}
|
|
|
|
m_pLayoutData->m_fWidgetHeight = *pCalcHeight;
|
|
return;
|
|
}
|
|
if (*pCalcWidth < 0 && *pCalcHeight < 0) {
|
|
Optional<float> height;
|
|
Optional<float> width = TryWidth();
|
|
if (width) {
|
|
fWidth = *width;
|
|
|
|
height = TryHeight();
|
|
if (height)
|
|
*pCalcHeight = *height;
|
|
}
|
|
if (!width || !height) {
|
|
CFX_SizeF size = CalculateAccWidthAndHeight(doc, fWidth);
|
|
*pCalcWidth = size.width;
|
|
*pCalcHeight = size.height;
|
|
} else {
|
|
*pCalcWidth = fWidth;
|
|
}
|
|
}
|
|
m_pLayoutData->m_fWidgetHeight = *pCalcHeight;
|
|
}
|
|
|
|
CFX_SizeF CXFA_Node::CalculateAccWidthAndHeight(CXFA_FFDoc* doc, float fWidth) {
|
|
CFX_SizeF sz(fWidth, m_pLayoutData->m_fWidgetHeight);
|
|
switch (GetFFWidgetType()) {
|
|
case XFA_FFWidgetType::kBarcode:
|
|
case XFA_FFWidgetType::kChoiceList:
|
|
case XFA_FFWidgetType::kSignature:
|
|
CalculateFieldAutoSize(doc, &sz);
|
|
break;
|
|
case XFA_FFWidgetType::kImageEdit:
|
|
CalculateImageEditAutoSize(doc, &sz);
|
|
break;
|
|
case XFA_FFWidgetType::kButton:
|
|
CalculatePushButtonAutoSize(doc, &sz);
|
|
break;
|
|
case XFA_FFWidgetType::kCheckButton:
|
|
CalculateCheckButtonAutoSize(doc, &sz);
|
|
break;
|
|
case XFA_FFWidgetType::kDateTimeEdit:
|
|
case XFA_FFWidgetType::kNumericEdit:
|
|
case XFA_FFWidgetType::kPasswordEdit:
|
|
case XFA_FFWidgetType::kTextEdit:
|
|
CalculateTextEditAutoSize(doc, &sz);
|
|
break;
|
|
case XFA_FFWidgetType::kImage:
|
|
CalculateImageAutoSize(doc, &sz);
|
|
break;
|
|
case XFA_FFWidgetType::kArc:
|
|
case XFA_FFWidgetType::kLine:
|
|
case XFA_FFWidgetType::kRectangle:
|
|
case XFA_FFWidgetType::kSubform:
|
|
case XFA_FFWidgetType::kExclGroup:
|
|
CalculateWidgetAutoSize(&sz);
|
|
break;
|
|
case XFA_FFWidgetType::kText:
|
|
case XFA_FFWidgetType::kNone:
|
|
break;
|
|
}
|
|
|
|
m_pLayoutData->m_fWidgetHeight = sz.height;
|
|
return sz;
|
|
}
|
|
|
|
Optional<float> CXFA_Node::FindSplitPos(CXFA_FFDocView* pDocView,
|
|
size_t szBlockIndex,
|
|
float fCalcHeight) {
|
|
if (GetFFWidgetType() == XFA_FFWidgetType::kSubform)
|
|
return pdfium::nullopt;
|
|
|
|
switch (GetFFWidgetType()) {
|
|
case XFA_FFWidgetType::kText:
|
|
case XFA_FFWidgetType::kTextEdit:
|
|
case XFA_FFWidgetType::kNumericEdit:
|
|
case XFA_FFWidgetType::kPasswordEdit:
|
|
break;
|
|
default:
|
|
return 0.0f;
|
|
}
|
|
|
|
float fTopInset = 0;
|
|
float fBottomInset = 0;
|
|
if (szBlockIndex == 0) {
|
|
CXFA_Margin* margin = GetMarginIfExists();
|
|
if (margin) {
|
|
fTopInset = margin->GetTopInset();
|
|
fBottomInset = margin->GetBottomInset();
|
|
}
|
|
|
|
CFX_RectF rtUIMargin = GetUIMargin();
|
|
fTopInset += rtUIMargin.top;
|
|
fBottomInset += rtUIMargin.width;
|
|
}
|
|
if (GetFFWidgetType() == XFA_FFWidgetType::kText) {
|
|
float fHeight = fCalcHeight;
|
|
if (szBlockIndex == 0) {
|
|
fCalcHeight -= fTopInset;
|
|
fCalcHeight = std::max(fCalcHeight, 0.0f);
|
|
}
|
|
CXFA_TextLayout* pTextLayout =
|
|
m_pLayoutData->AsTextLayoutData()->GetTextLayout();
|
|
fCalcHeight = pTextLayout->DoSplitLayout(
|
|
szBlockIndex, fCalcHeight, m_pLayoutData->m_fWidgetHeight - fTopInset);
|
|
if (fCalcHeight != 0) {
|
|
if (szBlockIndex == 0)
|
|
fCalcHeight += fTopInset;
|
|
if (fabs(fHeight - fCalcHeight) < kXFAWidgetPrecision)
|
|
return pdfium::nullopt;
|
|
}
|
|
return fCalcHeight;
|
|
}
|
|
|
|
XFA_AttributeValue iCapPlacement = XFA_AttributeValue::Unknown;
|
|
float fCapReserve = 0;
|
|
if (szBlockIndex == 0) {
|
|
CXFA_Caption* caption = GetCaptionIfExists();
|
|
if (caption && !caption->IsHidden()) {
|
|
iCapPlacement = caption->GetPlacementType();
|
|
fCapReserve = caption->GetReserve();
|
|
}
|
|
if (iCapPlacement == XFA_AttributeValue::Top &&
|
|
fCalcHeight < fCapReserve + fTopInset) {
|
|
return 0.0f;
|
|
}
|
|
if (iCapPlacement == XFA_AttributeValue::Bottom &&
|
|
m_pLayoutData->m_fWidgetHeight - fCapReserve - fBottomInset) {
|
|
return 0.0f;
|
|
}
|
|
if (iCapPlacement != XFA_AttributeValue::Top)
|
|
fCapReserve = 0;
|
|
}
|
|
CXFA_FieldLayoutData* pFieldData = m_pLayoutData->AsFieldLayoutData();
|
|
int32_t iLinesCount = 0;
|
|
float fHeight = m_pLayoutData->m_fWidgetHeight;
|
|
if (GetValue(XFA_VALUEPICTURE_Display).IsEmpty()) {
|
|
iLinesCount = 1;
|
|
} else {
|
|
if (!pFieldData->m_pTextOut) {
|
|
CFX_SizeF size = CalculateAccWidthAndHeight(pDocView->GetDoc(),
|
|
TryWidth().value_or(0));
|
|
fHeight = size.height;
|
|
}
|
|
|
|
iLinesCount = pFieldData->m_pTextOut->GetTotalLines();
|
|
}
|
|
std::vector<float>* pFieldArray = &pFieldData->m_FieldSplitArray;
|
|
size_t szFieldSplitCount = pFieldArray->size();
|
|
if (szFieldSplitCount < szBlockIndex * 3)
|
|
return pdfium::nullopt;
|
|
|
|
for (size_t i = 0; i < szBlockIndex * 3; i += 3) {
|
|
iLinesCount -= (int32_t)(*pFieldArray)[i + 1];
|
|
fHeight -= (*pFieldArray)[i + 2];
|
|
}
|
|
if (iLinesCount == 0)
|
|
return pdfium::nullopt;
|
|
|
|
float fLineHeight = GetLineHeight();
|
|
float fFontSize = GetFontSize();
|
|
float fTextHeight = iLinesCount * fLineHeight - fLineHeight + fFontSize;
|
|
float fSpaceAbove = 0;
|
|
float fStartOffset = 0;
|
|
if (fHeight > 0.1f && szBlockIndex == 0) {
|
|
fStartOffset = fTopInset;
|
|
fHeight -= (fTopInset + fBottomInset);
|
|
CXFA_Para* para = GetParaIfExists();
|
|
if (para) {
|
|
fSpaceAbove = para->GetSpaceAbove();
|
|
float fSpaceBelow = para->GetSpaceBelow();
|
|
fHeight -= (fSpaceAbove + fSpaceBelow);
|
|
switch (para->GetVerticalAlign()) {
|
|
case XFA_AttributeValue::Top:
|
|
fStartOffset += fSpaceAbove;
|
|
break;
|
|
case XFA_AttributeValue::Middle:
|
|
fStartOffset += ((fHeight - fTextHeight) / 2 + fSpaceAbove);
|
|
break;
|
|
case XFA_AttributeValue::Bottom:
|
|
fStartOffset += (fHeight - fTextHeight + fSpaceAbove);
|
|
break;
|
|
default:
|
|
NOTREACHED();
|
|
break;
|
|
}
|
|
}
|
|
if (fStartOffset < 0.1f)
|
|
fStartOffset = 0;
|
|
}
|
|
if (szBlockIndex > 0) {
|
|
size_t i = szBlockIndex - 1;
|
|
fStartOffset = (*pFieldArray)[i * 3] - (*pFieldArray)[i * 3 + 2];
|
|
if (fStartOffset < 0.1f)
|
|
fStartOffset = 0;
|
|
}
|
|
if (szFieldSplitCount / 3 == (szBlockIndex + 1))
|
|
(*pFieldArray)[0] = fStartOffset;
|
|
else
|
|
pFieldArray->push_back(fStartOffset);
|
|
|
|
XFA_VERSION version = pDocView->GetDoc()->GetXFADoc()->GetCurVersionMode();
|
|
bool bCanSplitNoContent = false;
|
|
auto value = GetParent()->JSObject()->TryEnum(XFA_Attribute::Layout, true);
|
|
XFA_AttributeValue eLayoutMode = value.value_or(XFA_AttributeValue::Position);
|
|
if ((eLayoutMode == XFA_AttributeValue::Position ||
|
|
eLayoutMode == XFA_AttributeValue::Tb ||
|
|
eLayoutMode == XFA_AttributeValue::Row ||
|
|
eLayoutMode == XFA_AttributeValue::Table) &&
|
|
version > XFA_VERSION_208) {
|
|
bCanSplitNoContent = true;
|
|
}
|
|
if ((eLayoutMode == XFA_AttributeValue::Tb ||
|
|
eLayoutMode == XFA_AttributeValue::Row ||
|
|
eLayoutMode == XFA_AttributeValue::Table) &&
|
|
version <= XFA_VERSION_208) {
|
|
if (fStartOffset >= fCalcHeight)
|
|
return 0.0f;
|
|
|
|
bCanSplitNoContent = true;
|
|
}
|
|
if (!bCanSplitNoContent ||
|
|
fCalcHeight - fTopInset - fSpaceAbove < fLineHeight) {
|
|
return 0.0f;
|
|
}
|
|
|
|
if (fStartOffset + kXFAWidgetPrecision >= fCalcHeight) {
|
|
if (szFieldSplitCount / 3 == (szBlockIndex + 1)) {
|
|
(*pFieldArray)[szBlockIndex * 3 + 1] = 0;
|
|
(*pFieldArray)[szBlockIndex * 3 + 2] = fCalcHeight;
|
|
} else {
|
|
pFieldArray->push_back(0);
|
|
pFieldArray->push_back(fCalcHeight);
|
|
}
|
|
return pdfium::nullopt;
|
|
}
|
|
|
|
if (fCalcHeight - fStartOffset < fLineHeight) {
|
|
fCalcHeight = fStartOffset;
|
|
if (szFieldSplitCount / 3 == (szBlockIndex + 1)) {
|
|
(*pFieldArray)[szBlockIndex * 3 + 1] = 0;
|
|
(*pFieldArray)[szBlockIndex * 3 + 2] = fCalcHeight;
|
|
} else {
|
|
pFieldArray->push_back(0);
|
|
pFieldArray->push_back(fCalcHeight);
|
|
}
|
|
return fCalcHeight;
|
|
}
|
|
|
|
float fTextNum =
|
|
fCalcHeight + kXFAWidgetPrecision - fCapReserve - fStartOffset;
|
|
int32_t iLineNum =
|
|
(int32_t)((fTextNum + (fLineHeight - fFontSize)) / fLineHeight);
|
|
if (iLineNum >= iLinesCount) {
|
|
if (fCalcHeight - fStartOffset - fTextHeight >= fFontSize) {
|
|
if (szFieldSplitCount / 3 == (szBlockIndex + 1)) {
|
|
(*pFieldArray)[szBlockIndex * 3 + 1] = iLinesCount;
|
|
(*pFieldArray)[szBlockIndex * 3 + 2] = fCalcHeight;
|
|
} else {
|
|
pFieldArray->push_back(iLinesCount);
|
|
pFieldArray->push_back(fCalcHeight);
|
|
}
|
|
return pdfium::nullopt;
|
|
}
|
|
if (fHeight - fStartOffset - fTextHeight < fFontSize) {
|
|
iLineNum -= 1;
|
|
if (iLineNum == 0)
|
|
return 0.0f;
|
|
} else {
|
|
iLineNum = (int32_t)(fTextNum / fLineHeight);
|
|
}
|
|
}
|
|
if (iLineNum <= 0)
|
|
return 0.0f;
|
|
|
|
float fSplitHeight = iLineNum * fLineHeight + fCapReserve + fStartOffset;
|
|
if (szFieldSplitCount / 3 == (szBlockIndex + 1)) {
|
|
(*pFieldArray)[szBlockIndex * 3 + 1] = iLineNum;
|
|
(*pFieldArray)[szBlockIndex * 3 + 2] = fSplitHeight;
|
|
} else {
|
|
pFieldArray->push_back(iLineNum);
|
|
pFieldArray->push_back(fSplitHeight);
|
|
}
|
|
if (fabs(fSplitHeight - fCalcHeight) < kXFAWidgetPrecision)
|
|
return pdfium::nullopt;
|
|
return fSplitHeight;
|
|
}
|
|
|
|
void CXFA_Node::InitLayoutData() {
|
|
if (m_pLayoutData)
|
|
return;
|
|
|
|
switch (GetFFWidgetType()) {
|
|
case XFA_FFWidgetType::kText:
|
|
m_pLayoutData = pdfium::MakeUnique<CXFA_TextLayoutData>();
|
|
return;
|
|
case XFA_FFWidgetType::kTextEdit:
|
|
m_pLayoutData = pdfium::MakeUnique<CXFA_TextEditData>();
|
|
return;
|
|
case XFA_FFWidgetType::kImage:
|
|
m_pLayoutData = pdfium::MakeUnique<CXFA_ImageLayoutData>();
|
|
return;
|
|
case XFA_FFWidgetType::kImageEdit:
|
|
m_pLayoutData = pdfium::MakeUnique<CXFA_ImageEditData>();
|
|
return;
|
|
default:
|
|
break;
|
|
}
|
|
if (GetElementType() == XFA_Element::Field) {
|
|
m_pLayoutData = pdfium::MakeUnique<CXFA_FieldLayoutData>();
|
|
return;
|
|
}
|
|
m_pLayoutData = pdfium::MakeUnique<CXFA_WidgetLayoutData>();
|
|
}
|
|
|
|
void CXFA_Node::StartTextLayout(CXFA_FFDoc* doc,
|
|
float* pCalcWidth,
|
|
float* pCalcHeight) {
|
|
InitLayoutData();
|
|
|
|
CXFA_TextLayoutData* pTextLayoutData = m_pLayoutData->AsTextLayoutData();
|
|
pTextLayoutData->LoadText(doc, this);
|
|
|
|
CXFA_TextLayout* pTextLayout = pTextLayoutData->GetTextLayout();
|
|
float fTextHeight = 0;
|
|
if (*pCalcWidth > 0 && *pCalcHeight > 0) {
|
|
float fWidth = GetWidthWithoutMargin(*pCalcWidth);
|
|
pTextLayout->StartLayout(fWidth);
|
|
fTextHeight = *pCalcHeight;
|
|
fTextHeight = GetHeightWithoutMargin(fTextHeight);
|
|
pTextLayout->DoLayout(fTextHeight);
|
|
return;
|
|
}
|
|
if (*pCalcWidth > 0 && *pCalcHeight < 0) {
|
|
float fWidth = GetWidthWithoutMargin(*pCalcWidth);
|
|
pTextLayout->StartLayout(fWidth);
|
|
}
|
|
if (*pCalcWidth < 0 && *pCalcHeight < 0) {
|
|
Optional<float> width = TryWidth();
|
|
if (width) {
|
|
pTextLayout->StartLayout(GetWidthWithoutMargin(*width));
|
|
*pCalcWidth = *width;
|
|
} else {
|
|
float fMaxWidth = CalculateWidgetAutoWidth(pTextLayout->StartLayout(-1));
|
|
pTextLayout->StartLayout(GetWidthWithoutMargin(fMaxWidth));
|
|
*pCalcWidth = fMaxWidth;
|
|
}
|
|
}
|
|
if (m_pLayoutData->m_fWidgetHeight < 0) {
|
|
m_pLayoutData->m_fWidgetHeight = pTextLayout->GetLayoutHeight();
|
|
m_pLayoutData->m_fWidgetHeight =
|
|
CalculateWidgetAutoHeight(m_pLayoutData->m_fWidgetHeight);
|
|
}
|
|
fTextHeight = m_pLayoutData->m_fWidgetHeight;
|
|
fTextHeight = GetHeightWithoutMargin(fTextHeight);
|
|
pTextLayout->DoLayout(fTextHeight);
|
|
*pCalcHeight = m_pLayoutData->m_fWidgetHeight;
|
|
}
|
|
|
|
bool CXFA_Node::LoadCaption(CXFA_FFDoc* doc) {
|
|
InitLayoutData();
|
|
return m_pLayoutData->AsFieldLayoutData()->LoadCaption(doc, this);
|
|
}
|
|
|
|
CXFA_TextLayout* CXFA_Node::GetCaptionTextLayout() {
|
|
return m_pLayoutData
|
|
? m_pLayoutData->AsFieldLayoutData()->m_pCapTextLayout.get()
|
|
: nullptr;
|
|
}
|
|
|
|
CXFA_TextLayout* CXFA_Node::GetTextLayout() {
|
|
return m_pLayoutData ? m_pLayoutData->AsTextLayoutData()->GetTextLayout()
|
|
: nullptr;
|
|
}
|
|
|
|
RetainPtr<CFX_DIBitmap> CXFA_Node::GetImageImage() {
|
|
return m_pLayoutData ? m_pLayoutData->AsImageLayoutData()->m_pDIBitmap
|
|
: nullptr;
|
|
}
|
|
|
|
RetainPtr<CFX_DIBitmap> CXFA_Node::GetImageEditImage() {
|
|
return m_pLayoutData ? m_pLayoutData->AsFieldLayoutData()
|
|
->AsImageEditData()
|
|
->m_pDIBitmap
|
|
: nullptr;
|
|
}
|
|
|
|
void CXFA_Node::SetImageImage(const RetainPtr<CFX_DIBitmap>& newImage) {
|
|
CXFA_ImageLayoutData* pData = m_pLayoutData->AsImageLayoutData();
|
|
if (pData->m_pDIBitmap != newImage)
|
|
pData->m_pDIBitmap = newImage;
|
|
}
|
|
|
|
void CXFA_Node::SetImageEditImage(const RetainPtr<CFX_DIBitmap>& newImage) {
|
|
CXFA_ImageEditData* pData =
|
|
m_pLayoutData->AsFieldLayoutData()->AsImageEditData();
|
|
if (pData->m_pDIBitmap != newImage)
|
|
pData->m_pDIBitmap = newImage;
|
|
}
|
|
|
|
RetainPtr<CFGAS_GEFont> CXFA_Node::GetFDEFont(CXFA_FFDoc* doc) {
|
|
WideString wsFontName = L"Courier";
|
|
uint32_t dwFontStyle = 0;
|
|
CXFA_Font* font = GetFontIfExists();
|
|
if (font) {
|
|
if (font->IsBold())
|
|
dwFontStyle |= FXFONT_FORCE_BOLD;
|
|
if (font->IsItalic())
|
|
dwFontStyle |= FXFONT_ITALIC;
|
|
|
|
wsFontName = font->GetTypeface();
|
|
}
|
|
return doc->GetApp()->GetXFAFontMgr()->GetFont(doc, wsFontName.AsStringView(),
|
|
dwFontStyle);
|
|
}
|
|
|
|
bool CXFA_Node::HasButtonRollover() {
|
|
CXFA_Items* pItems = GetChild<CXFA_Items>(0, XFA_Element::Items, false);
|
|
if (!pItems)
|
|
return false;
|
|
|
|
for (CXFA_Node* pText = pItems->GetFirstChild(); pText;
|
|
pText = pText->GetNextSibling()) {
|
|
if (pText->JSObject()
|
|
->GetCData(XFA_Attribute::Name)
|
|
.EqualsASCII("rollover")) {
|
|
return !pText->JSObject()->GetContent(false).IsEmpty();
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool CXFA_Node::HasButtonDown() {
|
|
CXFA_Items* pItems = GetChild<CXFA_Items>(0, XFA_Element::Items, false);
|
|
if (!pItems)
|
|
return false;
|
|
|
|
for (CXFA_Node* pText = pItems->GetFirstChild(); pText;
|
|
pText = pText->GetNextSibling()) {
|
|
if (pText->JSObject()->GetCData(XFA_Attribute::Name).EqualsASCII("down")) {
|
|
return !pText->JSObject()->GetContent(false).IsEmpty();
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool CXFA_Node::IsRadioButton() {
|
|
CXFA_Node* pParent = GetParent();
|
|
return pParent && pParent->GetElementType() == XFA_Element::ExclGroup;
|
|
}
|
|
|
|
float CXFA_Node::GetCheckButtonSize() {
|
|
CXFA_Node* pUIChild = GetUIChildNode();
|
|
if (pUIChild) {
|
|
return pUIChild->JSObject()->GetMeasureInUnit(XFA_Attribute::Size,
|
|
XFA_Unit::Pt);
|
|
}
|
|
return CXFA_Measurement(10, XFA_Unit::Pt).ToUnit(XFA_Unit::Pt);
|
|
}
|
|
|
|
XFA_CHECKSTATE CXFA_Node::GetCheckState() {
|
|
WideString wsValue = GetRawValue();
|
|
if (wsValue.IsEmpty())
|
|
return XFA_CHECKSTATE_Off;
|
|
|
|
auto* pItems = GetChild<CXFA_Items>(0, XFA_Element::Items, false);
|
|
if (!pItems)
|
|
return XFA_CHECKSTATE_Off;
|
|
|
|
CXFA_Node* pText = pItems->GetFirstChild();
|
|
int32_t i = 0;
|
|
while (pText) {
|
|
Optional<WideString> wsContent = pText->JSObject()->TryContent(false, true);
|
|
if (wsContent && *wsContent == wsValue)
|
|
return static_cast<XFA_CHECKSTATE>(i);
|
|
|
|
i++;
|
|
pText = pText->GetNextSibling();
|
|
}
|
|
return XFA_CHECKSTATE_Off;
|
|
}
|
|
|
|
void CXFA_Node::SetCheckState(XFA_CHECKSTATE eCheckState, bool bNotify) {
|
|
CXFA_Node* node = GetExclGroupIfExists();
|
|
if (!node) {
|
|
CXFA_Items* pItems = GetChild<CXFA_Items>(0, XFA_Element::Items, false);
|
|
if (!pItems)
|
|
return;
|
|
|
|
int32_t i = -1;
|
|
CXFA_Node* pText = pItems->GetFirstChild();
|
|
WideString wsContent;
|
|
while (pText) {
|
|
i++;
|
|
if (i == eCheckState) {
|
|
wsContent = pText->JSObject()->GetContent(false);
|
|
break;
|
|
}
|
|
pText = pText->GetNextSibling();
|
|
}
|
|
SyncValue(wsContent, bNotify);
|
|
|
|
return;
|
|
}
|
|
|
|
WideString wsValue;
|
|
if (eCheckState != XFA_CHECKSTATE_Off) {
|
|
if (CXFA_Items* pItems =
|
|
GetChild<CXFA_Items>(0, XFA_Element::Items, false)) {
|
|
CXFA_Node* pText = pItems->GetFirstChild();
|
|
if (pText)
|
|
wsValue = pText->JSObject()->GetContent(false);
|
|
}
|
|
}
|
|
CXFA_Node* pChild = node->GetFirstChild();
|
|
for (; pChild; pChild = pChild->GetNextSibling()) {
|
|
if (pChild->GetElementType() != XFA_Element::Field)
|
|
continue;
|
|
|
|
CXFA_Items* pItem =
|
|
pChild->GetChild<CXFA_Items>(0, XFA_Element::Items, false);
|
|
if (!pItem)
|
|
continue;
|
|
|
|
CXFA_Node* pItemchild = pItem->GetFirstChild();
|
|
if (!pItemchild)
|
|
continue;
|
|
|
|
WideString text = pItemchild->JSObject()->GetContent(false);
|
|
WideString wsChildValue = text;
|
|
if (wsValue != text) {
|
|
pItemchild = pItemchild->GetNextSibling();
|
|
if (pItemchild)
|
|
wsChildValue = pItemchild->JSObject()->GetContent(false);
|
|
else
|
|
wsChildValue.clear();
|
|
}
|
|
pChild->SyncValue(wsChildValue, bNotify);
|
|
}
|
|
node->SyncValue(wsValue, bNotify);
|
|
}
|
|
|
|
CXFA_Node* CXFA_Node::GetSelectedMember() {
|
|
CXFA_Node* pSelectedMember = nullptr;
|
|
WideString wsState = GetRawValue();
|
|
if (wsState.IsEmpty())
|
|
return pSelectedMember;
|
|
|
|
for (CXFA_Node* pNode = ToNode(GetFirstChild()); pNode;
|
|
pNode = pNode->GetNextSibling()) {
|
|
if (pNode->GetCheckState() == XFA_CHECKSTATE_On) {
|
|
pSelectedMember = pNode;
|
|
break;
|
|
}
|
|
}
|
|
return pSelectedMember;
|
|
}
|
|
|
|
CXFA_Node* CXFA_Node::SetSelectedMember(WideStringView wsName, bool bNotify) {
|
|
uint32_t nameHash = FX_HashCode_GetW(wsName, false);
|
|
for (CXFA_Node* pNode = ToNode(GetFirstChild()); pNode;
|
|
pNode = pNode->GetNextSibling()) {
|
|
if (pNode->GetNameHash() == nameHash) {
|
|
pNode->SetCheckState(XFA_CHECKSTATE_On, bNotify);
|
|
return pNode;
|
|
}
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
void CXFA_Node::SetSelectedMemberByValue(WideStringView wsValue,
|
|
bool bNotify,
|
|
bool bScriptModify,
|
|
bool bSyncData) {
|
|
WideString wsExclGroup;
|
|
for (CXFA_Node* pNode = GetFirstChild(); pNode;
|
|
pNode = pNode->GetNextSibling()) {
|
|
if (pNode->GetElementType() != XFA_Element::Field)
|
|
continue;
|
|
|
|
CXFA_Items* pItem =
|
|
pNode->GetChild<CXFA_Items>(0, XFA_Element::Items, false);
|
|
if (!pItem)
|
|
continue;
|
|
|
|
CXFA_Node* pItemchild = pItem->GetFirstChild();
|
|
if (!pItemchild)
|
|
continue;
|
|
|
|
WideString wsChildValue = pItemchild->JSObject()->GetContent(false);
|
|
if (wsValue != wsChildValue) {
|
|
pItemchild = pItemchild->GetNextSibling();
|
|
if (pItemchild)
|
|
wsChildValue = pItemchild->JSObject()->GetContent(false);
|
|
else
|
|
wsChildValue.clear();
|
|
} else {
|
|
wsExclGroup = wsValue;
|
|
}
|
|
pNode->JSObject()->SetContent(wsChildValue, wsChildValue, bNotify,
|
|
bScriptModify, false);
|
|
}
|
|
JSObject()->SetContent(wsExclGroup, wsExclGroup, bNotify, bScriptModify,
|
|
bSyncData);
|
|
}
|
|
|
|
CXFA_Node* CXFA_Node::GetExclGroupFirstMember() {
|
|
CXFA_Node* pNode = GetFirstChild();
|
|
while (pNode) {
|
|
if (pNode->GetElementType() == XFA_Element::Field)
|
|
return pNode;
|
|
|
|
pNode = pNode->GetNextSibling();
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
CXFA_Node* CXFA_Node::GetExclGroupNextMember(CXFA_Node* pNode) {
|
|
if (!pNode)
|
|
return nullptr;
|
|
|
|
CXFA_Node* pNodeField = pNode->GetNextSibling();
|
|
while (pNodeField) {
|
|
if (pNodeField->GetElementType() == XFA_Element::Field)
|
|
return pNodeField;
|
|
|
|
pNodeField = pNodeField->GetNextSibling();
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
bool CXFA_Node::IsChoiceListCommitOnSelect() {
|
|
CXFA_Node* pUIChild = GetUIChildNode();
|
|
if (pUIChild) {
|
|
return pUIChild->JSObject()->GetEnum(XFA_Attribute::CommitOn) ==
|
|
XFA_AttributeValue::Select;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool CXFA_Node::IsChoiceListAllowTextEntry() {
|
|
CXFA_Node* pUIChild = GetUIChildNode();
|
|
return pUIChild && pUIChild->JSObject()->GetBoolean(XFA_Attribute::TextEntry);
|
|
}
|
|
|
|
bool CXFA_Node::IsChoiceListMultiSelect() {
|
|
CXFA_Node* pUIChild = GetUIChildNode();
|
|
if (pUIChild) {
|
|
return pUIChild->JSObject()->GetEnum(XFA_Attribute::Open) ==
|
|
XFA_AttributeValue::MultiSelect;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool CXFA_Node::IsListBox() {
|
|
CXFA_Node* pUIChild = GetUIChildNode();
|
|
if (!pUIChild)
|
|
return false;
|
|
|
|
XFA_AttributeValue attr = pUIChild->JSObject()->GetEnum(XFA_Attribute::Open);
|
|
return attr == XFA_AttributeValue::Always ||
|
|
attr == XFA_AttributeValue::MultiSelect;
|
|
}
|
|
|
|
int32_t CXFA_Node::CountChoiceListItems(bool bSaveValue) {
|
|
std::vector<CXFA_Node*> pItems;
|
|
int32_t iCount = 0;
|
|
for (CXFA_Node* pNode = GetFirstChild(); pNode;
|
|
pNode = pNode->GetNextSibling()) {
|
|
if (pNode->GetElementType() != XFA_Element::Items)
|
|
continue;
|
|
iCount++;
|
|
pItems.push_back(pNode);
|
|
if (iCount == 2)
|
|
break;
|
|
}
|
|
if (iCount == 0)
|
|
return 0;
|
|
|
|
CXFA_Node* pItem = pItems[0];
|
|
if (iCount > 1) {
|
|
bool bItemOneHasSave =
|
|
pItems[0]->JSObject()->GetBoolean(XFA_Attribute::Save);
|
|
bool bItemTwoHasSave =
|
|
pItems[1]->JSObject()->GetBoolean(XFA_Attribute::Save);
|
|
if (bItemOneHasSave != bItemTwoHasSave && bSaveValue == bItemTwoHasSave)
|
|
pItem = pItems[1];
|
|
}
|
|
return pItem->CountChildren(XFA_Element::Unknown, false);
|
|
}
|
|
|
|
Optional<WideString> CXFA_Node::GetChoiceListItem(int32_t nIndex,
|
|
bool bSaveValue) {
|
|
std::vector<CXFA_Node*> pItemsArray;
|
|
int32_t iCount = 0;
|
|
for (CXFA_Node* pNode = GetFirstChild(); pNode;
|
|
pNode = pNode->GetNextSibling()) {
|
|
if (pNode->GetElementType() != XFA_Element::Items)
|
|
continue;
|
|
|
|
++iCount;
|
|
pItemsArray.push_back(pNode);
|
|
if (iCount == 2)
|
|
break;
|
|
}
|
|
if (iCount == 0)
|
|
return {};
|
|
|
|
CXFA_Node* pItems = pItemsArray[0];
|
|
if (iCount > 1) {
|
|
bool bItemOneHasSave =
|
|
pItemsArray[0]->JSObject()->GetBoolean(XFA_Attribute::Save);
|
|
bool bItemTwoHasSave =
|
|
pItemsArray[1]->JSObject()->GetBoolean(XFA_Attribute::Save);
|
|
if (bItemOneHasSave != bItemTwoHasSave && bSaveValue == bItemTwoHasSave)
|
|
pItems = pItemsArray[1];
|
|
}
|
|
if (!pItems)
|
|
return {};
|
|
|
|
CXFA_Node* pItem =
|
|
pItems->GetChild<CXFA_Node>(nIndex, XFA_Element::Unknown, false);
|
|
if (pItem)
|
|
return {pItem->JSObject()->GetContent(false)};
|
|
return {};
|
|
}
|
|
|
|
std::vector<WideString> CXFA_Node::GetChoiceListItems(bool bSaveValue) {
|
|
std::vector<CXFA_Node*> items;
|
|
for (CXFA_Node* pNode = GetFirstChild(); pNode && items.size() < 2;
|
|
pNode = pNode->GetNextSibling()) {
|
|
if (pNode->GetElementType() == XFA_Element::Items)
|
|
items.push_back(pNode);
|
|
}
|
|
if (items.empty())
|
|
return std::vector<WideString>();
|
|
|
|
CXFA_Node* pItem = items.front();
|
|
if (items.size() > 1) {
|
|
bool bItemOneHasSave =
|
|
items[0]->JSObject()->GetBoolean(XFA_Attribute::Save);
|
|
bool bItemTwoHasSave =
|
|
items[1]->JSObject()->GetBoolean(XFA_Attribute::Save);
|
|
if (bItemOneHasSave != bItemTwoHasSave && bSaveValue == bItemTwoHasSave)
|
|
pItem = items[1];
|
|
}
|
|
|
|
std::vector<WideString> wsTextArray;
|
|
for (CXFA_Node* pNode = pItem->GetFirstChild(); pNode;
|
|
pNode = pNode->GetNextSibling()) {
|
|
wsTextArray.emplace_back(pNode->JSObject()->GetContent(false));
|
|
}
|
|
return wsTextArray;
|
|
}
|
|
|
|
int32_t CXFA_Node::CountSelectedItems() {
|
|
std::vector<WideString> wsValueArray = GetSelectedItemsValue();
|
|
if (IsListBox() || !IsChoiceListAllowTextEntry())
|
|
return pdfium::CollectionSize<int32_t>(wsValueArray);
|
|
|
|
int32_t iSelected = 0;
|
|
std::vector<WideString> wsSaveTextArray = GetChoiceListItems(true);
|
|
for (const auto& value : wsValueArray) {
|
|
if (pdfium::ContainsValue(wsSaveTextArray, value))
|
|
iSelected++;
|
|
}
|
|
return iSelected;
|
|
}
|
|
|
|
int32_t CXFA_Node::GetSelectedItem(int32_t nIndex) {
|
|
std::vector<WideString> wsValueArray = GetSelectedItemsValue();
|
|
if (!pdfium::IndexInBounds(wsValueArray, nIndex))
|
|
return -1;
|
|
|
|
std::vector<WideString> wsSaveTextArray = GetChoiceListItems(true);
|
|
auto it = std::find(wsSaveTextArray.begin(), wsSaveTextArray.end(),
|
|
wsValueArray[nIndex]);
|
|
return it != wsSaveTextArray.end() ? it - wsSaveTextArray.begin() : -1;
|
|
}
|
|
|
|
std::vector<int32_t> CXFA_Node::GetSelectedItems() {
|
|
std::vector<int32_t> iSelArray;
|
|
std::vector<WideString> wsValueArray = GetSelectedItemsValue();
|
|
std::vector<WideString> wsSaveTextArray = GetChoiceListItems(true);
|
|
for (const auto& value : wsValueArray) {
|
|
auto it = std::find(wsSaveTextArray.begin(), wsSaveTextArray.end(), value);
|
|
if (it != wsSaveTextArray.end())
|
|
iSelArray.push_back(it - wsSaveTextArray.begin());
|
|
}
|
|
return iSelArray;
|
|
}
|
|
|
|
std::vector<WideString> CXFA_Node::GetSelectedItemsValue() {
|
|
WideString wsValue = GetRawValue();
|
|
if (IsChoiceListMultiSelect())
|
|
return fxcrt::Split(wsValue, L'\n');
|
|
|
|
std::vector<WideString> wsSelTextArray;
|
|
wsSelTextArray.push_back(wsValue);
|
|
return wsSelTextArray;
|
|
}
|
|
|
|
bool CXFA_Node::GetItemState(int32_t nIndex) {
|
|
std::vector<WideString> wsSaveTextArray = GetChoiceListItems(true);
|
|
return pdfium::IndexInBounds(wsSaveTextArray, nIndex) &&
|
|
pdfium::ContainsValue(GetSelectedItemsValue(),
|
|
wsSaveTextArray[nIndex]);
|
|
}
|
|
|
|
void CXFA_Node::SetItemState(int32_t nIndex,
|
|
bool bSelected,
|
|
bool bNotify,
|
|
bool bScriptModify,
|
|
bool bSyncData) {
|
|
std::vector<WideString> wsSaveTextArray = GetChoiceListItems(true);
|
|
if (!pdfium::IndexInBounds(wsSaveTextArray, nIndex))
|
|
return;
|
|
|
|
int32_t iSel = -1;
|
|
std::vector<WideString> wsValueArray = GetSelectedItemsValue();
|
|
auto value_iter = std::find(wsValueArray.begin(), wsValueArray.end(),
|
|
wsSaveTextArray[nIndex]);
|
|
if (value_iter != wsValueArray.end())
|
|
iSel = value_iter - wsValueArray.begin();
|
|
|
|
if (IsChoiceListMultiSelect()) {
|
|
if (bSelected) {
|
|
if (iSel < 0) {
|
|
WideString wsValue = GetRawValue();
|
|
if (!wsValue.IsEmpty()) {
|
|
wsValue += L"\n";
|
|
}
|
|
wsValue += wsSaveTextArray[nIndex];
|
|
JSObject()->SetContent(wsValue, wsValue, bNotify, bScriptModify,
|
|
bSyncData);
|
|
}
|
|
} else if (iSel >= 0) {
|
|
std::vector<int32_t> iSelArray = GetSelectedItems();
|
|
auto selected_iter =
|
|
std::find(iSelArray.begin(), iSelArray.end(), nIndex);
|
|
if (selected_iter != iSelArray.end())
|
|
iSelArray.erase(selected_iter);
|
|
SetSelectedItems(iSelArray, bNotify, bScriptModify, bSyncData);
|
|
}
|
|
} else {
|
|
if (bSelected) {
|
|
if (iSel < 0) {
|
|
WideString wsSaveText = wsSaveTextArray[nIndex];
|
|
JSObject()->SetContent(wsSaveText, GetFormatDataValue(wsSaveText),
|
|
bNotify, bScriptModify, bSyncData);
|
|
}
|
|
} else if (iSel >= 0) {
|
|
JSObject()->SetContent(WideString(), WideString(), bNotify, bScriptModify,
|
|
bSyncData);
|
|
}
|
|
}
|
|
}
|
|
|
|
void CXFA_Node::SetSelectedItems(const std::vector<int32_t>& iSelArray,
|
|
bool bNotify,
|
|
bool bScriptModify,
|
|
bool bSyncData) {
|
|
WideString wsValue;
|
|
int32_t iSize = pdfium::CollectionSize<int32_t>(iSelArray);
|
|
if (iSize >= 1) {
|
|
std::vector<WideString> wsSaveTextArray = GetChoiceListItems(true);
|
|
WideString wsItemValue;
|
|
for (int32_t i = 0; i < iSize; i++) {
|
|
wsItemValue = (iSize == 1) ? wsSaveTextArray[iSelArray[i]]
|
|
: wsSaveTextArray[iSelArray[i]] + L"\n";
|
|
wsValue += wsItemValue;
|
|
}
|
|
}
|
|
WideString wsFormat(wsValue);
|
|
if (!IsChoiceListMultiSelect())
|
|
wsFormat = GetFormatDataValue(wsValue);
|
|
|
|
JSObject()->SetContent(wsValue, wsFormat, bNotify, bScriptModify, bSyncData);
|
|
}
|
|
|
|
void CXFA_Node::ClearAllSelections() {
|
|
CXFA_Node* pBind = GetBindData();
|
|
if (!pBind || !IsChoiceListMultiSelect()) {
|
|
SyncValue(WideString(), false);
|
|
return;
|
|
}
|
|
|
|
while (CXFA_Node* pChildNode = pBind->GetFirstChild())
|
|
pBind->RemoveChildAndNotify(pChildNode, true);
|
|
}
|
|
|
|
void CXFA_Node::InsertItem(const WideString& wsLabel,
|
|
const WideString& wsValue,
|
|
bool bNotify) {
|
|
int32_t nIndex = -1;
|
|
WideString wsNewValue(wsValue);
|
|
if (wsNewValue.IsEmpty())
|
|
wsNewValue = wsLabel;
|
|
|
|
std::vector<CXFA_Node*> listitems;
|
|
for (CXFA_Node* pItem = GetFirstChild(); pItem;
|
|
pItem = pItem->GetNextSibling()) {
|
|
if (pItem->GetElementType() == XFA_Element::Items)
|
|
listitems.push_back(pItem);
|
|
}
|
|
if (listitems.empty()) {
|
|
CXFA_Node* pItems = CreateSamePacketNode(XFA_Element::Items);
|
|
InsertChildAndNotify(-1, pItems);
|
|
InsertListTextItem(pItems, wsLabel, nIndex);
|
|
CXFA_Node* pSaveItems = CreateSamePacketNode(XFA_Element::Items);
|
|
InsertChildAndNotify(-1, pSaveItems);
|
|
pSaveItems->JSObject()->SetBoolean(XFA_Attribute::Save, true, false);
|
|
InsertListTextItem(pSaveItems, wsNewValue, nIndex);
|
|
} else if (listitems.size() > 1) {
|
|
for (int32_t i = 0; i < 2; i++) {
|
|
CXFA_Node* pNode = listitems[i];
|
|
bool bHasSave = pNode->JSObject()->GetBoolean(XFA_Attribute::Save);
|
|
if (bHasSave)
|
|
InsertListTextItem(pNode, wsNewValue, nIndex);
|
|
else
|
|
InsertListTextItem(pNode, wsLabel, nIndex);
|
|
}
|
|
} else {
|
|
CXFA_Node* pNode = listitems[0];
|
|
pNode->JSObject()->SetBoolean(XFA_Attribute::Save, false, false);
|
|
pNode->JSObject()->SetEnum(XFA_Attribute::Presence,
|
|
XFA_AttributeValue::Visible, false);
|
|
CXFA_Node* pSaveItems = CreateSamePacketNode(XFA_Element::Items);
|
|
InsertChildAndNotify(-1, pSaveItems);
|
|
pSaveItems->JSObject()->SetBoolean(XFA_Attribute::Save, true, false);
|
|
pSaveItems->JSObject()->SetEnum(XFA_Attribute::Presence,
|
|
XFA_AttributeValue::Hidden, false);
|
|
CXFA_Node* pListNode = pNode->GetFirstChild();
|
|
int32_t i = 0;
|
|
while (pListNode) {
|
|
InsertListTextItem(pSaveItems, pListNode->JSObject()->GetContent(false),
|
|
i);
|
|
++i;
|
|
|
|
pListNode = pListNode->GetNextSibling();
|
|
}
|
|
InsertListTextItem(pNode, wsLabel, nIndex);
|
|
InsertListTextItem(pSaveItems, wsNewValue, nIndex);
|
|
}
|
|
if (bNotify)
|
|
GetDocument()->GetNotify()->OnWidgetListItemAdded(this, wsLabel, nIndex);
|
|
}
|
|
|
|
WideString CXFA_Node::GetItemLabel(WideStringView wsValue) const {
|
|
std::vector<CXFA_Node*> listitems;
|
|
CXFA_Node* pItems = GetFirstChild();
|
|
for (; pItems; pItems = pItems->GetNextSibling()) {
|
|
if (pItems->GetElementType() != XFA_Element::Items)
|
|
continue;
|
|
listitems.push_back(pItems);
|
|
}
|
|
|
|
if (listitems.size() <= 1)
|
|
return WideString(wsValue);
|
|
|
|
CXFA_Node* pLabelItems = listitems[0];
|
|
bool bSave = pLabelItems->JSObject()->GetBoolean(XFA_Attribute::Save);
|
|
CXFA_Node* pSaveItems = nullptr;
|
|
if (bSave) {
|
|
pSaveItems = pLabelItems;
|
|
pLabelItems = listitems[1];
|
|
} else {
|
|
pSaveItems = listitems[1];
|
|
}
|
|
|
|
int32_t iCount = 0;
|
|
int32_t iSearch = -1;
|
|
for (CXFA_Node* pChildItem = pSaveItems->GetFirstChild(); pChildItem;
|
|
pChildItem = pChildItem->GetNextSibling()) {
|
|
if (pChildItem->JSObject()->GetContent(false) == wsValue) {
|
|
iSearch = iCount;
|
|
break;
|
|
}
|
|
iCount++;
|
|
}
|
|
if (iSearch < 0)
|
|
return WideString();
|
|
|
|
CXFA_Node* pText =
|
|
pLabelItems->GetChild<CXFA_Node>(iSearch, XFA_Element::Unknown, false);
|
|
return pText ? pText->JSObject()->GetContent(false) : WideString();
|
|
}
|
|
|
|
WideString CXFA_Node::GetItemValue(WideStringView wsLabel) {
|
|
int32_t iCount = 0;
|
|
std::vector<CXFA_Node*> listitems;
|
|
for (CXFA_Node* pItems = GetFirstChild(); pItems;
|
|
pItems = pItems->GetNextSibling()) {
|
|
if (pItems->GetElementType() != XFA_Element::Items)
|
|
continue;
|
|
iCount++;
|
|
listitems.push_back(pItems);
|
|
}
|
|
if (iCount <= 1)
|
|
return WideString(wsLabel);
|
|
|
|
CXFA_Node* pLabelItems = listitems[0];
|
|
bool bSave = pLabelItems->JSObject()->GetBoolean(XFA_Attribute::Save);
|
|
CXFA_Node* pSaveItems = nullptr;
|
|
if (bSave) {
|
|
pSaveItems = pLabelItems;
|
|
pLabelItems = listitems[1];
|
|
} else {
|
|
pSaveItems = listitems[1];
|
|
}
|
|
iCount = 0;
|
|
|
|
int32_t iSearch = -1;
|
|
WideString wsContent;
|
|
CXFA_Node* pChildItem = pLabelItems->GetFirstChild();
|
|
for (; pChildItem; pChildItem = pChildItem->GetNextSibling()) {
|
|
if (pChildItem->JSObject()->GetContent(false) == wsLabel) {
|
|
iSearch = iCount;
|
|
break;
|
|
}
|
|
iCount++;
|
|
}
|
|
if (iSearch < 0)
|
|
return WideString();
|
|
|
|
CXFA_Node* pText =
|
|
pSaveItems->GetChild<CXFA_Node>(iSearch, XFA_Element::Unknown, false);
|
|
return pText ? pText->JSObject()->GetContent(false) : WideString();
|
|
}
|
|
|
|
bool CXFA_Node::DeleteItem(int32_t nIndex, bool bNotify, bool bScriptModify) {
|
|
bool bSetValue = false;
|
|
CXFA_Node* pItems = GetFirstChild();
|
|
for (; pItems; pItems = pItems->GetNextSibling()) {
|
|
if (pItems->GetElementType() != XFA_Element::Items)
|
|
continue;
|
|
|
|
if (nIndex < 0) {
|
|
while (CXFA_Node* pNode = pItems->GetFirstChild()) {
|
|
pItems->RemoveChildAndNotify(pNode, true);
|
|
}
|
|
} else {
|
|
if (!bSetValue && pItems->JSObject()->GetBoolean(XFA_Attribute::Save)) {
|
|
SetItemState(nIndex, false, true, bScriptModify, true);
|
|
bSetValue = true;
|
|
}
|
|
int32_t i = 0;
|
|
CXFA_Node* pNode = pItems->GetFirstChild();
|
|
while (pNode) {
|
|
if (i == nIndex) {
|
|
pItems->RemoveChildAndNotify(pNode, true);
|
|
break;
|
|
}
|
|
i++;
|
|
pNode = pNode->GetNextSibling();
|
|
}
|
|
}
|
|
}
|
|
if (bNotify)
|
|
GetDocument()->GetNotify()->OnWidgetListItemRemoved(this, nIndex);
|
|
return true;
|
|
}
|
|
|
|
bool CXFA_Node::IsHorizontalScrollPolicyOff() {
|
|
CXFA_Node* pUIChild = GetUIChildNode();
|
|
if (pUIChild) {
|
|
return pUIChild->JSObject()->GetEnum(XFA_Attribute::HScrollPolicy) ==
|
|
XFA_AttributeValue::Off;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool CXFA_Node::IsVerticalScrollPolicyOff() {
|
|
CXFA_Node* pUIChild = GetUIChildNode();
|
|
if (pUIChild) {
|
|
return pUIChild->JSObject()->GetEnum(XFA_Attribute::VScrollPolicy) ==
|
|
XFA_AttributeValue::Off;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
Optional<int32_t> CXFA_Node::GetNumberOfCells() {
|
|
CXFA_Node* pUIChild = GetUIChildNode();
|
|
if (!pUIChild)
|
|
return {};
|
|
if (CXFA_Comb* pNode =
|
|
pUIChild->GetChild<CXFA_Comb>(0, XFA_Element::Comb, false))
|
|
return {pNode->JSObject()->GetInteger(XFA_Attribute::NumberOfCells)};
|
|
return {};
|
|
}
|
|
|
|
bool CXFA_Node::IsMultiLine() {
|
|
CXFA_Node* pUIChild = GetUIChildNode();
|
|
return pUIChild && pUIChild->JSObject()->GetBoolean(XFA_Attribute::MultiLine);
|
|
}
|
|
|
|
std::pair<XFA_Element, int32_t> CXFA_Node::GetMaxChars() {
|
|
if (CXFA_Value* pNode = GetChild<CXFA_Value>(0, XFA_Element::Value, false)) {
|
|
if (CXFA_Node* pChild = pNode->GetFirstChild()) {
|
|
switch (pChild->GetElementType()) {
|
|
case XFA_Element::Text:
|
|
return {XFA_Element::Text,
|
|
pChild->JSObject()->GetInteger(XFA_Attribute::MaxChars)};
|
|
case XFA_Element::ExData: {
|
|
int32_t iMax =
|
|
pChild->JSObject()->GetInteger(XFA_Attribute::MaxLength);
|
|
return {XFA_Element::ExData, iMax < 0 ? 0 : iMax};
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return {XFA_Element::Unknown, 0};
|
|
}
|
|
|
|
int32_t CXFA_Node::GetFracDigits() {
|
|
CXFA_Value* pNode = GetChild<CXFA_Value>(0, XFA_Element::Value, false);
|
|
if (!pNode)
|
|
return -1;
|
|
|
|
CXFA_Decimal* pChild =
|
|
pNode->GetChild<CXFA_Decimal>(0, XFA_Element::Decimal, false);
|
|
if (!pChild)
|
|
return -1;
|
|
|
|
return pChild->JSObject()
|
|
->TryInteger(XFA_Attribute::FracDigits, true)
|
|
.value_or(-1);
|
|
}
|
|
|
|
int32_t CXFA_Node::GetLeadDigits() {
|
|
CXFA_Value* pNode = GetChild<CXFA_Value>(0, XFA_Element::Value, false);
|
|
if (!pNode)
|
|
return -1;
|
|
|
|
CXFA_Decimal* pChild =
|
|
pNode->GetChild<CXFA_Decimal>(0, XFA_Element::Decimal, false);
|
|
if (!pChild)
|
|
return -1;
|
|
|
|
return pChild->JSObject()
|
|
->TryInteger(XFA_Attribute::LeadDigits, true)
|
|
.value_or(-1);
|
|
}
|
|
|
|
bool CXFA_Node::SetValue(XFA_VALUEPICTURE eValueType,
|
|
const WideString& wsValue) {
|
|
if (wsValue.IsEmpty()) {
|
|
SyncValue(wsValue, true);
|
|
return true;
|
|
}
|
|
|
|
SetPreNull(IsNull());
|
|
SetIsNull(false);
|
|
|
|
WideString wsNewText(wsValue);
|
|
WideString wsPicture = GetPictureContent(eValueType);
|
|
bool bValidate = true;
|
|
bool bSyncData = false;
|
|
CXFA_Node* pNode = GetUIChildNode();
|
|
if (!pNode)
|
|
return true;
|
|
|
|
XFA_Element eType = pNode->GetElementType();
|
|
if (!wsPicture.IsEmpty()) {
|
|
CXFA_LocaleMgr* pLocaleMgr = GetDocument()->GetLocaleMgr();
|
|
LocaleIface* pLocale = GetLocale();
|
|
CXFA_LocaleValue widgetValue = XFA_GetLocaleValue(this);
|
|
bValidate =
|
|
widgetValue.ValidateValue(wsValue, wsPicture, pLocale, &wsPicture);
|
|
if (bValidate) {
|
|
widgetValue = CXFA_LocaleValue(widgetValue.GetType(), wsNewText,
|
|
wsPicture, pLocale, pLocaleMgr);
|
|
wsNewText = widgetValue.GetValue();
|
|
if (eType == XFA_Element::NumericEdit)
|
|
wsNewText = NumericLimit(wsNewText);
|
|
|
|
bSyncData = true;
|
|
}
|
|
} else if (eType == XFA_Element::NumericEdit) {
|
|
if (!wsNewText.EqualsASCII("0"))
|
|
wsNewText = NumericLimit(wsNewText);
|
|
|
|
bSyncData = true;
|
|
}
|
|
if (eType != XFA_Element::NumericEdit || bSyncData)
|
|
SyncValue(wsNewText, true);
|
|
|
|
return bValidate;
|
|
}
|
|
|
|
WideString CXFA_Node::GetPictureContent(XFA_VALUEPICTURE ePicture) {
|
|
if (ePicture == XFA_VALUEPICTURE_Raw)
|
|
return WideString();
|
|
|
|
CXFA_LocaleValue widgetValue = XFA_GetLocaleValue(this);
|
|
switch (ePicture) {
|
|
case XFA_VALUEPICTURE_Display: {
|
|
if (CXFA_Format* pFormat =
|
|
GetChild<CXFA_Format>(0, XFA_Element::Format, false)) {
|
|
if (CXFA_Picture* pPicture = pFormat->GetChild<CXFA_Picture>(
|
|
0, XFA_Element::Picture, false)) {
|
|
Optional<WideString> picture =
|
|
pPicture->JSObject()->TryContent(false, true);
|
|
if (picture)
|
|
return *picture;
|
|
}
|
|
}
|
|
|
|
LocaleIface* pLocale = GetLocale();
|
|
if (!pLocale)
|
|
return WideString();
|
|
|
|
uint32_t dwType = widgetValue.GetType();
|
|
switch (dwType) {
|
|
case XFA_VT_DATE:
|
|
return pLocale->GetDatePattern(FX_LOCALEDATETIMESUBCATEGORY_Medium);
|
|
case XFA_VT_TIME:
|
|
return pLocale->GetTimePattern(FX_LOCALEDATETIMESUBCATEGORY_Medium);
|
|
case XFA_VT_DATETIME:
|
|
return pLocale->GetDatePattern(FX_LOCALEDATETIMESUBCATEGORY_Medium) +
|
|
L"T" +
|
|
pLocale->GetTimePattern(FX_LOCALEDATETIMESUBCATEGORY_Medium);
|
|
case XFA_VT_DECIMAL:
|
|
case XFA_VT_FLOAT:
|
|
default:
|
|
return WideString();
|
|
}
|
|
}
|
|
case XFA_VALUEPICTURE_Edit: {
|
|
CXFA_Ui* pUI = GetChild<CXFA_Ui>(0, XFA_Element::Ui, false);
|
|
if (pUI) {
|
|
if (CXFA_Picture* pPicture =
|
|
pUI->GetChild<CXFA_Picture>(0, XFA_Element::Picture, false)) {
|
|
Optional<WideString> picture =
|
|
pPicture->JSObject()->TryContent(false, true);
|
|
if (picture)
|
|
return *picture;
|
|
}
|
|
}
|
|
|
|
LocaleIface* pLocale = GetLocale();
|
|
if (!pLocale)
|
|
return WideString();
|
|
|
|
uint32_t dwType = widgetValue.GetType();
|
|
switch (dwType) {
|
|
case XFA_VT_DATE:
|
|
return pLocale->GetDatePattern(FX_LOCALEDATETIMESUBCATEGORY_Short);
|
|
case XFA_VT_TIME:
|
|
return pLocale->GetTimePattern(FX_LOCALEDATETIMESUBCATEGORY_Short);
|
|
case XFA_VT_DATETIME:
|
|
return pLocale->GetDatePattern(FX_LOCALEDATETIMESUBCATEGORY_Short) +
|
|
L"T" +
|
|
pLocale->GetTimePattern(FX_LOCALEDATETIMESUBCATEGORY_Short);
|
|
default:
|
|
return WideString();
|
|
}
|
|
}
|
|
case XFA_VALUEPICTURE_DataBind: {
|
|
CXFA_Bind* bind = GetBindIfExists();
|
|
if (bind)
|
|
return bind->GetPicture();
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
return WideString();
|
|
}
|
|
|
|
WideString CXFA_Node::GetValue(XFA_VALUEPICTURE eValueType) {
|
|
WideString wsValue = JSObject()->GetContent(false);
|
|
|
|
if (eValueType == XFA_VALUEPICTURE_Display)
|
|
wsValue = GetItemLabel(wsValue.AsStringView());
|
|
|
|
WideString wsPicture = GetPictureContent(eValueType);
|
|
CXFA_Node* pNode = GetUIChildNode();
|
|
if (!pNode)
|
|
return wsValue;
|
|
|
|
switch (pNode->GetElementType()) {
|
|
case XFA_Element::ChoiceList: {
|
|
if (eValueType == XFA_VALUEPICTURE_Display) {
|
|
int32_t iSelItemIndex = GetSelectedItem(0);
|
|
if (iSelItemIndex >= 0) {
|
|
wsValue =
|
|
GetChoiceListItem(iSelItemIndex, false).value_or(WideString());
|
|
wsPicture.clear();
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case XFA_Element::NumericEdit:
|
|
if (eValueType != XFA_VALUEPICTURE_Raw && wsPicture.IsEmpty()) {
|
|
LocaleIface* pLocale = GetLocale();
|
|
if (eValueType == XFA_VALUEPICTURE_Display && pLocale)
|
|
wsValue = FormatNumStr(NormalizeNumStr(wsValue), pLocale);
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
if (wsPicture.IsEmpty())
|
|
return wsValue;
|
|
|
|
if (LocaleIface* pLocale = GetLocale()) {
|
|
CXFA_LocaleValue widgetValue = XFA_GetLocaleValue(this);
|
|
CXFA_LocaleMgr* pLocaleMgr = GetDocument()->GetLocaleMgr();
|
|
switch (widgetValue.GetType()) {
|
|
case XFA_VT_DATE: {
|
|
WideString wsDate, wsTime;
|
|
if (SplitDateTime(wsValue, wsDate, wsTime)) {
|
|
CXFA_LocaleValue date(XFA_VT_DATE, wsDate, pLocaleMgr);
|
|
if (date.FormatPatterns(wsValue, wsPicture, pLocale, eValueType))
|
|
return wsValue;
|
|
}
|
|
break;
|
|
}
|
|
case XFA_VT_TIME: {
|
|
WideString wsDate, wsTime;
|
|
if (SplitDateTime(wsValue, wsDate, wsTime)) {
|
|
CXFA_LocaleValue time(XFA_VT_TIME, wsTime, pLocaleMgr);
|
|
if (time.FormatPatterns(wsValue, wsPicture, pLocale, eValueType))
|
|
return wsValue;
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
widgetValue.FormatPatterns(wsValue, wsPicture, pLocale, eValueType);
|
|
}
|
|
return wsValue;
|
|
}
|
|
|
|
WideString CXFA_Node::GetNormalizeDataValue(const WideString& wsValue) {
|
|
if (wsValue.IsEmpty())
|
|
return WideString();
|
|
|
|
WideString wsPicture = GetPictureContent(XFA_VALUEPICTURE_DataBind);
|
|
if (wsPicture.IsEmpty())
|
|
return wsValue;
|
|
|
|
CXFA_LocaleMgr* pLocaleMgr = GetDocument()->GetLocaleMgr();
|
|
LocaleIface* pLocale = GetLocale();
|
|
CXFA_LocaleValue widgetValue = XFA_GetLocaleValue(this);
|
|
if (widgetValue.ValidateValue(wsValue, wsPicture, pLocale, &wsPicture)) {
|
|
widgetValue = CXFA_LocaleValue(widgetValue.GetType(), wsValue, wsPicture,
|
|
pLocale, pLocaleMgr);
|
|
return widgetValue.GetValue();
|
|
}
|
|
return wsValue;
|
|
}
|
|
|
|
WideString CXFA_Node::GetFormatDataValue(const WideString& wsValue) {
|
|
if (wsValue.IsEmpty())
|
|
return WideString();
|
|
|
|
WideString wsPicture = GetPictureContent(XFA_VALUEPICTURE_DataBind);
|
|
if (wsPicture.IsEmpty())
|
|
return wsValue;
|
|
|
|
WideString wsFormattedValue = wsValue;
|
|
if (LocaleIface* pLocale = GetLocale()) {
|
|
CXFA_Value* pNodeValue = GetChild<CXFA_Value>(0, XFA_Element::Value, false);
|
|
if (!pNodeValue)
|
|
return wsValue;
|
|
|
|
CXFA_Node* pValueChild = pNodeValue->GetFirstChild();
|
|
if (!pValueChild)
|
|
return wsValue;
|
|
|
|
int32_t iVTType = XFA_VT_NULL;
|
|
switch (pValueChild->GetElementType()) {
|
|
case XFA_Element::Decimal:
|
|
iVTType = XFA_VT_DECIMAL;
|
|
break;
|
|
case XFA_Element::Float:
|
|
iVTType = XFA_VT_FLOAT;
|
|
break;
|
|
case XFA_Element::Date:
|
|
iVTType = XFA_VT_DATE;
|
|
break;
|
|
case XFA_Element::Time:
|
|
iVTType = XFA_VT_TIME;
|
|
break;
|
|
case XFA_Element::DateTime:
|
|
iVTType = XFA_VT_DATETIME;
|
|
break;
|
|
case XFA_Element::Boolean:
|
|
iVTType = XFA_VT_BOOLEAN;
|
|
break;
|
|
case XFA_Element::Integer:
|
|
iVTType = XFA_VT_INTEGER;
|
|
break;
|
|
case XFA_Element::Text:
|
|
iVTType = XFA_VT_TEXT;
|
|
break;
|
|
default:
|
|
iVTType = XFA_VT_NULL;
|
|
break;
|
|
}
|
|
CXFA_LocaleMgr* pLocaleMgr = GetDocument()->GetLocaleMgr();
|
|
CXFA_LocaleValue widgetValue(iVTType, wsValue, pLocaleMgr);
|
|
switch (widgetValue.GetType()) {
|
|
case XFA_VT_DATE: {
|
|
WideString wsDate, wsTime;
|
|
if (SplitDateTime(wsValue, wsDate, wsTime)) {
|
|
CXFA_LocaleValue date(XFA_VT_DATE, wsDate, pLocaleMgr);
|
|
if (date.FormatPatterns(wsFormattedValue, wsPicture, pLocale,
|
|
XFA_VALUEPICTURE_DataBind)) {
|
|
return wsFormattedValue;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case XFA_VT_TIME: {
|
|
WideString wsDate, wsTime;
|
|
if (SplitDateTime(wsValue, wsDate, wsTime)) {
|
|
CXFA_LocaleValue time(XFA_VT_TIME, wsTime, pLocaleMgr);
|
|
if (time.FormatPatterns(wsFormattedValue, wsPicture, pLocale,
|
|
XFA_VALUEPICTURE_DataBind)) {
|
|
return wsFormattedValue;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
widgetValue.FormatPatterns(wsFormattedValue, wsPicture, pLocale,
|
|
XFA_VALUEPICTURE_DataBind);
|
|
}
|
|
return wsFormattedValue;
|
|
}
|
|
|
|
WideString CXFA_Node::NormalizeNumStr(const WideString& wsValue) {
|
|
if (wsValue.IsEmpty())
|
|
return WideString();
|
|
|
|
WideString wsOutput = wsValue;
|
|
wsOutput.TrimLeft('0');
|
|
|
|
if (!wsOutput.IsEmpty() && wsOutput.Contains('.') && GetFracDigits() != -1) {
|
|
wsOutput.TrimRight(L"0");
|
|
wsOutput.TrimRight(L".");
|
|
}
|
|
if (wsOutput.IsEmpty() || wsOutput[0] == '.')
|
|
wsOutput.InsertAtFront('0');
|
|
|
|
return wsOutput;
|
|
}
|
|
|
|
void CXFA_Node::InsertListTextItem(CXFA_Node* pItems,
|
|
const WideString& wsText,
|
|
int32_t nIndex) {
|
|
CXFA_Node* pText = pItems->CreateSamePacketNode(XFA_Element::Text);
|
|
pItems->InsertChildAndNotify(nIndex, pText);
|
|
pText->JSObject()->SetContent(wsText, wsText, false, false, false);
|
|
}
|
|
|
|
WideString CXFA_Node::NumericLimit(const WideString& wsValue) {
|
|
int32_t iLead = GetLeadDigits();
|
|
int32_t iTread = GetFracDigits();
|
|
|
|
if ((iLead == -1) && (iTread == -1))
|
|
return wsValue;
|
|
|
|
WideString wsRet;
|
|
int32_t iLead_ = 0, iTread_ = -1;
|
|
int32_t iCount = wsValue.GetLength();
|
|
if (iCount == 0)
|
|
return wsValue;
|
|
|
|
int32_t i = 0;
|
|
if (wsValue[i] == L'-') {
|
|
wsRet += L'-';
|
|
i++;
|
|
}
|
|
for (; i < iCount; i++) {
|
|
wchar_t wc = wsValue[i];
|
|
if (FXSYS_IsDecimalDigit(wc)) {
|
|
if (iLead >= 0) {
|
|
iLead_++;
|
|
if (iLead_ > iLead)
|
|
return L"0";
|
|
} else if (iTread_ >= 0) {
|
|
iTread_++;
|
|
if (iTread_ > iTread) {
|
|
if (iTread != -1) {
|
|
CFGAS_Decimal wsDeci = CFGAS_Decimal(wsValue.AsStringView());
|
|
wsDeci.SetScale(iTread);
|
|
wsRet = wsDeci.ToWideString();
|
|
}
|
|
return wsRet;
|
|
}
|
|
}
|
|
} else if (wc == L'.') {
|
|
iTread_ = 0;
|
|
iLead = -1;
|
|
}
|
|
wsRet += wc;
|
|
}
|
|
return wsRet;
|
|
}
|
|
|
|
bool CXFA_Node::IsTransparent() const {
|
|
XFA_Element type = GetElementType();
|
|
return type == XFA_Element::SubformSet || type == XFA_Element::Area ||
|
|
type == XFA_Element::Proto || (IsUnnamed() && IsContainerNode());
|
|
}
|
|
|
|
bool CXFA_Node::IsProperty() const {
|
|
CXFA_Node* parent = GetParent();
|
|
return parent && parent->HasProperty(GetElementType());
|
|
}
|
|
|
|
bool CXFA_Node::PresenceRequiresSpace() const {
|
|
auto value = JSObject()->TryEnum(XFA_Attribute::Presence, true);
|
|
XFA_AttributeValue ePresence = value.value_or(XFA_AttributeValue::Visible);
|
|
return ePresence == XFA_AttributeValue::Visible ||
|
|
ePresence == XFA_AttributeValue::Invisible;
|
|
}
|
|
|
|
void CXFA_Node::SetBindingNode(CXFA_Node* node) {
|
|
binding_nodes_.clear();
|
|
if (node)
|
|
binding_nodes_.emplace_back(node);
|
|
}
|
|
|
|
void CXFA_Node::SetNodeAndDescendantsUnused() {
|
|
CXFA_NodeIterator sIterator(this);
|
|
for (CXFA_Node* pNode = sIterator.GetCurrent(); pNode;
|
|
pNode = sIterator.MoveToNext()) {
|
|
pNode->SetFlag(XFA_NodeFlag_UnusedNode);
|
|
}
|
|
}
|
|
|
|
void CXFA_Node::SetToXML(const WideString& value) {
|
|
auto* pNode = GetXMLMappingNode();
|
|
switch (pNode->GetType()) {
|
|
case CFX_XMLNode::Type::kElement: {
|
|
auto* elem = static_cast<CFX_XMLElement*>(pNode);
|
|
if (IsAttributeInXML()) {
|
|
elem->SetAttribute(JSObject()->GetCData(XFA_Attribute::QualifiedName),
|
|
value);
|
|
return;
|
|
}
|
|
|
|
bool bDeleteChildren = true;
|
|
if (GetPacketType() == XFA_PacketType::Datasets) {
|
|
for (CXFA_Node* pChildDataNode = GetFirstChild(); pChildDataNode;
|
|
pChildDataNode = pChildDataNode->GetNextSibling()) {
|
|
if (pChildDataNode->HasBindItems()) {
|
|
bDeleteChildren = false;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (bDeleteChildren)
|
|
elem->RemoveAllChildren();
|
|
|
|
auto* text = GetXMLDocument()->CreateNode<CFX_XMLText>(value);
|
|
elem->AppendLastChild(text);
|
|
break;
|
|
}
|
|
case CFX_XMLNode::Type::kText:
|
|
ToXMLText(GetXMLMappingNode())->SetText(value);
|
|
break;
|
|
default:
|
|
NOTREACHED();
|
|
}
|
|
}
|
|
|
|
CXFA_Node* CXFA_Node::GetTransparentParent() {
|
|
CXFA_Node* parent = GetParent();
|
|
while (parent) {
|
|
XFA_Element type = parent->GetElementType();
|
|
if (type == XFA_Element::Variables ||
|
|
(type != XFA_Element::SubformSet && !parent->IsUnnamed())) {
|
|
return parent;
|
|
}
|
|
parent = parent->GetParent();
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
CFX_XMLDocument* CXFA_Node::GetXMLDocument() const {
|
|
return GetDocument()->GetNotify()->GetHDOC()->GetXMLDocument();
|
|
}
|
|
|
|
// static
|
|
std::unique_ptr<CXFA_Node> CXFA_Node::Create(CXFA_Document* doc,
|
|
XFA_Element element,
|
|
XFA_PacketType packet) {
|
|
std::unique_ptr<CXFA_Node> node;
|
|
switch (element) {
|
|
case XFA_Element::Ps:
|
|
node = pdfium::MakeUnique<CXFA_Ps>(doc, packet);
|
|
break;
|
|
case XFA_Element::To:
|
|
node = pdfium::MakeUnique<CXFA_To>(doc, packet);
|
|
break;
|
|
case XFA_Element::Ui:
|
|
node = pdfium::MakeUnique<CXFA_Ui>(doc, packet);
|
|
break;
|
|
case XFA_Element::RecordSet:
|
|
node = pdfium::MakeUnique<CXFA_RecordSet>(doc, packet);
|
|
break;
|
|
case XFA_Element::SubsetBelow:
|
|
node = pdfium::MakeUnique<CXFA_SubsetBelow>(doc, packet);
|
|
break;
|
|
case XFA_Element::SubformSet:
|
|
node = pdfium::MakeUnique<CXFA_SubformSet>(doc, packet);
|
|
break;
|
|
case XFA_Element::AdobeExtensionLevel:
|
|
node = pdfium::MakeUnique<CXFA_AdobeExtensionLevel>(doc, packet);
|
|
break;
|
|
case XFA_Element::Typeface:
|
|
node = pdfium::MakeUnique<CXFA_Typeface>(doc, packet);
|
|
break;
|
|
case XFA_Element::Break:
|
|
node = pdfium::MakeUnique<CXFA_Break>(doc, packet);
|
|
break;
|
|
case XFA_Element::FontInfo:
|
|
node = pdfium::MakeUnique<CXFA_FontInfo>(doc, packet);
|
|
break;
|
|
case XFA_Element::NumberPattern:
|
|
node = pdfium::MakeUnique<CXFA_NumberPattern>(doc, packet);
|
|
break;
|
|
case XFA_Element::DynamicRender:
|
|
node = pdfium::MakeUnique<CXFA_DynamicRender>(doc, packet);
|
|
break;
|
|
case XFA_Element::PrintScaling:
|
|
node = pdfium::MakeUnique<CXFA_PrintScaling>(doc, packet);
|
|
break;
|
|
case XFA_Element::CheckButton:
|
|
node = pdfium::MakeUnique<CXFA_CheckButton>(doc, packet);
|
|
break;
|
|
case XFA_Element::DatePatterns:
|
|
node = pdfium::MakeUnique<CXFA_DatePatterns>(doc, packet);
|
|
break;
|
|
case XFA_Element::SourceSet:
|
|
node = pdfium::MakeUnique<CXFA_SourceSet>(doc, packet);
|
|
break;
|
|
case XFA_Element::Amd:
|
|
node = pdfium::MakeUnique<CXFA_Amd>(doc, packet);
|
|
break;
|
|
case XFA_Element::Arc:
|
|
node = pdfium::MakeUnique<CXFA_Arc>(doc, packet);
|
|
break;
|
|
case XFA_Element::Day:
|
|
node = pdfium::MakeUnique<CXFA_Day>(doc, packet);
|
|
break;
|
|
case XFA_Element::Era:
|
|
node = pdfium::MakeUnique<CXFA_Era>(doc, packet);
|
|
break;
|
|
case XFA_Element::Jog:
|
|
node = pdfium::MakeUnique<CXFA_Jog>(doc, packet);
|
|
break;
|
|
case XFA_Element::Log:
|
|
node = pdfium::MakeUnique<CXFA_Log>(doc, packet);
|
|
break;
|
|
case XFA_Element::Map:
|
|
node = pdfium::MakeUnique<CXFA_Map>(doc, packet);
|
|
break;
|
|
case XFA_Element::Mdp:
|
|
node = pdfium::MakeUnique<CXFA_Mdp>(doc, packet);
|
|
break;
|
|
case XFA_Element::BreakBefore:
|
|
node = pdfium::MakeUnique<CXFA_BreakBefore>(doc, packet);
|
|
break;
|
|
case XFA_Element::Oid:
|
|
node = pdfium::MakeUnique<CXFA_Oid>(doc, packet);
|
|
break;
|
|
case XFA_Element::Pcl:
|
|
node = pdfium::MakeUnique<CXFA_Pcl>(doc, packet);
|
|
break;
|
|
case XFA_Element::Pdf:
|
|
node = pdfium::MakeUnique<CXFA_Pdf>(doc, packet);
|
|
break;
|
|
case XFA_Element::Ref:
|
|
node = pdfium::MakeUnique<CXFA_Ref>(doc, packet);
|
|
break;
|
|
case XFA_Element::Uri:
|
|
node = pdfium::MakeUnique<CXFA_Uri>(doc, packet);
|
|
break;
|
|
case XFA_Element::Xdc:
|
|
node = pdfium::MakeUnique<CXFA_Xdc>(doc, packet);
|
|
break;
|
|
case XFA_Element::Xdp:
|
|
node = pdfium::MakeUnique<CXFA_Xdp>(doc, packet);
|
|
break;
|
|
case XFA_Element::Xfa:
|
|
node = pdfium::MakeUnique<CXFA_Xfa>(doc, packet);
|
|
break;
|
|
case XFA_Element::Xsl:
|
|
node = pdfium::MakeUnique<CXFA_Xsl>(doc, packet);
|
|
break;
|
|
case XFA_Element::Zpl:
|
|
node = pdfium::MakeUnique<CXFA_Zpl>(doc, packet);
|
|
break;
|
|
case XFA_Element::Cache:
|
|
node = pdfium::MakeUnique<CXFA_Cache>(doc, packet);
|
|
break;
|
|
case XFA_Element::Margin:
|
|
node = pdfium::MakeUnique<CXFA_Margin>(doc, packet);
|
|
break;
|
|
case XFA_Element::KeyUsage:
|
|
node = pdfium::MakeUnique<CXFA_KeyUsage>(doc, packet);
|
|
break;
|
|
case XFA_Element::Exclude:
|
|
node = pdfium::MakeUnique<CXFA_Exclude>(doc, packet);
|
|
break;
|
|
case XFA_Element::ChoiceList:
|
|
node = pdfium::MakeUnique<CXFA_ChoiceList>(doc, packet);
|
|
break;
|
|
case XFA_Element::Level:
|
|
node = pdfium::MakeUnique<CXFA_Level>(doc, packet);
|
|
break;
|
|
case XFA_Element::LabelPrinter:
|
|
node = pdfium::MakeUnique<CXFA_LabelPrinter>(doc, packet);
|
|
break;
|
|
case XFA_Element::CalendarSymbols:
|
|
node = pdfium::MakeUnique<CXFA_CalendarSymbols>(doc, packet);
|
|
break;
|
|
case XFA_Element::Para:
|
|
node = pdfium::MakeUnique<CXFA_Para>(doc, packet);
|
|
break;
|
|
case XFA_Element::Part:
|
|
node = pdfium::MakeUnique<CXFA_Part>(doc, packet);
|
|
break;
|
|
case XFA_Element::Pdfa:
|
|
node = pdfium::MakeUnique<CXFA_Pdfa>(doc, packet);
|
|
break;
|
|
case XFA_Element::Filter:
|
|
node = pdfium::MakeUnique<CXFA_Filter>(doc, packet);
|
|
break;
|
|
case XFA_Element::Present:
|
|
node = pdfium::MakeUnique<CXFA_Present>(doc, packet);
|
|
break;
|
|
case XFA_Element::Pagination:
|
|
node = pdfium::MakeUnique<CXFA_Pagination>(doc, packet);
|
|
break;
|
|
case XFA_Element::Encoding:
|
|
node = pdfium::MakeUnique<CXFA_Encoding>(doc, packet);
|
|
break;
|
|
case XFA_Element::Event:
|
|
node = pdfium::MakeUnique<CXFA_Event>(doc, packet);
|
|
break;
|
|
case XFA_Element::Whitespace:
|
|
node = pdfium::MakeUnique<CXFA_Whitespace>(doc, packet);
|
|
break;
|
|
case XFA_Element::DefaultUi:
|
|
node = pdfium::MakeUnique<CXFA_DefaultUi>(doc, packet);
|
|
break;
|
|
case XFA_Element::DataModel:
|
|
node = pdfium::MakeUnique<CXFA_DataModel>(doc, packet);
|
|
break;
|
|
case XFA_Element::Barcode:
|
|
node = pdfium::MakeUnique<CXFA_Barcode>(doc, packet);
|
|
break;
|
|
case XFA_Element::TimePattern:
|
|
node = pdfium::MakeUnique<CXFA_TimePattern>(doc, packet);
|
|
break;
|
|
case XFA_Element::BatchOutput:
|
|
node = pdfium::MakeUnique<CXFA_BatchOutput>(doc, packet);
|
|
break;
|
|
case XFA_Element::Enforce:
|
|
node = pdfium::MakeUnique<CXFA_Enforce>(doc, packet);
|
|
break;
|
|
case XFA_Element::CurrencySymbols:
|
|
node = pdfium::MakeUnique<CXFA_CurrencySymbols>(doc, packet);
|
|
break;
|
|
case XFA_Element::AddSilentPrint:
|
|
node = pdfium::MakeUnique<CXFA_AddSilentPrint>(doc, packet);
|
|
break;
|
|
case XFA_Element::Rename:
|
|
node = pdfium::MakeUnique<CXFA_Rename>(doc, packet);
|
|
break;
|
|
case XFA_Element::Operation:
|
|
node = pdfium::MakeUnique<CXFA_Operation>(doc, packet);
|
|
break;
|
|
case XFA_Element::Typefaces:
|
|
node = pdfium::MakeUnique<CXFA_Typefaces>(doc, packet);
|
|
break;
|
|
case XFA_Element::SubjectDNs:
|
|
node = pdfium::MakeUnique<CXFA_SubjectDNs>(doc, packet);
|
|
break;
|
|
case XFA_Element::Issuers:
|
|
node = pdfium::MakeUnique<CXFA_Issuers>(doc, packet);
|
|
break;
|
|
case XFA_Element::WsdlConnection:
|
|
node = pdfium::MakeUnique<CXFA_WsdlConnection>(doc, packet);
|
|
break;
|
|
case XFA_Element::Debug:
|
|
node = pdfium::MakeUnique<CXFA_Debug>(doc, packet);
|
|
break;
|
|
case XFA_Element::Delta:
|
|
node = pdfium::MakeUnique<CXFA_Delta>(doc, packet);
|
|
break;
|
|
case XFA_Element::EraNames:
|
|
node = pdfium::MakeUnique<CXFA_EraNames>(doc, packet);
|
|
break;
|
|
case XFA_Element::ModifyAnnots:
|
|
node = pdfium::MakeUnique<CXFA_ModifyAnnots>(doc, packet);
|
|
break;
|
|
case XFA_Element::StartNode:
|
|
node = pdfium::MakeUnique<CXFA_StartNode>(doc, packet);
|
|
break;
|
|
case XFA_Element::Button:
|
|
node = pdfium::MakeUnique<CXFA_Button>(doc, packet);
|
|
break;
|
|
case XFA_Element::Format:
|
|
node = pdfium::MakeUnique<CXFA_Format>(doc, packet);
|
|
break;
|
|
case XFA_Element::Border:
|
|
node = pdfium::MakeUnique<CXFA_Border>(doc, packet);
|
|
break;
|
|
case XFA_Element::Area:
|
|
node = pdfium::MakeUnique<CXFA_Area>(doc, packet);
|
|
break;
|
|
case XFA_Element::Hyphenation:
|
|
node = pdfium::MakeUnique<CXFA_Hyphenation>(doc, packet);
|
|
break;
|
|
case XFA_Element::Text:
|
|
node = pdfium::MakeUnique<CXFA_Text>(doc, packet);
|
|
break;
|
|
case XFA_Element::Time:
|
|
node = pdfium::MakeUnique<CXFA_Time>(doc, packet);
|
|
break;
|
|
case XFA_Element::Type:
|
|
node = pdfium::MakeUnique<CXFA_Type>(doc, packet);
|
|
break;
|
|
case XFA_Element::Overprint:
|
|
node = pdfium::MakeUnique<CXFA_Overprint>(doc, packet);
|
|
break;
|
|
case XFA_Element::Certificates:
|
|
node = pdfium::MakeUnique<CXFA_Certificates>(doc, packet);
|
|
break;
|
|
case XFA_Element::EncryptionMethods:
|
|
node = pdfium::MakeUnique<CXFA_EncryptionMethods>(doc, packet);
|
|
break;
|
|
case XFA_Element::SetProperty:
|
|
node = pdfium::MakeUnique<CXFA_SetProperty>(doc, packet);
|
|
break;
|
|
case XFA_Element::PrinterName:
|
|
node = pdfium::MakeUnique<CXFA_PrinterName>(doc, packet);
|
|
break;
|
|
case XFA_Element::StartPage:
|
|
node = pdfium::MakeUnique<CXFA_StartPage>(doc, packet);
|
|
break;
|
|
case XFA_Element::PageOffset:
|
|
node = pdfium::MakeUnique<CXFA_PageOffset>(doc, packet);
|
|
break;
|
|
case XFA_Element::DateTime:
|
|
node = pdfium::MakeUnique<CXFA_DateTime>(doc, packet);
|
|
break;
|
|
case XFA_Element::Comb:
|
|
node = pdfium::MakeUnique<CXFA_Comb>(doc, packet);
|
|
break;
|
|
case XFA_Element::Pattern:
|
|
node = pdfium::MakeUnique<CXFA_Pattern>(doc, packet);
|
|
break;
|
|
case XFA_Element::IfEmpty:
|
|
node = pdfium::MakeUnique<CXFA_IfEmpty>(doc, packet);
|
|
break;
|
|
case XFA_Element::SuppressBanner:
|
|
node = pdfium::MakeUnique<CXFA_SuppressBanner>(doc, packet);
|
|
break;
|
|
case XFA_Element::OutputBin:
|
|
node = pdfium::MakeUnique<CXFA_OutputBin>(doc, packet);
|
|
break;
|
|
case XFA_Element::Field:
|
|
node = pdfium::MakeUnique<CXFA_Field>(doc, packet);
|
|
break;
|
|
case XFA_Element::Agent:
|
|
node = pdfium::MakeUnique<CXFA_Agent>(doc, packet);
|
|
break;
|
|
case XFA_Element::OutputXSL:
|
|
node = pdfium::MakeUnique<CXFA_OutputXSL>(doc, packet);
|
|
break;
|
|
case XFA_Element::AdjustData:
|
|
node = pdfium::MakeUnique<CXFA_AdjustData>(doc, packet);
|
|
break;
|
|
case XFA_Element::AutoSave:
|
|
node = pdfium::MakeUnique<CXFA_AutoSave>(doc, packet);
|
|
break;
|
|
case XFA_Element::ContentArea:
|
|
node = pdfium::MakeUnique<CXFA_ContentArea>(doc, packet);
|
|
break;
|
|
case XFA_Element::WsdlAddress:
|
|
node = pdfium::MakeUnique<CXFA_WsdlAddress>(doc, packet);
|
|
break;
|
|
case XFA_Element::Solid:
|
|
node = pdfium::MakeUnique<CXFA_Solid>(doc, packet);
|
|
break;
|
|
case XFA_Element::DateTimeSymbols:
|
|
node = pdfium::MakeUnique<CXFA_DateTimeSymbols>(doc, packet);
|
|
break;
|
|
case XFA_Element::EncryptionLevel:
|
|
node = pdfium::MakeUnique<CXFA_EncryptionLevel>(doc, packet);
|
|
break;
|
|
case XFA_Element::Edge:
|
|
node = pdfium::MakeUnique<CXFA_Edge>(doc, packet);
|
|
break;
|
|
case XFA_Element::Stipple:
|
|
node = pdfium::MakeUnique<CXFA_Stipple>(doc, packet);
|
|
break;
|
|
case XFA_Element::Attributes:
|
|
node = pdfium::MakeUnique<CXFA_Attributes>(doc, packet);
|
|
break;
|
|
case XFA_Element::VersionControl:
|
|
node = pdfium::MakeUnique<CXFA_VersionControl>(doc, packet);
|
|
break;
|
|
case XFA_Element::Meridiem:
|
|
node = pdfium::MakeUnique<CXFA_Meridiem>(doc, packet);
|
|
break;
|
|
case XFA_Element::ExclGroup:
|
|
node = pdfium::MakeUnique<CXFA_ExclGroup>(doc, packet);
|
|
break;
|
|
case XFA_Element::ToolTip:
|
|
node = pdfium::MakeUnique<CXFA_ToolTip>(doc, packet);
|
|
break;
|
|
case XFA_Element::Compress:
|
|
node = pdfium::MakeUnique<CXFA_Compress>(doc, packet);
|
|
break;
|
|
case XFA_Element::Reason:
|
|
node = pdfium::MakeUnique<CXFA_Reason>(doc, packet);
|
|
break;
|
|
case XFA_Element::Execute:
|
|
node = pdfium::MakeUnique<CXFA_Execute>(doc, packet);
|
|
break;
|
|
case XFA_Element::ContentCopy:
|
|
node = pdfium::MakeUnique<CXFA_ContentCopy>(doc, packet);
|
|
break;
|
|
case XFA_Element::DateTimeEdit:
|
|
node = pdfium::MakeUnique<CXFA_DateTimeEdit>(doc, packet);
|
|
break;
|
|
case XFA_Element::Config:
|
|
node = pdfium::MakeUnique<CXFA_Config>(doc, packet);
|
|
break;
|
|
case XFA_Element::Image:
|
|
node = pdfium::MakeUnique<CXFA_Image>(doc, packet);
|
|
break;
|
|
case XFA_Element::SharpxHTML:
|
|
node = pdfium::MakeUnique<CXFA_SharpxHTML>(doc, packet);
|
|
break;
|
|
case XFA_Element::NumberOfCopies:
|
|
node = pdfium::MakeUnique<CXFA_NumberOfCopies>(doc, packet);
|
|
break;
|
|
case XFA_Element::BehaviorOverride:
|
|
node = pdfium::MakeUnique<CXFA_BehaviorOverride>(doc, packet);
|
|
break;
|
|
case XFA_Element::TimeStamp:
|
|
node = pdfium::MakeUnique<CXFA_TimeStamp>(doc, packet);
|
|
break;
|
|
case XFA_Element::Month:
|
|
node = pdfium::MakeUnique<CXFA_Month>(doc, packet);
|
|
break;
|
|
case XFA_Element::ViewerPreferences:
|
|
node = pdfium::MakeUnique<CXFA_ViewerPreferences>(doc, packet);
|
|
break;
|
|
case XFA_Element::ScriptModel:
|
|
node = pdfium::MakeUnique<CXFA_ScriptModel>(doc, packet);
|
|
break;
|
|
case XFA_Element::Decimal:
|
|
node = pdfium::MakeUnique<CXFA_Decimal>(doc, packet);
|
|
break;
|
|
case XFA_Element::Subform:
|
|
node = pdfium::MakeUnique<CXFA_Subform>(doc, packet);
|
|
break;
|
|
case XFA_Element::Select:
|
|
node = pdfium::MakeUnique<CXFA_Select>(doc, packet);
|
|
break;
|
|
case XFA_Element::Window:
|
|
node = pdfium::MakeUnique<CXFA_Window>(doc, packet);
|
|
break;
|
|
case XFA_Element::LocaleSet:
|
|
node = pdfium::MakeUnique<CXFA_LocaleSet>(doc, packet);
|
|
break;
|
|
case XFA_Element::Handler:
|
|
node = pdfium::MakeUnique<CXFA_Handler>(doc, packet);
|
|
break;
|
|
case XFA_Element::Presence:
|
|
node = pdfium::MakeUnique<CXFA_Presence>(doc, packet);
|
|
break;
|
|
case XFA_Element::Record:
|
|
node = pdfium::MakeUnique<CXFA_Record>(doc, packet);
|
|
break;
|
|
case XFA_Element::Embed:
|
|
node = pdfium::MakeUnique<CXFA_Embed>(doc, packet);
|
|
break;
|
|
case XFA_Element::Version:
|
|
node = pdfium::MakeUnique<CXFA_Version>(doc, packet);
|
|
break;
|
|
case XFA_Element::Command:
|
|
node = pdfium::MakeUnique<CXFA_Command>(doc, packet);
|
|
break;
|
|
case XFA_Element::Copies:
|
|
node = pdfium::MakeUnique<CXFA_Copies>(doc, packet);
|
|
break;
|
|
case XFA_Element::Staple:
|
|
node = pdfium::MakeUnique<CXFA_Staple>(doc, packet);
|
|
break;
|
|
case XFA_Element::SubmitFormat:
|
|
node = pdfium::MakeUnique<CXFA_SubmitFormat>(doc, packet);
|
|
break;
|
|
case XFA_Element::Boolean:
|
|
node = pdfium::MakeUnique<CXFA_Boolean>(doc, packet);
|
|
break;
|
|
case XFA_Element::Message:
|
|
node = pdfium::MakeUnique<CXFA_Message>(doc, packet);
|
|
break;
|
|
case XFA_Element::Output:
|
|
node = pdfium::MakeUnique<CXFA_Output>(doc, packet);
|
|
break;
|
|
case XFA_Element::PsMap:
|
|
node = pdfium::MakeUnique<CXFA_PsMap>(doc, packet);
|
|
break;
|
|
case XFA_Element::ExcludeNS:
|
|
node = pdfium::MakeUnique<CXFA_ExcludeNS>(doc, packet);
|
|
break;
|
|
case XFA_Element::Assist:
|
|
node = pdfium::MakeUnique<CXFA_Assist>(doc, packet);
|
|
break;
|
|
case XFA_Element::Picture:
|
|
node = pdfium::MakeUnique<CXFA_Picture>(doc, packet);
|
|
break;
|
|
case XFA_Element::Traversal:
|
|
node = pdfium::MakeUnique<CXFA_Traversal>(doc, packet);
|
|
break;
|
|
case XFA_Element::SilentPrint:
|
|
node = pdfium::MakeUnique<CXFA_SilentPrint>(doc, packet);
|
|
break;
|
|
case XFA_Element::WebClient:
|
|
node = pdfium::MakeUnique<CXFA_WebClient>(doc, packet);
|
|
break;
|
|
case XFA_Element::Producer:
|
|
node = pdfium::MakeUnique<CXFA_Producer>(doc, packet);
|
|
break;
|
|
case XFA_Element::Corner:
|
|
node = pdfium::MakeUnique<CXFA_Corner>(doc, packet);
|
|
break;
|
|
case XFA_Element::MsgId:
|
|
node = pdfium::MakeUnique<CXFA_MsgId>(doc, packet);
|
|
break;
|
|
case XFA_Element::Color:
|
|
node = pdfium::MakeUnique<CXFA_Color>(doc, packet);
|
|
break;
|
|
case XFA_Element::Keep:
|
|
node = pdfium::MakeUnique<CXFA_Keep>(doc, packet);
|
|
break;
|
|
case XFA_Element::Query:
|
|
node = pdfium::MakeUnique<CXFA_Query>(doc, packet);
|
|
break;
|
|
case XFA_Element::Insert:
|
|
node = pdfium::MakeUnique<CXFA_Insert>(doc, packet);
|
|
break;
|
|
case XFA_Element::ImageEdit:
|
|
node = pdfium::MakeUnique<CXFA_ImageEdit>(doc, packet);
|
|
break;
|
|
case XFA_Element::Validate:
|
|
node = pdfium::MakeUnique<CXFA_Validate>(doc, packet);
|
|
break;
|
|
case XFA_Element::DigestMethods:
|
|
node = pdfium::MakeUnique<CXFA_DigestMethods>(doc, packet);
|
|
break;
|
|
case XFA_Element::NumberPatterns:
|
|
node = pdfium::MakeUnique<CXFA_NumberPatterns>(doc, packet);
|
|
break;
|
|
case XFA_Element::PageSet:
|
|
node = pdfium::MakeUnique<CXFA_PageSet>(doc, packet);
|
|
break;
|
|
case XFA_Element::Integer:
|
|
node = pdfium::MakeUnique<CXFA_Integer>(doc, packet);
|
|
break;
|
|
case XFA_Element::SoapAddress:
|
|
node = pdfium::MakeUnique<CXFA_SoapAddress>(doc, packet);
|
|
break;
|
|
case XFA_Element::Equate:
|
|
node = pdfium::MakeUnique<CXFA_Equate>(doc, packet);
|
|
break;
|
|
case XFA_Element::FormFieldFilling:
|
|
node = pdfium::MakeUnique<CXFA_FormFieldFilling>(doc, packet);
|
|
break;
|
|
case XFA_Element::PageRange:
|
|
node = pdfium::MakeUnique<CXFA_PageRange>(doc, packet);
|
|
break;
|
|
case XFA_Element::Update:
|
|
node = pdfium::MakeUnique<CXFA_Update>(doc, packet);
|
|
break;
|
|
case XFA_Element::ConnectString:
|
|
node = pdfium::MakeUnique<CXFA_ConnectString>(doc, packet);
|
|
break;
|
|
case XFA_Element::Mode:
|
|
node = pdfium::MakeUnique<CXFA_Mode>(doc, packet);
|
|
break;
|
|
case XFA_Element::Layout:
|
|
node = pdfium::MakeUnique<CXFA_Layout>(doc, packet);
|
|
break;
|
|
case XFA_Element::Sharpxml:
|
|
node = pdfium::MakeUnique<CXFA_Sharpxml>(doc, packet);
|
|
break;
|
|
case XFA_Element::XsdConnection:
|
|
node = pdfium::MakeUnique<CXFA_XsdConnection>(doc, packet);
|
|
break;
|
|
case XFA_Element::Traverse:
|
|
node = pdfium::MakeUnique<CXFA_Traverse>(doc, packet);
|
|
break;
|
|
case XFA_Element::Encodings:
|
|
node = pdfium::MakeUnique<CXFA_Encodings>(doc, packet);
|
|
break;
|
|
case XFA_Element::Template:
|
|
node = pdfium::MakeUnique<CXFA_Template>(doc, packet);
|
|
break;
|
|
case XFA_Element::Acrobat:
|
|
node = pdfium::MakeUnique<CXFA_Acrobat>(doc, packet);
|
|
break;
|
|
case XFA_Element::ValidationMessaging:
|
|
node = pdfium::MakeUnique<CXFA_ValidationMessaging>(doc, packet);
|
|
break;
|
|
case XFA_Element::Signing:
|
|
node = pdfium::MakeUnique<CXFA_Signing>(doc, packet);
|
|
break;
|
|
case XFA_Element::Script:
|
|
node = pdfium::MakeUnique<CXFA_Script>(doc, packet);
|
|
break;
|
|
case XFA_Element::AddViewerPreferences:
|
|
node = pdfium::MakeUnique<CXFA_AddViewerPreferences>(doc, packet);
|
|
break;
|
|
case XFA_Element::AlwaysEmbed:
|
|
node = pdfium::MakeUnique<CXFA_AlwaysEmbed>(doc, packet);
|
|
break;
|
|
case XFA_Element::PasswordEdit:
|
|
node = pdfium::MakeUnique<CXFA_PasswordEdit>(doc, packet);
|
|
break;
|
|
case XFA_Element::NumericEdit:
|
|
node = pdfium::MakeUnique<CXFA_NumericEdit>(doc, packet);
|
|
break;
|
|
case XFA_Element::EncryptionMethod:
|
|
node = pdfium::MakeUnique<CXFA_EncryptionMethod>(doc, packet);
|
|
break;
|
|
case XFA_Element::Change:
|
|
node = pdfium::MakeUnique<CXFA_Change>(doc, packet);
|
|
break;
|
|
case XFA_Element::PageArea:
|
|
node = pdfium::MakeUnique<CXFA_PageArea>(doc, packet);
|
|
break;
|
|
case XFA_Element::SubmitUrl:
|
|
node = pdfium::MakeUnique<CXFA_SubmitUrl>(doc, packet);
|
|
break;
|
|
case XFA_Element::Oids:
|
|
node = pdfium::MakeUnique<CXFA_Oids>(doc, packet);
|
|
break;
|
|
case XFA_Element::Signature:
|
|
node = pdfium::MakeUnique<CXFA_Signature>(doc, packet);
|
|
break;
|
|
case XFA_Element::ADBE_JSConsole:
|
|
node = pdfium::MakeUnique<CXFA_ADBE_JSConsole>(doc, packet);
|
|
break;
|
|
case XFA_Element::Caption:
|
|
node = pdfium::MakeUnique<CXFA_Caption>(doc, packet);
|
|
break;
|
|
case XFA_Element::Relevant:
|
|
node = pdfium::MakeUnique<CXFA_Relevant>(doc, packet);
|
|
break;
|
|
case XFA_Element::FlipLabel:
|
|
node = pdfium::MakeUnique<CXFA_FlipLabel>(doc, packet);
|
|
break;
|
|
case XFA_Element::ExData:
|
|
node = pdfium::MakeUnique<CXFA_ExData>(doc, packet);
|
|
break;
|
|
case XFA_Element::DayNames:
|
|
node = pdfium::MakeUnique<CXFA_DayNames>(doc, packet);
|
|
break;
|
|
case XFA_Element::SoapAction:
|
|
node = pdfium::MakeUnique<CXFA_SoapAction>(doc, packet);
|
|
break;
|
|
case XFA_Element::DefaultTypeface:
|
|
node = pdfium::MakeUnique<CXFA_DefaultTypeface>(doc, packet);
|
|
break;
|
|
case XFA_Element::Manifest:
|
|
node = pdfium::MakeUnique<CXFA_Manifest>(doc, packet);
|
|
break;
|
|
case XFA_Element::Overflow:
|
|
node = pdfium::MakeUnique<CXFA_Overflow>(doc, packet);
|
|
break;
|
|
case XFA_Element::Linear:
|
|
node = pdfium::MakeUnique<CXFA_Linear>(doc, packet);
|
|
break;
|
|
case XFA_Element::CurrencySymbol:
|
|
node = pdfium::MakeUnique<CXFA_CurrencySymbol>(doc, packet);
|
|
break;
|
|
case XFA_Element::Delete:
|
|
node = pdfium::MakeUnique<CXFA_Delete>(doc, packet);
|
|
break;
|
|
case XFA_Element::DigestMethod:
|
|
node = pdfium::MakeUnique<CXFA_DigestMethod>(doc, packet);
|
|
break;
|
|
case XFA_Element::InstanceManager:
|
|
node = pdfium::MakeUnique<CXFA_InstanceManager>(doc, packet);
|
|
break;
|
|
case XFA_Element::EquateRange:
|
|
node = pdfium::MakeUnique<CXFA_EquateRange>(doc, packet);
|
|
break;
|
|
case XFA_Element::Medium:
|
|
node = pdfium::MakeUnique<CXFA_Medium>(doc, packet);
|
|
break;
|
|
case XFA_Element::TextEdit:
|
|
node = pdfium::MakeUnique<CXFA_TextEdit>(doc, packet);
|
|
break;
|
|
case XFA_Element::TemplateCache:
|
|
node = pdfium::MakeUnique<CXFA_TemplateCache>(doc, packet);
|
|
break;
|
|
case XFA_Element::CompressObjectStream:
|
|
node = pdfium::MakeUnique<CXFA_CompressObjectStream>(doc, packet);
|
|
break;
|
|
case XFA_Element::DataValue:
|
|
node = pdfium::MakeUnique<CXFA_DataValue>(doc, packet);
|
|
break;
|
|
case XFA_Element::AccessibleContent:
|
|
node = pdfium::MakeUnique<CXFA_AccessibleContent>(doc, packet);
|
|
break;
|
|
case XFA_Element::IncludeXDPContent:
|
|
node = pdfium::MakeUnique<CXFA_IncludeXDPContent>(doc, packet);
|
|
break;
|
|
case XFA_Element::XmlConnection:
|
|
node = pdfium::MakeUnique<CXFA_XmlConnection>(doc, packet);
|
|
break;
|
|
case XFA_Element::ValidateApprovalSignatures:
|
|
node = pdfium::MakeUnique<CXFA_ValidateApprovalSignatures>(doc, packet);
|
|
break;
|
|
case XFA_Element::SignData:
|
|
node = pdfium::MakeUnique<CXFA_SignData>(doc, packet);
|
|
break;
|
|
case XFA_Element::Packets:
|
|
node = pdfium::MakeUnique<CXFA_Packets>(doc, packet);
|
|
break;
|
|
case XFA_Element::DatePattern:
|
|
node = pdfium::MakeUnique<CXFA_DatePattern>(doc, packet);
|
|
break;
|
|
case XFA_Element::DuplexOption:
|
|
node = pdfium::MakeUnique<CXFA_DuplexOption>(doc, packet);
|
|
break;
|
|
case XFA_Element::Base:
|
|
node = pdfium::MakeUnique<CXFA_Base>(doc, packet);
|
|
break;
|
|
case XFA_Element::Bind:
|
|
node = pdfium::MakeUnique<CXFA_Bind>(doc, packet);
|
|
break;
|
|
case XFA_Element::Compression:
|
|
node = pdfium::MakeUnique<CXFA_Compression>(doc, packet);
|
|
break;
|
|
case XFA_Element::User:
|
|
node = pdfium::MakeUnique<CXFA_User>(doc, packet);
|
|
break;
|
|
case XFA_Element::Rectangle:
|
|
node = pdfium::MakeUnique<CXFA_Rectangle>(doc, packet);
|
|
break;
|
|
case XFA_Element::EffectiveOutputPolicy:
|
|
node = pdfium::MakeUnique<CXFA_EffectiveOutputPolicy>(doc, packet);
|
|
break;
|
|
case XFA_Element::ADBE_JSDebugger:
|
|
node = pdfium::MakeUnique<CXFA_ADBE_JSDebugger>(doc, packet);
|
|
break;
|
|
case XFA_Element::Acrobat7:
|
|
node = pdfium::MakeUnique<CXFA_Acrobat7>(doc, packet);
|
|
break;
|
|
case XFA_Element::Interactive:
|
|
node = pdfium::MakeUnique<CXFA_Interactive>(doc, packet);
|
|
break;
|
|
case XFA_Element::Locale:
|
|
node = pdfium::MakeUnique<CXFA_Locale>(doc, packet);
|
|
break;
|
|
case XFA_Element::CurrentPage:
|
|
node = pdfium::MakeUnique<CXFA_CurrentPage>(doc, packet);
|
|
break;
|
|
case XFA_Element::Data:
|
|
node = pdfium::MakeUnique<CXFA_Data>(doc, packet);
|
|
break;
|
|
case XFA_Element::Date:
|
|
node = pdfium::MakeUnique<CXFA_Date>(doc, packet);
|
|
break;
|
|
case XFA_Element::Desc:
|
|
node = pdfium::MakeUnique<CXFA_Desc>(doc, packet);
|
|
break;
|
|
case XFA_Element::Encrypt:
|
|
node = pdfium::MakeUnique<CXFA_Encrypt>(doc, packet);
|
|
break;
|
|
case XFA_Element::Draw:
|
|
node = pdfium::MakeUnique<CXFA_Draw>(doc, packet);
|
|
break;
|
|
case XFA_Element::Encryption:
|
|
node = pdfium::MakeUnique<CXFA_Encryption>(doc, packet);
|
|
break;
|
|
case XFA_Element::MeridiemNames:
|
|
node = pdfium::MakeUnique<CXFA_MeridiemNames>(doc, packet);
|
|
break;
|
|
case XFA_Element::Messaging:
|
|
node = pdfium::MakeUnique<CXFA_Messaging>(doc, packet);
|
|
break;
|
|
case XFA_Element::Speak:
|
|
node = pdfium::MakeUnique<CXFA_Speak>(doc, packet);
|
|
break;
|
|
case XFA_Element::DataGroup:
|
|
node = pdfium::MakeUnique<CXFA_DataGroup>(doc, packet);
|
|
break;
|
|
case XFA_Element::Common:
|
|
node = pdfium::MakeUnique<CXFA_Common>(doc, packet);
|
|
break;
|
|
case XFA_Element::Sharptext:
|
|
node = pdfium::MakeUnique<CXFA_Sharptext>(doc, packet);
|
|
break;
|
|
case XFA_Element::PaginationOverride:
|
|
node = pdfium::MakeUnique<CXFA_PaginationOverride>(doc, packet);
|
|
break;
|
|
case XFA_Element::Reasons:
|
|
node = pdfium::MakeUnique<CXFA_Reasons>(doc, packet);
|
|
break;
|
|
case XFA_Element::SignatureProperties:
|
|
node = pdfium::MakeUnique<CXFA_SignatureProperties>(doc, packet);
|
|
break;
|
|
case XFA_Element::Threshold:
|
|
node = pdfium::MakeUnique<CXFA_Threshold>(doc, packet);
|
|
break;
|
|
case XFA_Element::AppearanceFilter:
|
|
node = pdfium::MakeUnique<CXFA_AppearanceFilter>(doc, packet);
|
|
break;
|
|
case XFA_Element::Fill:
|
|
node = pdfium::MakeUnique<CXFA_Fill>(doc, packet);
|
|
break;
|
|
case XFA_Element::Font:
|
|
node = pdfium::MakeUnique<CXFA_Font>(doc, packet);
|
|
break;
|
|
case XFA_Element::Form:
|
|
node = pdfium::MakeUnique<CXFA_Form>(doc, packet);
|
|
break;
|
|
case XFA_Element::MediumInfo:
|
|
node = pdfium::MakeUnique<CXFA_MediumInfo>(doc, packet);
|
|
break;
|
|
case XFA_Element::Certificate:
|
|
node = pdfium::MakeUnique<CXFA_Certificate>(doc, packet);
|
|
break;
|
|
case XFA_Element::Password:
|
|
node = pdfium::MakeUnique<CXFA_Password>(doc, packet);
|
|
break;
|
|
case XFA_Element::RunScripts:
|
|
node = pdfium::MakeUnique<CXFA_RunScripts>(doc, packet);
|
|
break;
|
|
case XFA_Element::Trace:
|
|
node = pdfium::MakeUnique<CXFA_Trace>(doc, packet);
|
|
break;
|
|
case XFA_Element::Float:
|
|
node = pdfium::MakeUnique<CXFA_Float>(doc, packet);
|
|
break;
|
|
case XFA_Element::RenderPolicy:
|
|
node = pdfium::MakeUnique<CXFA_RenderPolicy>(doc, packet);
|
|
break;
|
|
case XFA_Element::Destination:
|
|
node = pdfium::MakeUnique<CXFA_Destination>(doc, packet);
|
|
break;
|
|
case XFA_Element::Value:
|
|
node = pdfium::MakeUnique<CXFA_Value>(doc, packet);
|
|
break;
|
|
case XFA_Element::Bookend:
|
|
node = pdfium::MakeUnique<CXFA_Bookend>(doc, packet);
|
|
break;
|
|
case XFA_Element::ExObject:
|
|
node = pdfium::MakeUnique<CXFA_ExObject>(doc, packet);
|
|
break;
|
|
case XFA_Element::OpenAction:
|
|
node = pdfium::MakeUnique<CXFA_OpenAction>(doc, packet);
|
|
break;
|
|
case XFA_Element::NeverEmbed:
|
|
node = pdfium::MakeUnique<CXFA_NeverEmbed>(doc, packet);
|
|
break;
|
|
case XFA_Element::BindItems:
|
|
node = pdfium::MakeUnique<CXFA_BindItems>(doc, packet);
|
|
break;
|
|
case XFA_Element::Calculate:
|
|
node = pdfium::MakeUnique<CXFA_Calculate>(doc, packet);
|
|
break;
|
|
case XFA_Element::Print:
|
|
node = pdfium::MakeUnique<CXFA_Print>(doc, packet);
|
|
break;
|
|
case XFA_Element::Extras:
|
|
node = pdfium::MakeUnique<CXFA_Extras>(doc, packet);
|
|
break;
|
|
case XFA_Element::Proto:
|
|
node = pdfium::MakeUnique<CXFA_Proto>(doc, packet);
|
|
break;
|
|
case XFA_Element::DSigData:
|
|
node = pdfium::MakeUnique<CXFA_DSigData>(doc, packet);
|
|
break;
|
|
case XFA_Element::Creator:
|
|
node = pdfium::MakeUnique<CXFA_Creator>(doc, packet);
|
|
break;
|
|
case XFA_Element::Connect:
|
|
node = pdfium::MakeUnique<CXFA_Connect>(doc, packet);
|
|
break;
|
|
case XFA_Element::Permissions:
|
|
node = pdfium::MakeUnique<CXFA_Permissions>(doc, packet);
|
|
break;
|
|
case XFA_Element::ConnectionSet:
|
|
node = pdfium::MakeUnique<CXFA_ConnectionSet>(doc, packet);
|
|
break;
|
|
case XFA_Element::Submit:
|
|
node = pdfium::MakeUnique<CXFA_Submit>(doc, packet);
|
|
break;
|
|
case XFA_Element::Range:
|
|
node = pdfium::MakeUnique<CXFA_Range>(doc, packet);
|
|
break;
|
|
case XFA_Element::Linearized:
|
|
node = pdfium::MakeUnique<CXFA_Linearized>(doc, packet);
|
|
break;
|
|
case XFA_Element::Packet:
|
|
node = pdfium::MakeUnique<CXFA_Packet>(doc, packet);
|
|
break;
|
|
case XFA_Element::RootElement:
|
|
node = pdfium::MakeUnique<CXFA_RootElement>(doc, packet);
|
|
break;
|
|
case XFA_Element::PlaintextMetadata:
|
|
node = pdfium::MakeUnique<CXFA_PlaintextMetadata>(doc, packet);
|
|
break;
|
|
case XFA_Element::NumberSymbols:
|
|
node = pdfium::MakeUnique<CXFA_NumberSymbols>(doc, packet);
|
|
break;
|
|
case XFA_Element::PrintHighQuality:
|
|
node = pdfium::MakeUnique<CXFA_PrintHighQuality>(doc, packet);
|
|
break;
|
|
case XFA_Element::Driver:
|
|
node = pdfium::MakeUnique<CXFA_Driver>(doc, packet);
|
|
break;
|
|
case XFA_Element::IncrementalLoad:
|
|
node = pdfium::MakeUnique<CXFA_IncrementalLoad>(doc, packet);
|
|
break;
|
|
case XFA_Element::SubjectDN:
|
|
node = pdfium::MakeUnique<CXFA_SubjectDN>(doc, packet);
|
|
break;
|
|
case XFA_Element::CompressLogicalStructure:
|
|
node = pdfium::MakeUnique<CXFA_CompressLogicalStructure>(doc, packet);
|
|
break;
|
|
case XFA_Element::IncrementalMerge:
|
|
node = pdfium::MakeUnique<CXFA_IncrementalMerge>(doc, packet);
|
|
break;
|
|
case XFA_Element::Radial:
|
|
node = pdfium::MakeUnique<CXFA_Radial>(doc, packet);
|
|
break;
|
|
case XFA_Element::Variables:
|
|
node = pdfium::MakeUnique<CXFA_Variables>(doc, packet);
|
|
break;
|
|
case XFA_Element::TimePatterns:
|
|
node = pdfium::MakeUnique<CXFA_TimePatterns>(doc, packet);
|
|
break;
|
|
case XFA_Element::EffectiveInputPolicy:
|
|
node = pdfium::MakeUnique<CXFA_EffectiveInputPolicy>(doc, packet);
|
|
break;
|
|
case XFA_Element::NameAttr:
|
|
node = pdfium::MakeUnique<CXFA_NameAttr>(doc, packet);
|
|
break;
|
|
case XFA_Element::Conformance:
|
|
node = pdfium::MakeUnique<CXFA_Conformance>(doc, packet);
|
|
break;
|
|
case XFA_Element::Transform:
|
|
node = pdfium::MakeUnique<CXFA_Transform>(doc, packet);
|
|
break;
|
|
case XFA_Element::LockDocument:
|
|
node = pdfium::MakeUnique<CXFA_LockDocument>(doc, packet);
|
|
break;
|
|
case XFA_Element::BreakAfter:
|
|
node = pdfium::MakeUnique<CXFA_BreakAfter>(doc, packet);
|
|
break;
|
|
case XFA_Element::Line:
|
|
node = pdfium::MakeUnique<CXFA_Line>(doc, packet);
|
|
break;
|
|
case XFA_Element::Source:
|
|
node = pdfium::MakeUnique<CXFA_Source>(doc, packet);
|
|
break;
|
|
case XFA_Element::Occur:
|
|
node = pdfium::MakeUnique<CXFA_Occur>(doc, packet);
|
|
break;
|
|
case XFA_Element::PickTrayByPDFSize:
|
|
node = pdfium::MakeUnique<CXFA_PickTrayByPDFSize>(doc, packet);
|
|
break;
|
|
case XFA_Element::MonthNames:
|
|
node = pdfium::MakeUnique<CXFA_MonthNames>(doc, packet);
|
|
break;
|
|
case XFA_Element::Severity:
|
|
node = pdfium::MakeUnique<CXFA_Severity>(doc, packet);
|
|
break;
|
|
case XFA_Element::GroupParent:
|
|
node = pdfium::MakeUnique<CXFA_GroupParent>(doc, packet);
|
|
break;
|
|
case XFA_Element::DocumentAssembly:
|
|
node = pdfium::MakeUnique<CXFA_DocumentAssembly>(doc, packet);
|
|
break;
|
|
case XFA_Element::NumberSymbol:
|
|
node = pdfium::MakeUnique<CXFA_NumberSymbol>(doc, packet);
|
|
break;
|
|
case XFA_Element::Tagged:
|
|
node = pdfium::MakeUnique<CXFA_Tagged>(doc, packet);
|
|
break;
|
|
case XFA_Element::Items:
|
|
node = pdfium::MakeUnique<CXFA_Items>(doc, packet);
|
|
break;
|
|
default:
|
|
NOTREACHED();
|
|
return nullptr;
|
|
}
|
|
if (!node || !node->IsValidInPacket(packet))
|
|
return nullptr;
|
|
return node;
|
|
}
|